资讯专栏INFORMATION COLUMN

Python3 基于asyncio的新闻爬虫思路

zhangyucha0 / 929人阅读

摘要:开始,加入了新的语法,和这两个关键字,也成了标准库,这对于我们写异步的程序来说就是如虎添翼,让我们轻而易举的实现一个定向抓取新闻的异步爬虫。网址池异步爬虫的所有流程不能单单用一个循环来完成,它是多个循环至少两个相互作用共同完成的。

Python写爬虫是非常方便的,爬取的目标不同,实现的方式也有很大不同。新闻爬虫的方便之处是,新闻网站几乎没有反爬虫策略,不好的地方是你想要爬取的新闻网站非常非常多。这个时候,效率就是你首要考虑的问题。
同步循环的效率在这里相形见绌,你需要的是异步IO实现一个高效率的爬虫。

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

异步爬虫依赖的模块

asyncio: 标准异步模块,实现python的异步机制;
uvloop:一个用C开发的异步循环模块,大大提高异步机制的效率;
aiohttp: 一个异步http请求的模块,用于下载网页;
urllib.parse: 解析url网站的模块;
logging: 记录爬虫日志;
leveldb: Google的Key-Value数据库,用以记录url的状态;
farmhash: 对url进行hash计算作为url的唯一标识;
sanicdb: 对aiomysql的封装,更方便的进行数据库mysql操作;

异步爬虫实现的流程

2.1 新闻源列表

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

它们是网站首页、频道首页、最新列表等等;
它们包含非常多的新闻页面的链接;
它们经常被网站更新,以包含最新的新闻链接;
它们不是包含新闻内容的新闻页面;
Hub网页就是爬虫抓取的起点,爬虫从中提取新闻页面的链接再进行抓取。Hub网址可以保存在MySQL数据库中,运维可以随时添加、删除这个列表;爬虫定时读取这个列表来更新定向抓取的任务。这就需要爬虫中有一个循环来定时读取hub网址。

2.2 网址池

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

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

一方面,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 要点:

读读asyncio的文档就可以知道它的运行流程,这里分享一下使用时注意到的地方。

(1)使用loop.run_until_complete(self.loop_crawl())来启动整个程序的主循环;

(2)使用asyncio.ensure_future() 来异步调用一个函数,它相当于多进程的fork,gevent的spawn(),具体可以参考上述代码。

文章来源于:猿人学网站的python教程。

版权申明:若没有特殊说明,文章皆是猿人学原创,没有猿人学授权,请勿以任何形式转载。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43729.html

相关文章

  • Python协程(真才实学,想学进来)

    摘要:所以与多线程相比,线程的数量越多,协程性能的优势越明显。值得一提的是,在此过程中,只有一个线程在执行,因此这与多线程的概念是不一样的。 真正有知识的人的成长过程,就像麦穗的成长过程:麦穗空的时候,麦子长得很快,麦穗骄傲地高高昂起,但是,麦穗成熟饱满时,它们开始谦虚,垂下麦芒。 ——蒙田《蒙田随笔全集》 上篇论述了关于python多线程是否是鸡肋的问题,得到了一些网友的认可,当然也有...

    lykops 评论0 收藏0
  • 关于Python爬虫种类、法律、轮子一二三

    摘要:一般用进程池维护,的设为数量。多线程爬虫多线程版本可以在单进程下进行异步采集,但线程间的切换开销也会随着线程数的增大而增大。异步协程爬虫引入了异步协程语法。 Welcome to the D-age 对于网络上的公开数据,理论上只要由服务端发送到前端都可以由爬虫获取到。但是Data-age时代的到来,数据是新的黄金,毫不夸张的说,数据是未来的一切。基于统计学数学模型的各种人工智能的出现...

    lscho 评论0 收藏0
  • Python爬虫神器pyppeteer,对 js 加密降维打击

    摘要:爬虫神器,对加密降维打击是对无头浏览器的封装。使用等其他无头浏览器的最大优势当然是对加密实行降维打击,完全无视加密手段,对于一些需要登录的应用,也可以模拟点击然后保存。请求过滤你的那一段页面自动下拉脚本 爬虫神器pyppeteer,对 js 加密降维打击 pyppeteer 是对无头浏览器 puppeteer的 Python 封装。无头浏览器广泛用于自动化测试,同时也是一种很好地爬虫思...

    Karuru 评论0 收藏0
  • 首次公开,整理12年积累博客收藏夹,零距离展示《收藏夹吃灰》系列博客

    摘要:时间永远都过得那么快,一晃从年注册,到现在已经过去了年那些被我藏在收藏夹吃灰的文章,已经太多了,是时候把他们整理一下了。那是因为收藏夹太乱,橡皮擦给设置私密了,不收拾不好看呀。 ...

    Harriet666 评论0 收藏0
  • Sanic教程:快速开始

    摘要:快速开始在安装之前在支持异步的过程中,都经历了哪些比较重大的更新。踏出第一步我们将正式使用来构建一个项目,让我们踏出第一步,利用来编写一个返回字符串的服务程序。本次示例的源代码全部在上,见。 快速开始 在安装Sanic之前,让我们一起来看看Python在支持异步的过程中,都经历了哪些比较重大的更新。 首先是Python3.4版本引入了asyncio,这让Python有了支持异步IO的标...

    warmcheng 评论0 收藏0

发表评论

0条评论

zhangyucha0

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<