Python写爬虫是很是方便的,爬取的目标不一样,实现的方式也有很大不一样。新闻爬虫的方便之处是,新闻网站几乎没有反爬虫策略,很差的地方是你想要爬取的新闻网站很是很是多。这个时候,效率就是你首要考虑的问题。
同步循环的效率在这里相形见绌,你须要的是异步IO实现一个高效率的爬虫。python
Python3.5开始,加入了新的语法,async和await这两个关键字,asyncio也成了标准库,这对于咱们写异步IO的程序来讲就是如虎添翼,让咱们垂手可得的实现一个定向抓取新闻的异步爬虫。mysql
asyncio: 标准异步模块,实现python的异步机制;
uvloop:一个用C开发的异步循环模块,大大提升异步机制的效率;
aiohttp: 一个异步http请求的模块,用于下载网页;
urllib.parse: 解析url网站的模块;
logging: 记录爬虫日志;
leveldb: Google的Key-Value数据库,用以记录url的状态;
farmhash: 对url进行hash计算做为url的惟一标识;
sanicdb: 对aiomysql的封装,更方便的进行数据库mysql操做;sql
2.1 新闻源列表数据库
本文要实现的异步爬虫是一个定向抓取新闻网站的爬虫,因此就须要管理一个定向源列表,这个源列表记录了不少咱们想要抓取的新闻网站的url,这些url指向的网页叫作hub网页,它们有以下特色:运维
它们是网站首页、频道首页、最新列表等等;
它们包含很是多的新闻页面的连接;
它们常常被网站更新,以包含最新的新闻连接;
它们不是包含新闻内容的新闻页面;
Hub网页就是爬虫抓取的起点,爬虫从中提取新闻页面的连接再进行抓取。Hub网址能够保存在MySQL数据库中,运维能够随时添加、删除这个列表;爬虫定时读取这个列表来更新定向抓取的任务。这就须要爬虫中有一个循环来定时读取hub网址。异步
2.2 网址池async
异步爬虫的全部流程不能单单用一个循环来完成,它是多个循环(至少两个)相互做用共同完成的。它们相互做用的桥梁就是“网址池”(用asyncio.Queue来实现)。函数
这个网址池就是咱们比较熟悉的“生产者-消费者”模式。oop
一方面,hub网址隔段时间就要进入网址池,爬虫从网页提取到的新闻连接也有进入到网址池,这是生产网址的过程;网站
另外一方面,爬虫要从网址池中取出网址进行下载,这个过程是消费过程;
两个过程相互配合,就有url不断的进进出出网址池。
2.3 数据库
这里面用到了两个数据库:MySQL和Leveldb。前者用于保存hub网址、下载的网页;后者用于存储全部url的状态(是否抓取成功)。
从网页提取到的不少连接可能已经被抓取过了,就没必要再进行抓取,因此他们在进入网址池前就要被检查一下,经过leveldb能够快速查看其状态。
前面的爬虫流程中提到两个循环:
循环一:定时更新hub网站列表
async def loop_get_urls(self,): print('loop_get_urls() start') while 1: await self.get_urls() # 从MySQL读取hub列表并将hub url放入queue await asyncio.sleep(50)
循环二: 抓取网页的循环
async def loop_crawl(self,): print('loop_crawl() start') last_rating_time = time.time() asyncio.ensure_future(self.loop_get_urls()) counter = 0 while 1: item = await self.queue.get() url, ishub = item self._workers += 1 counter += 1 asyncio.ensure_future(self.process(url, ishub)) span = time.time() - last_rating_time if self._workers > self.workers_max: print('got workers_max, sleep 3 sec to next worker') await asyncio.sleep(3)
读读asyncio的文档就能够知道它的运行流程,这里分享一下使用时注意到的地方。
(1)使用loop.run_until_complete(self.loop_crawl())来启动整个程序的主循环;
(2)使用asyncio.ensure_future() 来异步调用一个函数,它至关于多进程的fork,gevent的spawn(),具体能够参考上述代码。
文章来源于:猿人学网站的python教程。
版权申明:若没有特殊说明,文章皆是猿人学原创,没有猿人学受权,请勿以任何形式转载。