利用Python多線程快速爬取某網站數據

  小爬最近受同事所託,幫忙寫個爬蟲來獲取某個網站的公開數據,該網站沒有文件導出功能,後臺返回的也不是完美的json格式數據,每頁且只能顯示不超過22行數據,合計有2200多頁,約50000條數據,這就讓手工取數變得遙不可及。

  小爬原本想用python+selenium思路來低效爬取,實際體驗了之後,發現其速度着實不夠理想,且還存在穩定性問題,容易在控制翻頁的過程中遭遇異常中斷。經過一番思忖,小爬還是決定通過requests庫來獲取html,再用lxml+xpath或者RE表達式來解析,用threading來加速,用csv文件來存儲爬取的內容。

 

 

  說幹咱就幹,通過後臺抓包,我們分析該網站主要是get請求,參數如下:

 

 

 顯然turn_x控制翻頁,classid_x控制類別,mode_x看上去始終爲1.由於我們準備爬取所有服務器存儲的2206頁數據,所以此時可以不區分其類型(任意類型):

   我們可以定義個task函數,傳入pageNum作爲參數來爬取。假如我們一開始不知道服務器中總共多少頁,多少條數據,我們可以先請求一次服務器,解析得到總條數和總頁數,以決定後續的循環次數。不過此時考慮到它的型號數量每天基本保持不變,爲了簡化步驟,我們可以直接確定循環的次數。

  使用requests來爬取網頁信息時,爲了不被反爬策略攔截導致頁面404,我們需要添加必要的Request Headers,而Request Headers中最重要的就是User Agent信息。此處爲了簡化,我們可以如下這樣定義我們的Session:

   我們先定義一個task函數,將pageNum作爲參數:

   拿到頁面元素後,我們使用瀏覽器的Inspect元素偵測功能,觀察頁面的結構:

 

   每條信息都有12個字段,其中“供應商”字段爲廣告,我們需要的是如下這些字段:

類型國內新型號國內舊型號內徑
(mm)
外徑
(mm)
寬度
(mm)
Cr
(kN)
Cor
(kN)
脂潤滑轉速
(r/min)
油潤滑轉速
(r/min)
重量
(kg)

 

 

  部分字段的文本帶有超鏈接(深色文字),部分字段則只有純文本。體現在Html源碼上的差別是,部分文本爲td標籤下的a標籤的文本,部分則直接是td標籤的文本信息。

我們可以利用正則表達式的findall方法拿到所有的td標籤,再對這些內容中含有a標籤的數據進行進一步清洗:

 

   上面代碼中的tdList包含了所有的td標籤信息,可實際上,我們每11個td標籤則爲一行數據,考慮到我們需要分行存儲這些軸承字段信息,那麼有必要將上面正則表達式得到的tdList列表進行分段,得到n個長度爲11的子列表,這個可以通過python的列表表達式快速得到,python語法上簡潔的優勢也再一次得到印證:

 

   緊接着,我們遍歷列表的每一個元素,將含有a標籤的,進一步用re表達式的search+group方法得到其文本內容:

   通過上面一通操作,我們就得到了一個二維列表rows,剩下的操作就是將這個二維數組存入csv文件。

   不過上面這樣得到的csv文件缺少表頭,我們可以在創建csv文件(使用w模式)一開始就寫入表頭,後面便可以用“a”模式追加行信息:

 

   最後我們引入多線程,藉助concurrent庫來加速程序,這個過程中要注意幾個地方:當多個線程同時對某個csv文件進行寫操作時,容易由於共享文件導致寫入亂碼或者信息丟失,所以,在寫入操作時,要引入線程鎖,利用它的acquire 和release方法,以保證信息的寫入安全;另外一點,我們可以利用map方法來快速傳入多個pageNum參數。限於篇幅原因,完整的代碼可以在公衆號“小小爬蟲師”中獲取到。

  經過一番嘗試,藉助多線程技術,我們的腳本,在不到40秒時間就完成了約50000條數據的爬取,可謂高效~

  現實的工作中,我們往往會遇到各式各樣的網站,也會面臨各類爬蟲需求。只有靈活使用各種爬蟲方法、頁面解析方法、多線程、多進程等異步加速手段,才能高效完成工作,向996 say no~

 o(* ̄▽ ̄*)ブ

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章