想提升爬蟲效率?aiohttp 瞭解下

本文原創發佈於微信公衆號「極客猴」,歡迎關注第一時間獲取更多原創分享python

對於爬蟲程序,咱們每每會很關注其爬蟲效率。影響爬蟲效率有幾個因素有,是否使用多線程,I/O 操做,是否同步執行等。其中 I/O 操做、同步執行是最影響爬蟲效率的。web

衆所周知,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() 的例子:cookie

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 方式安裝,在終端中執行安裝命令便可。session

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 的用法。


本文首發於微信公衆號,原文地址是 想提升爬蟲效率?aiohttp 瞭解下。隨時歡迎轉載文章, 轉載請聯繫號主開通白名單,尊重做者的原創。本人微信公衆號「極客猴」,每週分享 Python 原創乾貨。涉及網絡爬蟲、數據分析、web 開發等方向。

相關文章
相關標籤/搜索