python協程爬蟲-aiohttp+aiomultiprocess使用


最近使用協程寫了個爬蟲,效果杠杠的啊,使用aiohttp替代requests發起請求,requests是同步的,會阻塞比較久,再加上aiomultiprocess,實現多進程異步協程,每個進程都單獨的事件循環執行多個協程任務;這篇文章主要是記錄下這兩個庫的使用

aiohttp

aiohttp是基於asyncio的一個異步http客戶端和服務器

官方文檔:https://aiohttp.readthedocs.io/en/stable/client_quickstart.html

這里我主要記錄客戶端的操作

簡單實用例子

async def funct(index):    
    print("start ", index)    
    async with aiohttp.ClientSession() as session:        
        async with session.get("https://movie.douban.com/top250?start=0", timeout=5) as resp:            
            print(resp.status)
            print(await resp.text())    
    print("end ", index)

  

是要先創建一個會話,然后使用這個會話進行請求

aiohttp.ClientSession()

創建會話,session提供了各種請求方法,如get、post、delete、put等

這里認識了新的關鍵字async with,因為是協程的上下文管理,所以多了async關鍵字

這個不是強制使用的,你也可以自己手動關閉會話,但是一定要記得關閉

注意:

1、不要為每個請求創建會話。每個應用程序很可能需要一個會話來執行所有請求。

2、aiohttp在發送請求之前在內部執行URL 規范化。要禁用規范化,請使用encoded=True參數進行URL構建

 

獲取響應信息

resp.status # 狀態碼
await resp.text() # 獲取響應正文,可以指定編碼
await resp.read() # 讀取二進制響應內容
await resp.json() # 獲取json響應內容
await resp.content.read(size) # 讀取流

注意事項:aiohttp是在await resp.text()之后才發起請求的,所以必須調用之后才能獲取響應的內容,不然會出現異常aiohttp.client_exceptions.ClientConnectionError: Connection closed

aiomultiprocess

asyncio和多處理本身是有用的,但有局限性:asyncio仍然不能超過GIL的速度,並且多處理一次只能處理一個任務。但是,他們在一起可以充分實現自己的真正潛力。

aiomultiprocess提供了一個簡單的界面,同時在每個子進程上運行完整的asyncio事件循環,從而實現了Python應用程序從未有過的並發級別。每個子進程可以一次執行多個協程,僅受工作量和可用內核數限制。

注:aiomultiprocess需要Python 3.6或更高版本

用法

在子進程中執行協程

import asyncio
from aiohttp import request
from aiomultiprocess import Process
​
async def put(url, params):
    async with request("PUT", url, params=params) as response:
        pass
​
async def main():
    p = Process(target=put, args=("https://jreese.sh", {}))
    await p
​
if __name__ == "__main__":
    asyncio.run(main())

  

 

如果您想從協程中獲取結果Worker,請使用以下方法:

import asyncio
from aiohttp import request
from aiomultiprocess import Worker
​
async def get(url):
    async with request("GET", url) as response:
        return await response.text("utf-8")
​
async def main():
    p = Worker(target=get, args=("https://jreese.sh", ))
    response = await p
​
if __name__ == "__main__":
    asyncio.run(main())

   

如果您需要一個托管的工作進程池,請使用Pool

import asyncio
from aiohttp import request from aiomultiprocess import Pool async def get(url): async with request("GET", url) as response: return await response.text("utf-8") async def main(): urls = ["https://jreese.sh", ...] async with Pool() as pool: result = await pool.map(get, urls) if __name__ == "__main__": asyncio.run(main())

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM