一个不简单的异步爬虫小程序

一个不简单的异步爬虫小程序

说到Python,爬虫可能是大家第一个想到的。

然而,Python在爬虫方面已经产生了巨大的变化。虽然本次的小程序并不简单,不过你们可以尝试着了解一下,在Python3中如何书写一个爬虫。

相关库

本次,我们使用的库并不是`requests`库,而是仅仅支持`Python3.4.2+`的`aiohttp`。

首先我们需要搭建相关的环境:

安装`aiohttp`

pip install aiohttp

安装`cchardet`

pip3 install cchardet

安装`aiodns`

pip3 install aiodns

以上库基本上都没有依赖问题,可以直接安装。

## 目标

例如:`URL — http://flupy.org/data/flags/cn/cn.gif`的内容是一面中国国旗(希望大家做一个爱国的好公民)

![img](http://flupy.org/data/flags/cn/cn.gif)

当然,国旗不只这一面,我们我们只要吧`url`中的`cn/cn.gif`换成别的国家,就可以拿到别的国家的旗子。

例如:`URL — http://flupy.org/data/flags/us/us.gif`的内容是一面美国国旗(us是美国的国家代码)

![img](http://flupy.org/data/flags/us/us.gif)

因此,我们今天的目标就是:

`CN IN US ID BR PK NG BD RU JP MX PH VN ET EG DE IR TR CD FR`

这20个旗子

构造URL代码

为了构造这些目标,我们必须要先获得URL,因此我们通过`base_url`和`contry_codes`的形式分别存储URL共同的部分与不同的部分。

     一个不简单的异步爬虫小程序

程序设计

主流程:

主流程一半是出现再`__name__`测试中的入口函数,使用它的目的一半是提供一个统一的接口,并且提供一个清晰的逻辑,以方便我们添加一些额外的信息。

   一个不简单的异步爬虫小程序

该主流程,只有两个功能

1. 用来调用本程序真正的代码

2. 用来对整个代码的执行计时

实际流程:

在实际的流程中,我们需要开启一个事件循环,来处理我们的任务。

因此我们需要得到一个事件循环`loop`。来执行我们非阻塞的`coroutine`。当然,时间循环一单用完,需要关闭。

     一个不简单的异步爬虫小程序

在这个流程中,`wait`可以通过许多的`coroutine`来构造一个非阻塞的`coroutine`。而且最后这个`coroutine`是在所有`coroutine`完成时才完成。

其实这个流程也只完成了两件事:

* 构造了循环

* 构造需要被时间循环执行的`coroutine`,并提交给循环

处理单个爬取的coroutine

记住,`download_many`的依然是一个普通的函数,但是它的作用是操作时间循环去调度`coroutine`,因此我们需要开始写我们的`coroutine`。

由上一部分可知,对应没一个旗子的`download_one`就是一个`coroutine`

一个不简单的异步爬虫小程序

此处分块处理的原因是因为,不确定图片的大小,可以保证不要一次性占用太多的内存空间。

从上面看出,所有的`coroutine`都是异步的,如果读者自己尝试一下。就会发现,与普通的排队式爬虫相比,速度提高了近16倍,甚至更多。

与使用多线程爬虫的效果相当,但是占用更少的资源,可以腾出更多的内存空间。

待改进

其实在此处,埋了一个伏笔,本程序还有待改进,它现在唯一不完美的地方是,对`pool`的重复利用不好,最好把session放入download_many中。

关注+转发谢谢亲们

一个不简单的异步爬虫小程序