日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

提高爬虫效率aiohttp

發布時間:2024/3/24 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 提高爬虫效率aiohttp 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

眾所周知,Requests 庫一個優秀的 HTTP 庫,通過它可以非常簡單地發起 HTTP 請求。不過,這個庫所執行的網絡請求都是同步。當爬蟲程序進程獲得 CPU 的時間片時,如果程序在進行 I/O 操作(例下載圖片),在這段 IO 執行的時間里,CPU 處于空閑中,這樣會造成 CPU 的計算能力就被浪費了。

如果 CPU 能將等待時間利用起來,那么爬蟲效率就提高了。那就需要對程序進行改造,將 I/O 同步操作變成異步操作。本文內容是介紹一個強大的異步 I/O 操作的庫 —— aiohttp。

1 aiohttp 安裝

安裝 aiohttp 可以通過 pip 方式安裝,在終端中執行安裝命令即可。

pip install aiohttp

2 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 的請求。

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 asyncioasync 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 aiohttpurl = '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 方式請求 httbinasync 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 的用法。

相關例子
同步

from datetime import datetimeimport requests from lxml import etreeheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit""/537.36 (KHTML, like Gecko) ""Chrome/72.0.3626.121 Safari/537.36"}def get_movie_url():req_url = "https://movie.douban.com/chart"response = requests.get(url=req_url, headers=headers)html = etree.HTML(response.text)movies_url = html.xpath("//*[@id='content']/div/div[1]/div/div/table/tr/td/a/@href")return movies_urldef get_movie_content(movie_url):response = requests.get(movie_url, headers=headers)result = etree.HTML(response.text)movie = dict()name = result.xpath('//*[@id="content"]/h1/span[1]//text()')author = result.xpath('//*[@id="info"]/span[1]/span[2]//text()')movie["name"] = namemovie["author"] = authorreturn movieif __name__ == '__main__':start = datetime.now()movie_url_list = get_movie_url()movies = dict()for url in movie_url_list:movies[url] = get_movie_content(url)print(movies)print("同步用時為:{}".format(datetime.now() - start))E:\venv\spider\Scripts\python.exe E:/python_project/filetest/douban.py [{'name': ['小丑 Joker'], 'author': ['托德·菲利普斯']}, {'name': ['好萊塢往事 Once Upon a Time... in Hollywood'], 'author': ['昆汀·塔倫蒂諾']}, {'name': ['愛爾蘭人 The Irishman'], 'author': ['馬丁·斯科塞斯']}, {'name': ['準備好了沒 Ready or Not'], 'author': ['馬特·貝蒂內利-奧爾平', ' / ', '泰勒·吉勒特']}, {'name': ['82年生的金智英 82?? ???'], 'author': ['金度英']}, {'name': ['克勞斯:圣誕節的秘密 Klaus'], 'author': ['塞爾希奧·巴勃羅斯', ' / ', '卡洛斯·馬丁內斯·洛佩斯']}, {'name': ['寄生蟲 ???'], 'author': ['奉俊昊']}, {'name': ['騾子 The Mule'], 'author': ['克林特·伊斯特伍德']}, {'name': ['別告訴她 The Farewell'], 'author': ['王子逸']}, {'name': ['犯罪現場 犯罪現場'], 'author': ['馮志強']}] 同步用時為:0:00:08.765342Process finished with exit code 0

異步

import asyncio from datetime import datetimeimport aiohttp from lxml import etree headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit""/537.36 (KHTML, like Gecko) ""Chrome/72.0.3626.121 Safari/537.36"}async def get_movie_url():req_url = "https://movie.douban.com/chart"async with aiohttp.ClientSession(headers=headers) as session:async with session.get(url=req_url, headers=headers) as response:result = await response.text()result = etree.HTML(result)return result.xpath("//*[@id='content']/div/div[1]/div/div/table/tr/td/a/@href")async def get_movie_content(movie_url):async with aiohttp.ClientSession(headers=headers) as session:async with session.get(url=movie_url, headers=headers) as response:result = await response.text()result = etree.HTML(result)movie = dict()name = result.xpath('//*[@id="content"]/h1/span[1]//text()')author = result.xpath('//*[@id="info"]/span[1]/span[2]//text()')movie["name"] = namemovie["author"] = authorreturn movieif __name__ == '__main__':start = datetime.now()loop = asyncio.get_event_loop()movie_url_list = loop.run_until_complete(get_movie_url())tasks = [get_movie_content(url) for url in movie_url_list]movies = loop.run_until_complete(asyncio.gather(*tasks))print(movies)print("異步用時為:{}".format(datetime.now() - start))E:\venv\spider\Scripts\python.exe E:/python_project/filetest/aio_douban.py [{'name': ['小丑 Joker'], 'author': ['托德·菲利普斯']}, {'name': ['好萊塢往事 Once Upon a Time... in Hollywood'], 'author': ['昆汀·塔倫蒂諾']}, {'name': ['愛爾蘭人 The Irishman'], 'author': ['馬丁·斯科塞斯']}, {'name': ['準備好了沒 Ready or Not'], 'author': ['馬特·貝蒂內利-奧爾平', ' / ', '泰勒·吉勒特']}, {'name': ['82年生的金智英 82?? ???'], 'author': ['金度英']}, {'name': ['克勞斯:圣誕節的秘密 Klaus'], 'author': ['塞爾希奧·巴勃羅斯', ' / ', '卡洛斯·馬丁內斯·洛佩斯']}, {'name': ['寄生蟲 ???'], 'author': ['奉俊昊']}, {'name': ['騾子 The Mule'], 'author': ['克林特·伊斯特伍德']}, {'name': ['別告訴她 The Farewell'], 'author': ['王子逸']}, {'name': ['犯罪現場 犯罪現場'], 'author': ['馮志強']}] 異步用時為:0:00:02.230956Process finished with exit code 0

總結

以上是生活随笔為你收集整理的提高爬虫效率aiohttp的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。