专栏首页极客猴想提高爬虫效率?aiohttp 了解下

想提高爬虫效率?aiohttp 了解下

题图:by cfunk44 from Instagram

阅读文本大概需要 8 分钟。

对于爬虫程序,我们往往会很关注其爬虫效率。影响爬虫效率有几个因素有,是否使用多线程,I/O 操作,是否同步执行等。其中 I/O 操作、同步执行是最影响爬虫效率的。

众所周知,Requests 库一个优秀的 HTTP 库,通过它可以非常简单地发起 HTTP 请求。不过,这个库所执行的网络请求都是同步。当爬虫程序进程获得 CPU 的时间片时,如果程序在进行 I/O 操作(例下载图片),在这段 IO 执行的时间里,CPU 处于空闲中,这样会造成 CPU 的计算能力就被浪费了。

如果 CPU 能将等待时间利用起来,那么爬虫效率就提高了。那就需要对程序进行改造,将 I/O 同步操作变成异步操作。本文内容是介绍一个强大的异步 I/O 操作的库 —— aiohttp

1 aiohttp 介绍

说到 aiohttp ,不得不说下 asyncio 。asyncio 是 Python 3.4 版本引入的标准库。它工作模式是单线程并发,使用协同执行 I/O 操作。asyncio 的编程模型就是一个消息循环。我们从 asyncio 模块中直接获取一个 EventLoop 的引用,然后把需要执行的协程扔到 EventLoop 中执行,就实现了异步 IO。

使用 asyncio 实现一个异步函数 hello() 的例子:

import asyncio

@asyncio.coroutine # 修饰符,等同于 asyncio.coroutine(hello())
def hello():
    print("Hello world!")
    # 异步调用asyncio.sleep(1):
    r = yield from asyncio.sleep(1)
    print("Hello again!")

# 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()

而 aiohttp 则是基于 asyncio 实现的 HTTP 框架。 aiohttp 全称是 Async http client/server framework。翻译成中文是异步 HTTP 的客户端/服务器框架。从名字中,我们可知 aiohttp 是分为服务器端和客户端,专门异步处理 HTTP 的请求。

2 aiohttp 安装

安装 aiohttp 可以通过 pip 方式安装,在终端中执行安装命令即可。

pip install aiohttp

3 async/await 语法

前面我们讲到异步 I/O 的用法,但是声明异步函数比较繁琐,还需要依赖 yield 语法。在 Python 3.5 中,引入了 async/await 关键字,使得异步回调的写法更加直观和人性化。

在函数 def 之前增加关键字async,表示这个函数是异步函数。相当于替代语法@asyncio.coroutine。具体例子例如:

async def hello():
    print("Hello World!")

另外使用 await 替换了 yield from, 表示这部分操作为异步操作。

async def hello():
    print("Hello World!")
    r = await asyncio.sleep(1)
    print("Hello again!")

最后执行异步函数,还是需要用到 EventLoop 引用,然后利用协程执行异步函数。最终的代码如下:

import asyncio

async def hello():
    print("Hello world!")
    r = await asyncio.sleep(1)
    print("Hello again!")

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    tasks = [hello(), ]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()

运行结果如下:

Hello world!
>> 会暂停一秒钟
Hello again!

4 aiohttp 基本用法

我们使用 aiohttp 以 GET 方式向httpbin.org网站发起一个 HTTP 请求。因为是 aiohttp 是异步处理 HTTP 请求。所以还必须遵循 Python 的异步函数语法,即需使用 async/await 语法。

使用 aiohttp 发起一个 HTTP 请求,具体编写可以分为以下几步: 1)使用 async 定义异步函数 2)通过 aiohttp.ClientSession 获取一个 session 对象 3)用该 session 对象以 GET、POST、PUT 等方式去请求网页 4)最后获取 EventLoop 引用,执行异步函数。

import asyncio
import aiohttp

# 定义异步函数 main()
async def main():
    # 获取 session 对象
      async with aiohttp.ClientSession() as session:
        # get 方式请求 httbin  async with session.get('http://httpbin.org/get') as response:
            print(response.status)
            print(await response.text())

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

aiohttp 支持自定义 headers、设置超时时间、设置代理、自定义 cookie 等。

import asyncio
import aiohttp

url = 'http://httpbin.org/post'
headers = {
    'User-agent': "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
}

data = {
    'data': 'person data',
}

# 定义异步函数 main()
async def main():
    # 获取 session 对象
    async with aiohttp.ClientSession() as session:
        # post 方式请求 httbin
        async with session.post(url=url, headers=headers, data=data) as response:
            print(response.status)
            print(await response.text())

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

关于 aiohttp 更多用法,可以执行阅读官网文档。说句实话,aiohttp 跟 Requests 的用法大同小异。如果你已经学会了 Requests 库,很快就能掌握 aiohttp 的用法。

本文分享自微信公众号 - 极客猴(Geek_monkey),作者:极客猴

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-08-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Scrapy 框架插件之 IP 免费代理池

    现在很多网站都是对单个 IP 地址有访问次数限制,如果你在短时间内访问过于频繁。该网站会封掉你 IP,让你在一段时间内无法正常该网站。突破反爬虫机制的一个重要举...

    猴哥yuri
  • 震惊了!每30秒学会一个Python小技巧,Github星数4600+

    很多学习Python的朋友在项目实战中会遇到不少功能实现上的问题,有些问题并不是很难的问题,或者已经有了很好的方法来解决。当然,孰能生巧,当我们代码熟练了,自然...

    猴哥yuri
  • 爬虫 | Python学习之Scrapy-Redis实战京东图书

    scrapy-Redis就是结合了分布式数据库redis,重写了scrapy一些比较关键的代码,将scrapy变成一个可以在多个主机上同时运行的分布式爬虫。

    猴哥yuri
  • Mac电脑C语言开发的入门帖

    俺踏月色而来
  • 温故而知新:WinForm/Silverlight多线程编程中如何更新UI控件的值

    单线程的winfom程序中,设置一个控件的值是很easy的事情,直接 this.TextBox1.value = "Hello World!";就搞定了,但是如...

    菩提树下的杨过
  • 为什么43%前端开发者想学Vue.js

    根据JavaScript 2017前端库状况调查 Vue.js是开发者最想学的前端库。我在这里说明一下我为什么认为这也是和你一起通过使用Vue构建一个简单的Ap...

    笔阁
  • happens-before原则

    在Java中有一个很重要的原则,这个原则是判断线程是否存在数据竞争、线程是否安全的主要依据,这个原则就是happens-before原则。我们首先看一下到底什么...

    吉林乌拉
  • TW洞见〡为什么你的Angular代码很难测试?

    Angular推出有好几年的时候了,跟其他的MV*框架相比,它的双向绑定,无须显式声明Model,模块管理,依赖注入等特点都给Web应用开发带来了极大的便利,...

    ThoughtWorks
  • Service Worker:让你的 Web 应用牛逼起来

    https://github.com/omnipotent-front-end/blog/issues/2

    coder_koala
  • Power Query如何处理日月年的时间列?

    对我们来说可以理解为,日/月/年,但是我们看下导入到Power Query中会如何显示?

    逍遥之

扫码关注云+社区

领取腾讯云代金券