用scrapy爬取某官网的行政处罚信息公示表,先从官网的某省市分站进行数据抓取,批量下载了行政处罚文书文档,这个过程遇到了好几个坑,下载到的文档打开后结果还是乱码的。新手上路的我,现说说难点,希望走过路过的各位大神,能够帮忙指点一下迷津,不胜感激。
目标网页及数据:
第二层网页:
第一坑:网站上右键点击可以查看到详情页的链接地址和原码,但是scrapy返回的response是空的,只有网站的框架结构代码。F12调用开发人员工具,找不到详情页的链接和内容。
绕道,使用selenium+IE,返回的browser.page_source出现了详情页的链接地址。
第二坑:对browser.page_source使用xpath无法提取详情页的链接地址,可能是browser.page_source的格式问题,无法用xpath定位,IE用F12调用开发人员工具,无法显示和复制xpath,应该是我的水平问题实在看不清那么长的代码。百度,用格式化工具我也看不清详情页的链接地址的句柄,提取路径。无奈,最后用正值表达式,两次筛选后,得到了详情页的链接地址。
['/guangzhou/129142/129159/129166/4165418/index.html']
['/guangzhou/129142/129159/129166/4161566/index.html']
['/guangzhou/129142/129159/129166/4159365/index.html']
['/guangzhou/129142/129159/129166/4158449/index.html']
['/guangzhou/129142/129159/129166/4158442/index.html']
['/guangzhou/129142/129159/129166/4158436/index.html']
['/guangzhou/129142/129159/129166/4158431/index.html']
['/guangzhou/129142/129159/129166/4158426/index.html']
['/guangzhou/129142/129159/129166/4158414/index.html']
['/guangzhou/129142/129159/129166/4155532/index.html']
进入第二层网页,同样用正值表达式,两次筛选后,得到了每一条行政处罚信息公示表的下载链接地址,添加共同部分生成完整的链接地址。
file_spider.py的代码:
from scrapy import Request
from scrapy.spiders import Spider#导入Spider类
from seaborn_file_download.items import SeabornFileDownloadItem#导入Item
from selenium import webdriver
import chardet
import io,os
import time,re
import requests
import random
class FileDownloadSpider(Spider):
#定义爬虫名称
name = 'file'
def start_requests(self):
url = "http://guangzhou.pbc.gov.cn/guangzhou/129142/129159/129166/index.html"
yield Request(url)
# 解析函数-获取第一页列表中每份处罚书的url地址
def parse(self, response):
IEdriver = "C:\Program Files\internet explorer\IEDriverServer.exe"
browser = webdriver.Ie(IEdriver)
browser.get('http://guangzhou.pbc.gov.cn/guangzhou/129142/129159/129166/index.html')
titles = re.findall(r'font class="hei12">(.*?)</a></font>',browser.page_source)
urls = []
for title in titles:
url = re.findall(r'href=\"(.*?)\" target="_blank">',title)
urls.append(url[0])
#遍历每每份处罚书的url
for i in range(len(urls)):
# 构建完整的url绝对地址
url_next = 'http://guangzhou.pbc.gov.cn'+urls[i]
print(url_next)
browser.get(url_next)#根据第一页生成的链接地址,获取第二页信息
#print(browser.page_source)
text = re.findall(r'td align="left" class="hei14jj"><p>(.*?)</a></p></td>',browser.page_source)#从第二页信息中提取每一条处罚书的链接和名称
url_next2 = re.findall(r'a href=\"(.*?)\">',text[0])#提取每一条处罚书的链接
url_down = 'http://guangzhou.pbc.gov.cn'+url_next2[0]#加上网站的链接头,构成完整的处罚书下载链接
#创建SeabornFileDownloadItem对象
item = SeabornFileDownloadItem()
#将源文件的url地址以列表的形式保存到key为file_urls的Item中
item["file_urls"] = [url_down]
yield item
settings部分的代码:
BOT_NAME = 'seaborn_file_download'
SPIDER_MODULES = ['seaborn_file_download.spiders']
NEWSPIDER_MODULE = 'seaborn_file_download.spiders'
#FEED_EXPORT_ENCODING = 'utf-8-sig'
FEED_EXPORT_ENCODING = 'gbk'
#设置用户代理USER_AGENT
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
DOWNLOAD_DELAY = 3
ITEM_PIPELINES = { 'seaborn_file_download.pipelines.SaveFilePipeline': 300,
}
items部分的代码:
import scrapy
class SeabornFileDownloadItem(scrapy.Item):
file_urls = scrapy.Field()#文件url地址
files = scrapy.Field()#文件下载信息
pipelines.py部分的代码:
class SeabornFileDownloadPipeline(object):
def process_item(self, item, spider):
return item
from scrapy.pipelines.files import FilesPipeline#导入文件管道类
from scrapy import Request
#定义新的文件管道,继承于FilesPipeline
class SaveFilePipeline(FilesPipeline):
# #构造并返回下载Request请求
#def get_media_requests(self, item, info):
# # 获取文件url,构造文件下载Request请求
# yield Request(url = item["file_urls"][0])
# #文件下载(或下载失败)后调用该方法
# def item_completed(self, results, item, info):#判断是否正确下载
# if not results[0][0]:
# raise DropItem("文件下载失败")
# #打印日志
# logger.debug("文件下载成功")
#
# return item
#设定文件名称,并返回
def file_path(self, request, response=None, info=None):
#获取文件名,并返回
return request.url.split("/")[-1]
第三坑:详情页的链接地址,每个地址打开一个新的网页,只有一条行政处罚信息公示表名称,点击行政处罚信息公示表名称可以下载一个文档。可是,不同城市发布的行政处罚信息公示表的文件类型不统一,居然包括了xls,doc,DOC,et,ET四种,即使是同一xls,打开来看,表头格式也不一定相同,给后期的数据合并,统计分析增加了更多的麻烦。
同样用正值表达式,两次筛选后,得到了每一条行政处罚信息公示表的链接地址,scrapy成功批量下载了行政处罚信息公示表的文档(只是先爬网站第一页共10条记录,第二页及后面的等数据正常后再添加)。
心中暗喜,那只是一会儿。打开下载到的文档,乱码,心将崩溃。
走过路过的各位大神,指点一下迷津,不胜感激。祝各位大神新春快乐!工作顺利!
2021-02-17 11:12:41 [scrapy.core.engine] INFO: Closing spider (finished)
2021-02-17 11:12:41 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 6244,
'downloader/request_count': 11,
'downloader/request_method_count/GET': 11,
'downloader/response_bytes': 59496,
'downloader/response_count': 11,
'downloader/response_status_count/200': 11,
'elapsed_time_seconds': 35.240309,
'file_count': 10,
'file_status_count/downloaded': 10,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2021, 2, 17, 3, 12, 41, 375626),
'item_scraped_count': 10,
'log_count/DEBUG': 123,
'log_count/INFO': 10,
'log_count/WARNING': 1,
'response_received_count': 11,
'scheduler/dequeued': 1,
'scheduler/dequeued/memory': 1,
'scheduler/enqueued': 1,
'scheduler/enqueued/memory': 1,
'start_time': datetime.datetime(2021, 2, 17, 3, 12, 6, 135317)}
2021-02-17 11:12:41 [scrapy.core.engine] INFO: Spider closed (finished)