人生苦短,我用 Pythonhtml
前文傳送門:python
小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝github
小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門數據庫
小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門json
小白學 Python 爬蟲(5):前置準備(四)數據庫基礎瀏覽器
小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝微信
小白學 Python 爬蟲(8):網頁基礎session
小白學 Python 爬蟲(10):Session 和 Cookies
小白學 Python 爬蟲(11):urllib 基礎使用(一)
小白學 Python 爬蟲(12):urllib 基礎使用(二)
小白學 Python 爬蟲(13):urllib 基礎使用(三)
小白學 Python 爬蟲(14):urllib 基礎使用(四)
小白學 Python 爬蟲(15):urllib 基礎使用(五)
小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖
小白學 Python 爬蟲(17):Requests 基礎使用
小白學 Python 爬蟲(18):Requests 進階操做
小白學 Python 爬蟲(21):解析庫 Beautiful Soup(上)
小白學 Python 爬蟲(22):解析庫 Beautiful Soup(下)
小白學 Python 爬蟲(23):解析庫 pyquery 入門
小白學 Python 爬蟲(26):爲啥買不起上海二手房你都買不起
小白學 Python 爬蟲(27):自動化測試框架 Selenium 從入門到放棄(上)
小白學 Python 爬蟲(28):自動化測試框架 Selenium 從入門到放棄(下)
小白學 Python 爬蟲(29):Selenium 獲取某大型電商網站商品信息
小白學 Python 爬蟲(31):本身構建一個簡單的代理池
PS:原諒小編一件事兒,昨天公衆號推送的前文傳送門連接沒搞對,致使全部鏈接都失效了,微信又對已經推送的文章有修改限制,只支持刪改,不支持加連接,小編誠懇的給你們道個歉。
按照慣例,先放官方連接:
官方文檔:https://docs.aiohttp.org/en/stable/
惋惜這個沒有中文版的,瀏覽器自帶的翻譯軟件湊合看吧,有看不懂的再看原文。
緣由固然很簡單,快啊~~~
啊呸,不對,是效率高。
這個效率高怎麼定義呢?若是是爬取的接口或者頁面沒有先後的邏輯關係,舉個栗子:必需要先從 a 頁面獲取某個數據才能拼出來 b 頁面訪問連接,這個就叫有先後邏輯關係。
咱們不少狀況下頁面的爬取是沒有先後邏輯關係的,使用同步請求庫如: Requests 就只能等一個請求先出去,再回來纔會發送下一個請求。
若是是換成異步請求庫就不會有這個等待了,一個請求發出去,纔不會管這個請求什麼時間響應,直接下一個請求就接着發出去了,而後再是下下個請求。
固然,異步請求庫也爲咱們提供了回調方法,否則咱們都不知道何時請求有響應,何時會有咱們想要的數據回來。
先看個簡單的例子,咱們先直觀的感覺下異步請求庫到底能比同步請求庫快多少。
這裏使用的網站是度娘(其實原本想使用 Github 的,實在是小編使用的移動的寬帶網絡太xxx,循環打開十次 5 分鐘都跑不完),無奈轉換度娘,訪問 100 次,由於 10 次太少了,看不出來差距。
示例代碼以下:
import requests
from datetime import datetime
start = datetime.now()
for i in range(100):
print(requests.get('https://www.baidu.com/').text)
end = datetime.now()
print("request花費時間爲:", end - start)複製代碼
結果以下:
request花費時間爲: 0:00:13.410708複製代碼
其餘的打印小編這裏就不貼了,單純的貼一下最後時間差的打印。
示例代碼以下:
import aiohttp
import asyncio
from datetime import datetime
async def main():
async with aiohttp.ClientSession() as client:
html = await client.get('https://www.baidu.com/')
print(html)
loop = asyncio.get_event_loop()
tasks = []
for i in range(100):
task = loop.create_task(main())
tasks.append(task)
start = datetime.now()
loop.run_until_complete(main())
end = datetime.now()
print("aiohttp花費時間爲:", end - start)複製代碼
結果以下:
aiohttp花費時間爲: 0:00:00.249995複製代碼
各位同窗,看到了沒,這個訪問速度天差地別啊,一個用了 13s 多,一個連 1s 都沒到,這中間的差距小編已經不想算了,太大了。
不過訪問速度這麼快,訪問有 ip 防護的網站,封的速度也挺快的,可能爬蟲剛開始運行,茶杯子都沒端起來就已經把 ip 封掉了。
接下來咱們簡單的瞭解一下 AIOHTTP 的一些基本操做。
示例代碼:
import aiohttp
import asyncio
async def aio_1():
async with aiohttp.ClientSession() as session:
async with session.get('https://www.baidu.com/') as resp:
print(resp.status)
print(await resp.text())
loop = asyncio.get_event_loop()
loop.run_until_complete(aio_1())複製代碼
結果就不貼了,這裏主要是給各位同窗演示如何使用 AIOHTTP 發送請求。
這裏,咱們使用一個 ClientSession 做爲被調用的 session 和一個 ClientResponse 對象做爲響應結果。
一下內容爲來自官方文檔的提示:
注意:
不要爲每一個請求建立會話。每一個應用程序極可能須要一個會話來執行全部請求。
更復雜的狀況可能須要在每一個站點上進行一次會話,例如,一個會話用於Github,另外一個會話用於Facebook API。不管如何,爲每一個請求創建會話是一個很是糟糕的主意。
會話內部包含一個鏈接池。鏈接重用和保持活動狀態(默認狀況下均處於啓用狀態)可能會提升總體性能。
先看個示例:
async def aio_2():
async with aiohttp.ClientSession() as session:
async with session.get('https://www.geekdigging.com/') as resp:
print(resp.status)
print(await resp.text())
loop = asyncio.get_event_loop()
loop.run_until_complete(aio_2())複製代碼
AIOHTTP 爲咱們提供了自動解碼的功能,
這裏的示例訪問小編的博客站,其中首頁有大量的中文內容,若是解碼不正確中文是不能正常顯示的。結果小編就不貼了,解碼正確。
固然,若是咱們發現自動解碼不正確的時候能夠認爲的設定解碼類型,代碼以下:
await resp.text(encoding='gb2312')複製代碼
響應咱們一樣能夠經過二進制字節流的方式來進行訪問,代碼以下:
print(await resp.read())複製代碼
AIOHTTP 還爲咱們內置了一個 JSON 解碼器,能夠供咱們直接處理 JSON 格式的響應數據,示例代碼以下:
print(await resp.json())複製代碼
在前面咱們介紹其餘請求庫的時候,都有遇到過超時的問題,通常而言,咱們會爲請求添加一個超時時間,那麼在 AIOHTTP 中,超時時間的添加以下示例代碼:
async def aio_3():
timeout = aiohttp.ClientTimeout(total=60)
async with aiohttp.ClientSession(timeout = timeout) as session:
async with session.get('https://www.geekdigging.com/', timeout = timeout) as resp:
print(resp.status)
loop = asyncio.get_event_loop()
loop.run_until_complete(aio_3())複製代碼
若是咱們不設置超時時間 AIOHTTP 爲咱們默認設置的超時時間是 5 分鐘,若是咱們設置了超時時間,則以咱們設置的爲準,超時時間的設置能夠在兩個地方設置,小編已經在示例中都舉例出來了。
咱們能夠直接在建立 ClientSession 的時候直接設置超時時間,這時,整個超時時間是在當前的會話中都有效的,若是在後面的調用中如 ClientSession.get():
中從新設置超時時間,則會覆蓋咱們在建立 ClientSession 設置的超時時間。
而 ClientTimeout 則還有不少種屬性能夠進行設置,列表以下:
默認超時以下:
aiohttp.ClientTimeout(total=5*60, connect=None,
sock_connect=None, sock_read=None)複製代碼
本系列的全部代碼小編都會放在代碼管理倉庫 Github 和 Gitee 上,方便你們取用。