Python3 基于asyncio的新闻爬虫思路

Python写爬虫是非常方便的,爬取的目标不同,实现的方式也有很大不同。新闻爬虫的方便之处是,新闻网站几乎没有反爬虫策略,不好的地方是你想要爬取的新闻网站非常非常多。这个时候,效率就是你首要考虑的问题。

同步循环的效率在这里相形见绌,你需要的是异步IO实现一个高效率的爬虫。

Python3.5开始,加入了新的语法,async和await这两个关键字,asyncio也成了标准库,这对于我们写异步IO的程序来说就是如虎添翼,让我们轻而易举的实现一个定向抓取新闻的异步爬虫。

1. 异步爬虫依赖的模块

asyncio: 标准异步模块,实现python的异步机制;

uvloop:一个用C开发的异步循环模块,大大提高异步机制的效率;

aiohttp: 一个异步http请求的模块,用于下载网页;

urllib.parse: 解析url网站的模块;

logging: 记录爬虫日志;

leveldb: Google的Key-Value数据库,用以记录url的状态;

farmhash: 对url进行hash计算作为url的唯一标识;

sanicdb: 对aiomysql的封装,更方便的进行数据库mysql操作;

2. 异步爬虫实现的流程

2.1 新闻源列表

本文要实现的异步爬虫是一个定向抓取新闻网站的爬虫,所以就需要管理一个定向源列表,这个源列表记录了很多我们想要抓取的新闻网站的url,这些url指向的网页叫做hub网页,它们有如下特点:

它们是网站首页、频道首页、最新列表等等;

它们包含非常多的新闻页面的链接;

它们经常被网站更新,以包含最新的新闻链接;

它们不是包含新闻内容的新闻页面;

Hub网页就是爬虫抓取的起点,爬虫从中提取新闻页面的链接再进行抓取。Hub网址可以保存在MySQL数据库中,运维可以随时添加、删除这个列表;爬虫定时读取这个列表来更新定向抓取的任务。这就需要爬虫中有一个循环来定时读取hub网址。

2.2 网址池

异步爬虫的所有流程不能单单用一个循环来完成,它是多个循环(至少两个)相互作用共同完成的。它们相互作用的桥梁就是“网址池”(用asyncio.Queue来实现)。

这个网址池就是我们比较熟悉的“生产者-消费者”模式。

一方面,hub网址隔段时间就要进入网址池,爬虫从网页提取到的新闻链接也有进入到网址池,这是生产网址的过程;

另一方面,爬虫要从网址池中取出网址进行下载,这个过程是消费过程;

两个过程相互配合,就有url不断的进进出出网址池。

2.3 数据库

这里面用到了两个数据库:MySQL和Leveldb。前者用于保存hub网址、下载的网页;后者用于存储所有url的状态(是否抓取成功)。

从网页提取到的很多链接可能已经被抓取过了,就不必再进行抓取,所以他们在进入网址池前就要被检查一下,通过leveldb可以快速查看其状态。

3. 异步爬虫的实现细节

前面的爬虫流程中提到两个循环:

循环一:定时更新hub网站列表

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180911G1B79P00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券