目錄
文 | 閒歡
**:python 技術「id: pythonall」
今天在瀏覽知乎時,發現乙個有趣的問題:如何優化 python 爬蟲的速度?
他的問題描述是:
目前在寫乙個 python 爬蟲,單執行緒 urllib 感覺過於慢了,達不到資料量的要求(十萬級頁面)。求問有哪些可以提高爬取效率的方法?
這個問題還蠻多人關注的,但是回答的人卻不多。
我今天就來嘗試著回答一下這個問題。
程式提速這個問題其實解決方案就擺在那裡,要麼通過併發來提高單位時間內處理的工作量,要麼從程式本身去找提效點,比如爬取的資料用gzip傳輸、提高處理資料的速度等。
我會分別從幾種常見的併發方法去做同一件事情,從而www.cppcns.com比較處理效率。
我們先來乙個簡單的爬蟲,看看單執行緒處理會花費多少時間?
import time
import requests
from datetime import datetime
def fetch(url):
r = requests.get(url)
print(r.text)
start = datetime.now()
t1 = time.time()
for i in range(100):
fetch('')
print('requests版爬蟲耗時:', time.time() - t1)
# requests版爬蟲耗時:54.86306357383728
我們用乙個爬蟲的測試**,測試爬取100次,用時是54.86秒。
下面我們將上面的程式改為多執行緒版本:
import threading
import time
import requests
def fetch():
r = requests.get('')
print(r.text)
t1 = time.time()
t_list =
for i in range(100):
t = threading.thread(target=fetch, args=())
t_list.append(t)
t.程式設計客棧start()
for t in t_list:
t.join()
print("多執行緒版爬蟲耗時:", time.time() - t1)
# 多執行緒版爬蟲耗時:0.8038511276245117
我們可以看到,用上多執行緒之後,速度提高了68倍。其實用這種方式的話,由於我們併發操作,所以跑100次跟跑一次的時間基本是一致的。這只是乙個簡單的例子,實際情況中我們不可能無限制地增加執行緒數。
除了多執行緒之外,我們還可以使用多程序來提高爬蟲速度:
import requests
import time
import multiprocessing
from multiprocessing import pool
max_worker_num = multiprocessing.cpu_count()
def fetch():
r = requests.get('')
print(r.text)
if __name__ == '__main__':
t1 = time.time()
p = pool(max_worker_num)
for i in range(100):
p.apply_async(fetch, args=())
p.close()
p.join()
print('多程序爬蟲耗時:', time.time() - t1)
多程序爬蟲耗時: 7.9846765995025dakwlrsa635
我們可以看到多程序處理的時間是多執行緒的10倍,比單執行緒版本快7倍。
我們將程式改為使用 aiohttp 來實現,看看效率如何:
assert resp.status程式設計客棧 == 200
print("aiohttp版爬蟲耗時:", time.timwww.cppcns.come() - t1)
aiohttp版爬蟲耗時: 0.6133313179016113
我們可以看到使用這種方式實現,比單執行緒版本快90倍,比多執行緒還快。
通過上面的程式對比,我們可以看到,對於多工爬蟲來說,多執行緒、多程序、協程這幾種方式處理效率的排序為:aiohttp > 多執行緒 > 多程序。因此,對於簡單的爬蟲任務,如果想要提高效率,可以考慮使用協程。但是同時也要注意,這裡只是簡單的示例,實際運用中,我們一般會用執行緒池、程序池、協程池去操作。
這就是問題的答案了嗎?
對於乙個嚴謹的程式設計師來說,當然不是,實際上還有一些優化的庫,例如grequests,可以從請求上解決併發問題。實際的處理過程中,肯定還有其他的優化點,這裡只是從最常見的幾種併發方式去比較而已,應付簡單爬蟲還是可以的,其他的方式歡迎大家在評論區留言**。
熱門的耶穌問題
1.如何表示13個人?通過陣列表示,有13個元素,賦值為1 13 2.如何描述報數?使用count值統計當前是第幾個人 3.如何將人剔除,標記已經死掉的人?將元素值置為0 4.如何及時獲取當前活著的人?變數number記錄當前活著的人 5.使用哪種迴圈結構?採用while迴圈 6.迴圈條件是什麼?當...
提公升爬蟲效率的方法
任務物件 事件迴圈 特殊函式內部不能寫不支援非同步請求的模組,如time,requests.否則雖然不報錯但實現不了非同步 import asyncio import time start time time.time async def get request url await asyncio....
Python 爬蟲中遇到的反爬蟲問題
源 一般會有下面幾種限制 1 一定時間內單個ip訪問次數,乙個正常使用者訪問 除非是隨意的點著玩,否則不會在一段持續時間內過快訪問乙個 持續時間也不會太長,我們可以採用大量不規則 ip形成乙個執行緒池,隨機從 池中選擇 模擬訪問。有兩種,透明 和匿名 2 一定時間內單個賬號訪問次數,如果乙個人一天2...