查看原文
其他

学经济学也要敲代码——经生小白自力更生收集数据

Editor's Note

本文作者是17级经济学专业的本科生,而此文的主题是网络爬虫。实证经济学未来将越来越依赖于大数据资源和相关分析技术。作为经济学专业的学生,不仅要了解经济学理论和相关计量技术,在数据方面还要有“自己动手,丰衣足食”的决心。

The following article is from 数据Seminar Author Wallace


前言
我叫 Wallace ,目前就读于杭州某省属高校,半年前"入坑"经济学专业。经过指导老师半年的洗脑教导,我终于接受了如下事实:“在我们分析经济现象时,往往需要收集清理大量数据,特别是”新鲜活络“的互联网大数据,而python恰好能帮助我们规范(快速)爬取网站的数据。(what? 我是不是填错志愿进入经济统计?)”
于是,在完成专业要求的课程学习之外,上学期我被逼着邀请参加导师(多次下意识反复确认之后,确信导师和我都在经济学专业而不是经济统计专业学习/任课)主持的大数据开发创业公司的python爬虫培训。仗着本人自以为不错的数学功底和逻辑思维能力(是的,我超棒!),我还是撑到了最后。
猜猜哪个是我👆
暑假是我们几个学员正式发挥的时候。我的第一个爬虫任务是,(友好地)爬取海关网站的部分月度统计数据,并对杂乱的html文件按照文件名进行分类。这篇文章记录了我在第一次爬虫实战中的经历和心得体会。特别推荐给非专业出身的爬虫"小白"们,任何技术问题,都是"纸老虎"!

数据概览与总体思路

下图是需要爬取的月度进出口统计数据,一共有11页103个条目,而每个条目中都包含了一张表格。总的思路是,先写出爬取单个页面的代码,再通过chrome内核进行连续爬虫,最后保存进csv文件中。
#调用所需要的库import pandas as pd
import requests
import os
html=requests.get('http://www.customs.gov.cn/customs/302249/302274/302278/302280/2546702/index.html')  #向目标网站发起请求
df = pd.read_html(html.text,skiprows=3)[-1]  # 取返回列表中的最后一个表格
df.columns = ['Year&Month', 'Total', ' Export', ' Import', 'Balance',               '1to12 total','1to12 export','1to12 import','1to12 balance'] print(df)
左右滑动查看更多
在上述代码中,skiprows的作用就是在爬取表格的时候把不需要的行给去掉。我们需要的内容是下图方框内的数据,因此要把表格的前三行给去掉,所以这里的skiprows=3。
那么,如何将爬取的数据保存到csv文件呢?
df.to_csv(r'E:\月度数据.csv',encoding='utf_8_sig', mode='a', sep=",", header=not os.path.exists(r'E:\月度数据.csv'),index=False)
左右滑动查看更多
在技术部大佬的指导下,通过上述代码即可把所获取的数据保存到csv文件。
to_csv()是DataFrame类的方法,header决定了是否保留列名。如果我们要输出的文件存在,即not os.path.exists(r'E:\月度数据.csv')为False,就不保存DataFrame的header。
此处需要注意编码方式:encoding='utf_8_sig',刚开始我采用的编码方式是encoding='utf-8',excel打开输出的csv结果为乱码,是因为excel需要BOM来识别'utf-8'的文件,所以将'utf_8'改为'utf_8_sig'后就不会出现乱码的情况了。
utf-8以字节为编码单元,它的字节顺序在所有系统中都是一样的,没有字节序的问题,也因此它实际上并不需要BOM(“ByteOrder Mark”), 但是utf-8 with BOM即utf_8_sig需要提供BOM("ByteOrder Mark")。
接下来可以采用selenium进行爬虫。

一、准备工作
在爬虫之前,我们要先做一些准备工作。
首先,在命令行当中安装selenium框架,安装步骤非常简单,命令为:pip install selenium
这是已经安装完成的显示。
接着,我们要下载安装浏览器的驱动ChromeDriver,因为selenium就是像用户一样去操作浏览器,是需要浏览器的驱动的。
下载链接:https://sites.google.com/a/chromium.org/chromedriver/downloads
输入浏览器内核路径:
engine_path = r'D:/Users/hong/Desktop/chromedriver_win32.exe'
左右滑动查看更多
然后,我们调用所需要的第三方库,并且调用浏览器
import selenium.webdriver as webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import time
import traceback
import codecs
import re
import pandas as pd
import random
import os
import requests
左右滑动查看更多
如果没有安装这些库,则需要手动安装一下,代码为pip install + 库的名称

二、选择元素
完成以上准备工作,我们可以正式进入正题了,再提醒下,任务是爬取海关总署网站上月度数据部分的所有表格内容。
首先我们通过F12查看网站的HTML代码,然后点击页面元素选择按钮,接着点击需定位的元素,最后查看定位元素的源代码。具体流程如下图所示。
通过上图的流程,我们可以通过Xpath定位页面中的标签
page_xpath = '//*[@id="708ff4f3b78e4b29a3b73c4fe3b64f3a"]'
左右滑动查看更多
用同样的方法可以获得第一行条目的位置:
row_xpath = '//*[@id="708ff4f3b78e4b29a3b73c4fe3b64f3a"]/div/ul/li[1]/a'
左右滑动查看更多
第二行条目:
row_xpath = '//*[@id="708ff4f3b78e4b29a3b73c4fe3b64f3a"]/div/ul/li[2]/a'
左右滑动查看更多
后面几行的row_xpath也是通过这种方式获得,我们可以发现每一行row_xpath存在规律,即只有li[]中的数字会随行数发生变化,因此可以利用format()写出row_xpath的通式:
row_xpath = '//*[@id="708ff4f3b78e4b29a3b73c4fe3b64f3a"]/div/ul/li[{}]/a'.format(row_num)
左右滑动查看更多
接着就可以定位到该元素:
element_list = driver.find_elements_by_xpath(row_xpath)
左右滑动查看更多


三、页面操作
在定位到页面的元素之后,我们要对该元素进行一些操作,这里需要去点击每一行和“下一页”按钮,鼠标左击代码如下。
driver.find_element_by_xpath(row_xpath).click() #点击进入详情页
driver.switch_to.window(driver.window_handles[-1]) #点击每一行的详情页后都会弹出新的一页,所以需要进行窗口切换到弹出页
driver.find_element_by_xpath(page_xpath).click() #点击下一页翻页
左右滑动查看更多

四、设置等待时间
为了保证程序运行的稳定性,我们需要添加等待时间。
我们采用WebDriverWait()的方法,即在设规定的时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超出规定时间还未检测到页面元素则报错。
bool_func = lambda x: driver.find_elements_by_xpath(page_xpath)
webdriver.support.wait.WebDriverWait(driver, 20).until(bool_func)#确定需要的页面打开完毕,规定时间为20秒
左右滑动查看更多


五、其它操作
除了上述四个重要的步骤,我们还会用到一些关于页面和标题的操作。
title = driver.title #获取网页标题driver.get(root_url)#请求页面
print(driver.current_url) #输出当前的
urldriver.close()#关闭页面
driver.quit()#关闭浏览器
左右滑动查看更多


六、完整代码
import selenium.webdriver as webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import time
import traceback
import codecs
import re
import pandas as pd
import random
import os
import requests# 浏览器内核路径engine_path = r'D:/Users/hong/Desktop/chromedriver_win32.exe'# 初始urlroot_url = 'http://www.customs.gov.cn/eportal/ui?pageId=302280¤tPage=5&moduleId=708ff4f3b78e4b29a3b73c4fe3b64f3a&staticRequest=yes'#配置虚拟浏览器options = webdriver.ChromeOptions()
options.add_argument("--headless")


driver = webdriver.Chrome(executable_path=engine_path, options=options)
driver.set_window_size(1920, 1080) # 主要为了方便做屏幕截图


driver.get(root_url)
page_xpath = '//*[@id="708ff4f3b78e4b29a3b73c4fe3b64f3a"]' #从网页中获取页面的xpath


bool_func = lambda x: driver.find_elements_by_xpath(page_xpath)
webdriver.support.wait.WebDriverWait(driver, 20).until(bool_func)


row_num = 1
page_num = 1 #从第一页第一行开始
num = 1
while True:    page_xpath = '//*[@id="708ff4f3b78e4b29a3b73c4fe3b64f3a"]'    bool_func = lambda x: driver.find_elements_by_xpath(page_xpath) webdriver.support.wait.WebDriverWait(driver, 20).until(bool_func) row_xpath = '//*[@id="708ff4f3b78e4b29a3b73c4fe3b64f3a"]/div/ul/li[{}]/a'.format(row_num)#每一行的xpath都带有规律 element_list = driver.find_elements_by_xpath(row_xpath) if element_list:
element_list[0].click() #点击进入详情页 driver.switch_to.window(driver.window_handles[-1]) #浏览器中,进入详情页要翻页,所以要更换浏览器标签页。 # 确定我们需要的页面打开完毕 bool_func = lambda x: driver.find_elements_by_id('easysiteText') webdriver.support.wait.WebDriverWait(driver, 20).until(bool_func) title = driver.title html = driver.page_source df = pd.read_html(html.text,skiprows=3)[-1] # 取返回列表中的最后一个表格 df.columns = ['Year&Month', 'Total', ' Export', ' Import', 'Balance', '1to12 total', '1to12 export', '1to12 import', '1to12 balance'] df.to_csv(r'E:/{}{}.csv'.fromat(title,random.randint(1,10)),encoding='utf_8_sig', mode='a', sep=",",index=False) time.sleep(1) print(num) print(driver.current_url) driver.close() driver.switch_to.window(driver.window_handles[-1]) num = num + 1 row_num = row_num + 1 else:
        page_xpath = '//*[@id="708ff4f3b78e4b29a3b73c4fe3b64f3a"]/div/div/div[1]/a[3]'   #下一页的xpath                driver.find_element_by_xpath(page_xpath).click()   #点击下一页翻页                row_num = 1                        page_num = page_num + 1
左右滑动查看更多
以上就是通过selenium方法爬取网页的代码,简而言之有如下三大步骤:
1、构造url;
2、使用 selenuim 库控制浏览器访问url;
3、页面加载完成后提取响应数据。
推荐selenium学习网站:
https://blog.csdn.net/xie_0723/article/details/51437650
https://blog.csdn.net/aman1111/article/details/82049739


结语
以上就是经生小白Wallace用python爬取海关总署数据并分类的内容。
虽然之前受过爬虫的培训,但是听大佬们培训和轮到自己亲手实操完全是两种不同的心境,有时我所想的流程框架却不能用代码来实现(其实就是水平不够啦),在爬虫的过程中主要让我头痛的是正则表达式的书写和xpath的定位,还有一些让人摸不着头脑的报错。
随着对爬虫不断的学习和实践,我也越发感觉爬虫并不是件简单的事,同时python中还有很多值得我去发掘的模块。记得小刘老师曾经说过:“python主要是多练,光看视频不亲手操作是没有用的。”不积跬步无以至千里,经生小白Wallace一定会努力成为一名富有实战经验的经济学专业学者!





End



美滋滋教室

分享-学习-提高



👏欢迎 长按二维码添加关注👏


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存