本程序用于爬取各省(或许会增加到市)卫健委关于疫情的新闻报道。
程序规定了一个Manger-Crawler的管理架构,在一个Crawler实例完成对一个url的爬取,Manger统一管理所有crawler,用协程的方法定时爬取(目前采用一分钟一次的爬取频率),每次爬取最新的新闻,如果与记录中的最新新闻不同且标题有关键词,则进行汇报。
为了便于编写对不同的url的爬取,我采用外部json配置的方法进行管理,在config
文件夹中有目前已经完成的<地名>.json
文件,格式样例如下:
{
"name": "Pingxiang",
"Chinese_name": "萍乡",
"province": "江西",
"url": "http://wjw.pingxiang.gov.cn/news/class/?133.html",
"parser_name": "title_in_text_href_in_attr",
"code": "utf-8",
"search_path": [
{
"name": "div",
"id": "newsquery"
},
{
"name": "a"
}
]
}
其中name
是地名的官方英文(实际上大多是拼音,目前用于log输出),Chinese_name
是中文地名(用于发邮件),url
是爬取目标的网址,parser_name
是从目标结点解析出新闻标题与链接的函数名(该部分函数统一编写、管理),search_path
是一个从html解析树根部向下找到最新新闻标题的路径(实际路径往往可以压缩到2~3段,设置路径时请自行用BeautifulSoup进行验证),code
是手动指明网站编码(这是附加项,通常会自动推断,仅当自动推断导致乱码时可以考虑使用这个)。
目前需要将各个网站添加到解析范围中,主要是添加本部分内容。
parser
模块中给出了若干解析函数,由于此时已经解析到一个具体的结点,实际上获取数据应该只需要从该结点标签、文本中获取,目前给出了三个函数,如果遇到不能cover的情况再行添加(如专门添加的chongqing_parser
),万一有需要的话,对于某些特殊网站可以考虑直接把所有数据传到专用解析函数里进行针对性解析。
可以自行实现汇报方法,继承reporter.BasicReporter
,实现process(self, messages)
函数即可。
目前提供了PrintReporter
、EmailReporter
和PointReporter
三个子类:
PrintReporter
:会将更新信息打印到标准输出,主要用于配置好json后调试。EmailReporter
:后者会根据配置文件(默认为email.json
)登录163邮箱并发给列表中的目标。PointReport
:点到点的邮件通知,根据配置文件(默认为point.json
)将每一个爬到的结果定向发给设定的邮箱列表(即可直接写一个字符串作为唯一接收者,也可以写一个列表指定多个接收者)。
目前正在陆续添加各地级市的json配置以完成爬取。
-
如何设计search_path?
可以使用chrome的检查元素功能查看新闻标题外层包含的tag。但是应当注意这并不代表就能找对结果,一方面从浏览器看到的网页并不一定是get请求直接获得的(应从network里查看直接获取的结果),另一方面可能实际上有些地方有并列相同tag会形成歧义从而找错位置。实际操作时请务必用Python验证无误后再提交配置。
-
如果无法设计合理的search_path或者链接与标题不再一个tag怎么办?
这种情况属于需要针对解决的情况,可以先将tag定位到一个较小范围,然后写一个parse函数用BeatifulSoup的方法专门解析它。现在在
crawler.parser.py
中已经有了部分解析函数,可以参考chongqing_parser
。 -
遇到
![CDATA[]]
式结构怎么办?有时候可以换个网页来避开问题(某些省份新闻索引里有该结构,但是卫健委主页没有)。如果无法避开就先采用2中的办法定位到一个较小范围,再用正则表达式匹配出需要的部分。
-
如果遇到返回结果是JavaScript脚本与网页混编,新闻标题与链接在脚本中怎么办?
可以考虑先定位到script标签,然后用正则匹配的方法找到目标新闻标题,参考
guizhou_parser
。 -
如果遇到反爬怎么办?
反爬情况比较多,能避开尽量避开,例如湖北反爬水准比较高,因此我从黄冈卫健委获取了湖北疫情报告。上海采用了首次get返回javascript脚本生成cookie的办法, 我在架构中特判了它的返回状态码521,用
js2py
模块运行了该部分JS脚本获取cookie并重新get,解决了问题。实际情况可能更为复杂,需要具体情况具体分析,如果无法克服可以上报情况并跳过该目标。 -
(待续)
如有问题可以发送邮件至[email protected]联系作者。