上篇的爬虫回顾其实已经把爬虫基本上都做好了,但是我觉得一个个复制年度汇编地址也很麻烦,要从03年粘贴到16年,如果我能够再来一次循环就好了。并且,我通过浏览其他年度的某省份的工作报告,发现有些年度和省份的工作报告有分页现象。用上篇的博客做的爬虫匹配年份久的年度汇编网址的时候,发现省份的网站无法爬取,
处理后的值是空的。那么我们就要一步步地解决问题。
年份循环
按照上份的省份循环,会发现非常好解决
思路是一样的,无非就是把省份换成了年份而已
不同时期网站排版不同的兼容问题
在用上篇的爬虫处理年份比较久的年份汇编的时候发现了爬取的内容居然为空
然后查看网页内容进行对比发现,网页的排版不一样,然后逐个省份检查,发现有个不同的排版,如果进行兼容以及兼容后的数据保存的确有点棘手。
然后看着我的正则表达式我想到了一个傻办法
cities = '(北京|天津|河北|山西|内蒙古|辽宁|吉林|黑龙江|上海|江苏|浙江|安徽|福建|江西|' \
'山东|河南|湖北|湖南|广东|广西|海南|重庆|四川|贵州|云南|西藏|陕西|甘肃|青海|宁夏|新疆)'
cities = cities.decode('utf8').strip()
re.findall('"(http://www.gov.*?)".*?' + cities + '<', page, re.S)
两个不同的排版无非是后缀添加了省或者自治区,那么我不要这些省份以及自治区不就好了么
于是我的正则表达式变成了
def plar_serach_all_spider(self):
"""爬取当前工作年份中的地方政府工作报告的各省份报告超链接
爬取网页中的源代码 并进行省份与相应网址的匹配
将匹配的结果以省份为键,URL位置保存在元祖 plar_web_tuple 中
:return:None
"""
# 用来匹配省份
# 因为网站历经很多次的改版 各个时段对各个省份的叫法不一 所以给匹配带来了困难
# 例如 北京市 和 北京 都有出现过 所以需要一下方法解决
cities = '(北京市|北京|天津市|天津|河北省|河北|山西省|山西|内古|内蒙古自治区|内蒙古|辽宁省|辽宁|吉林省|吉林|' \
'黑江|黑龙江省|黑龙江|上海市|上海|江苏省|江苏|浙江省|浙江|安徽省|安徽|福建省|福建|江西省|江西|' \
'山东省|山东|河南省|河南|湖北省|湖北|湖南省|湖南|广东省|广东|广西壮族自治区|广西|海南省|海南|' \
'重庆市|重庆|四川省|四川|贵州省|贵州|云南省|云南|西藏自治区|西藏|陕西省|陕西|甘肃省|甘肃|' \
'青海省|青海|宁夏回族自治区|宁夏|新疆维吾尔自治区|新疆)'
cities = cities.decode('utf8').strip()
# 保存当前网页源码 并将干扰匹配的信息去除
page = urllib2.urlopen(self.year_dict[self.year]).read().replace(
'http://www.gov.cn/govweb/xhtml/favicon.ico', '').replace(' ', '').replace(
' ', '').decode('utf8').split(' ')
page_data = ''.join(page)
# 进行匹配
web_plar_tuple = re.findall('"(http://www.gov.*?)".*?' + cities + '<', page_data, re.S)
数据保存的时候 稍微处理一下就行
plar_web_tuple = {}
# 将匹配后的结果保存到元组中
for plar_line in web_plar_tuple:
templar = plar_line[1][0:2]
if templar == '内蒙'.decode('utf8'):
templar = '内蒙古'.decode('utf8')
if templar == '黑龙'.decode('utf8'):
templar = '黑龙江'.decode('utf8')
plar_web_tuple[templar] = plar_line[0]
# 进入省份循环
self.plar_loop(plar_web_tuple)
处理分页
一开始发现爬取的数据的文本比其他年度的文件大小小了很多,然后浏览到这个年度的省份报告网页发现网页的文字不是一页的分页处理的,这个时候就要看看有没有什么办法能够处理这个问题。通过平常浏览网页的心得,一般网站对分页对网站会有特殊的处理,果不其然,以2009年北京政府工作报告为例,从第一页http://www.gov.cn/test/2009-02/13/content_1230040.htm 跳转 下一页变成了 http://www.gov.cn/test/2009-02/13/content_1230040_2.htm 第三页则是 http://www.gov.cn/test/2009-02/13/content_1230040_3.htm
那么我可以添加一个判断,如果下一页如果存在,并且能够正常访问那么就是有分页的,把分页的数据加上再返回即可。
def page_processing(url_cut, myitems):
""" 处理分页
:param url_cut:
:param myitems:
:return:
"""
# 拥有下一页则设置为True 反之为False
next_page = True
# 爬取源码 保存
page = urllib2.urlopen(url_cut+'_2.htm').read().decode("utf8").replace(' ', '').replace(
'<strong>', '').replace('</strong>', '').replace('</br>', '')
myitems.extend(re.findall('<p.*?>(.*?[\u4e00-\u9fa5]*?.*?)</p>', page))
page_num = 3
# 直到没有下一页 否则一直循环
while next_page:
try:
page = urllib2.urlopen(url_cut + '_' + str(page_num)+'.htm').read().decode("utf8").replace(
' ', '').replace('<strong>', '').replace('</strong>', '').replace('</br>', '')
myitems.extend(re.findall('<p.*?>(.*?[\u4e00-\u9fa5]*?.*?)</p>', page))
page_num += 1
except urllib2.URLError:
next_page = False
return myitems
文件归类(分文件夹保存)
由于要处理数据,肯定是把文件分年度和分省份保存更加方便一下呀,但是我又觉得这样太麻烦了。说白了也是懒,然后我就各种查资料。
思路是通过爬取的时候我的文件命名方式是 年份省份政府工作报告 这样的,我分类的时候是把文件名进行切割,匹配所需要的字符串。
# 需要重新写
# 不涉及对类属性的操作
@staticmethod
def report_classification():
"""将文本文件归类
按年份以及月份归类 会自动创建文件夹进行分类
:return:
"""
# 调用包来使用文本复制功能
from shutil import copy as cp
# work_text 是需要粘贴的工作目录
# all_text 是需要复制的目录
# root_text是根目录
root_text = os.getcwd()
work_text = root_text + os.sep + 'report_down'
all_text = work_text + os.sep + 'all'
def cp_file(text):
"""复制文件
:param text: 需要归类的名称
:return:
"""
# 针对省份和年份做标记
if text == '省':
flag = 1
elif text == '年':
flag = 0
# 设置处理的工作目录
path = work + os.sep + '按'.decode('utf8') + text.decode('utf') + '份'.decode('utf')
# 寻找需要归类的文件
file_list = os.walk(all_text)
for file_line in file_list:
for filename in file_line[2]:
# 判断系统 Windows系统需要格外的转换
if platform.system() == 'Linux':
filename = filename.decode('utf8')
save_dir = filename.split('_')[flag]
elif platform.system() == 'Windows':
filename = filename.decode('gbk').encode('utf8')
save_dir = filename.split('_')[flag].decode('utf8')
filename = filename.decode('utf8')
else:
filename = filename.decode('utf8')
save_dir = filename.split('_')[flag]
# 若不在则新建文件夹
try:
if not os.path.exists(path + os.sep + save_dir):
os.makedirs(path + os.sep + save_dir)
except IOError:
print 'make dirs error'
# 开始复制
cp(all_text.decode('gbk') + os.sep + filename, path + os.sep + save_dir)
# Windows下需要将字符串转码
work = work_text.decode('gbk')
# 分别分类省和年的数据
cp_file('省')
cp_file('年')
print '打包完成'
结束
就这样拥有爬取以及文件归类的爬虫已经做好了