环境
- 操作系统:windows 10 x64
- 集成环境:Visual Studio Code
- Python版本:v3.10.5 64位
– 此程序需要博文 :伪造cookie爬取网站通用模块(附CSDN爬取范例) 中,download.py
模块的支持
1、环境搭建
爬取统计局需要用到几个常用的库。除此之外,由于需要下载,所以还需要用到下载模块。这里使用的是我自己编写的一个下载类,存放于modules中。关于它的源代码和使用方法,详解伪造cookie爬取网站通用模块(附CSDN爬取范例) 。
源代码:
import urllib.parse
import urllib.request
import ssl
import bs4
from modules import *
import re
import pandas
# 开启表单提取
ssl._create_default_https_context = ssl._create_unverified_context
# 定义headers,统计局不需要cookie,所以简单定义一个访问头就可以了
headers = {'Cache-Control': 'no-cache', # 将Cache-Control设置成no-cache比较稳妥
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'}
2、设置一些常用选项
设置年份的范围,以指定需要爬取的报告。最好是指定15年之前的,因为这之后统计年鉴从excel格式改成了图片格式,无法直接获取。
设置表格等宽。
# 定义需要查询的年份
choiceYear = []
for i in range(2005, 2015):
choiceYear.append(f'{i}年')
# 设置等宽
pandas.set_option('display.unicode.east_asian_width', True)
3、统计局有个网页,专门用于跳转到不同年份。可以通过这个网页获取年份对应的网址。
# 建立request
url = r'http://www.stats.gov.cn/tjsj/ndsj/'
req = urllib.request.Request(url=url, headers=headers, method="GET")
respon = urllib.request.urlopen(req)
html = respon.read().decode('utf8')
# 解析存储了年份和网址对应关系的网页部分
soul = bs4.BeautifulSoup(html, features='lxml')
urlList = soul.find_all('td', align="center", valign="middle")
# 将年份和网页的对应关系,存入字典{年:网址},并转为pandas对象
urlDict = {}
for i in urlList:
if i.a.string in choiceYear:
urlDict[i.a.string] = i.a["href"]
dfUrl = pandas.DataFrame.from_dict(data=urlDict, orient="index", columns=['网址'])
4、这一步需要基于统计局网站构建规律去获取文件存储的位置。
基本思路如下:
- 对于上面获取的每一个年鉴网址,将根目录改成left.htm,就可以获取年鉴大纲;
- 解析大纲网址,在所有<a>标签内搜索和定位需要的关键字,比如
个体就业人数
; - 对于搜索和定位到的<a>标签,调用其href属性,便获得了
个体就业人数
对应的网址 - 将网址的根目录类型改成.xls(.htm->.xls),便获取了文件存储网址(xls版本)
源代码:
for index in dfUrl.index:
# 改造value以获取网页框架内,左边框对应的值
subValue = urllib.parse.urljoin(dfUrl.loc[index, '网址'], 'left.htm')
# 对value进行访问并解析内容
subReq = urllib.request.Request(
url=subValue, headers=headers, method="GET")
subRespon = urlopen(subReq)
subHtml = subRespon.read().decode('gbk')
# 提取解析内容中存储于li标签的财政支出信息
subSoul = bs4.BeautifulSoup(subHtml, features='lxml')
pattern = re.compile('[^和]个体就业人数( *)\(')
subString = subSoul.find_all(name='a', string=pattern)[0].string
# 提取网址
subHref = subSoul.find_all(name='a', string=pattern)[0]["href"]
# 将网址资源的后缀从.htm改成.xls
subHref = subHref.replace('.htm', '.xls')
dfUrl.loc[index, '标签'] = subString
dfUrl.loc[index, '文件位置'] = urllib.parse.urljoin(
dfUrl.loc[index, '网址'], subHref)
5、下载
如果上一步顺利下来,那么就获取了每个年鉴报告的下载地址,存储于pandas.DataFrame对象的文件位置
里。这样就可以对报告进行下载。
源代码:
# 定义存储文件的位置
path = './out/'
for index in dfUrl.index:
Downunit(url=dfUrl.loc[index, '文件位置'],
path=path + index + '.xls', threadnum=3).Download()