Python網路爬蟲二三事

發表於2017-01-08

Python網路爬蟲二三事

1 前言

作為一名合格的資料分析師,其完整的技術知識體系必須貫穿資料獲取、資料儲存、資料提取、資料分析、資料探勘、資料視覺化等各大部分。在此作為初出茅廬的資料小白,我將會把自己學習資料科學過程中遇到的一些問題記錄下來,以便後續的查閱,同時也希望與各路同學一起交流、一起進步。剛好前段時間學習了Python網路爬蟲,在此將網路爬蟲做一個總結。

2 何為網路爬蟲?

2.1 爬蟲場景

我們先自己想象一下平時到天貓商城購物(PC端)的步驟,可能就是開啟瀏覽器==》搜尋天貓商城==》點選連結進入天貓商城==》選擇所需商品類目(站內搜尋)==》瀏覽商品(價格、詳情引數、評論等)==》點選連結==》進入下一個商品頁面,……這樣子周而復始。當然這其中的搜尋也是爬蟲的應用之一。簡單講,網路爬蟲是類似又區別於上述場景的一種程式。

2.2 爬蟲分類

  • 分類與關係
    一般最常用的爬蟲型別主要有通用爬蟲和聚焦爬蟲,其中聚焦爬蟲又分為淺聚焦與深聚焦,三者關係如下圖:Python網路爬蟲二三事
  • 區別
    通用爬蟲與聚焦爬蟲的區別就在有沒有對資訊進行過濾以儘量保證只抓取與主題相關的網頁資訊。
  • 聚焦爬蟲過濾方法
    • 淺聚焦爬蟲
      選取符合目標主題的種子URL,例如我們定義抓取的資訊為招聘資訊,我們便可將招聘網站的URL(拉勾網、大街網等)作為種子URL,這樣便保證了抓取內容與我們定義的主題的一致性。
    • 深聚焦爬蟲
      一般有兩種,一是針對內容二是針對URL。其中針對內容的如頁面中絕大部分超連結都是帶有錨文字的,我們可以根據錨文字進行篩選;針對URL的如現有連結http://geek.csdn.net/news/detail/126572 ,該連結便向我們透漏主題是新聞(news)。

2.3 爬蟲原理

總的來說,爬蟲就是從種子URL開始,通過 HTTP 請求獲取頁面內容,並從頁面內容中通過各種技術手段解析出更多的 URL,遞迴地請求獲取頁面的程式網路爬蟲,總結其主要原理如下圖(其中紅色為聚焦爬蟲相對通用爬蟲所需額外進行步驟):

Python網路爬蟲二三事

當然,如果對於網路爬蟲原理細節有興趣的同學可參考一下兩篇博文:
網路爬蟲基本原理(一)
網路爬蟲基本原理(二)

2.4 爬蟲應用

網路爬蟲可以做的事情很多,如以下列出:

  • 搜尋引擎
  • 採集資料(金融、商品、競品等)
  • 廣告過濾
  • ……

其實就我們個人興趣,學完爬蟲我們可以看看噹噹網上哪種技術圖書賣得比較火(銷量、評論等資訊)、看某個線上教育網站哪門網路課程做得比較成功、看雙十一天貓的活動情況等等,只要我們感興趣的資料,一般的話都可以爬取得到,不過有些網站比較狡猾,設定各種各樣的反扒機制。總而言之,網路爬蟲可以幫助我們做很多有趣的事情。

3 網路爬蟲基礎

個人建議本章除3.3以外,其他內容可以大致先看一下,有些許印象即可,等到後面已經完成一些簡單爬蟲後或者在寫爬蟲過程中遇到一些問題再回頭來鞏固一下,這樣子或許更有助於我們進一步網路理解爬蟲。

3.1 HTTP協議

HTTP 協議是爬蟲的基礎,通過封裝 TCP/IP 協議連結,簡化了網路請求的流程,使得使用者不需要關注三次握手,丟包超時等底層互動。

關於HTTP協議可以參考一下博文:

3.2 前端技術

作為新手,個人覺得入門的話懂一點HTML與JavaScript就可以實現基本的爬蟲專案,HTML主要協助我們處理靜態頁面,而實際上很多資料並不是我們簡單的右擊檢視網頁原始碼便可以看到的,而是存在JSON(JavaScript Object Notation)檔案中,這時我們便需要採取抓包分析,詳見《5.2 爬取基於Ajax技術網頁資料》。

3.3 正規表示式與XPath

做爬蟲必不可少的步驟便是做解析。正規表示式是文字匹配提取的利器,並且被各種語言支援。XPath即為XML路徑語言,類似Windows的檔案路徑,區別就在XPath是應用在網頁頁面中來定位我們所需內容的精確位置。具體用法參考以下資料:

4 網路爬蟲常見問題

4.1爬蟲利器——python

Python 是一種十分便利的指令碼語言,廣泛被應用在各種爬蟲框架。Python提供瞭如urllib、re、json、pyquery等模組,同時前人又利用Python造了許許多多的輪,如Scrapy框架、PySpider爬蟲系統等,所以做爬蟲Python是一大利器。

  • 說明:本章開發環境細節如下
    • 系統環境:windows 8.1
    • 開發語言:Python3.5
    • 開發工具:Spyder、Pycharm
    • 輔助工具:Chrome瀏覽器

4.2 編碼格式

Python3中,只有Unicode編碼的為str,其他編碼格式如gbk,utf-8,gb2312等都為bytes,在編解碼過程中位元組bytes通過解碼方法decode()解碼為字串str,然後字串str通過編碼方法encode()編碼為位元組bytes,關係如下圖:

Python網路爬蟲二三事

實戰——爬取噹噹網

爬取網頁

檢視編碼格式

可知爬取到的網頁是GB2312編碼,這是漢字的國標碼,專門用來表示漢字。
解碼

重編碼

4.3 超時設定

  • 允許超時
  • 執行緒推遲(單位為秒)

4.4 異常處理

每個程式都不可避免地要進行異常處理,爬蟲也不例外,假如不進行異常處理,可能導致爬蟲程式直接崩掉。

4.4.1 網路爬蟲中處理異常的種類與關係

  • URLError
    通常,URLError在沒有網路連線(沒有路由到特定伺服器),或者伺服器不存在的情況下產生。
  • HTTPError首先我們要明白伺服器上每一個HTTP 應答物件response都包含一個數字“狀態碼”,該狀態碼錶示HTTP協議所返回的響應的狀態,這就是HTTPError。比如當產生“404 Not Found”的時候,便表示“沒有找到對應頁面”,可能是輸錯了URL地址,也可能IP被該網站遮蔽了,這時便要使用代理IP進行爬取資料,關於代理IP的設定我們下面會講到。
  • 兩者關係
    兩者是父類與子類的關係,即HTTPError是URLError的子類,HTTPError有異常狀態碼與異常原因,URLError沒有異常狀態碼。所以,我們在處理的時候,不能使用URLError直接代替HTTPError。同時,Python中所有異常都是基類Exception的成員,所有異常都從此基類繼承,而且都在exceptions模組中定義。如果要代替,必須要判斷是否有狀態碼屬性。

4.4.2 Python中有一套異常處理機制語法

  • try-except語句
    • try 語句:捕獲異常
    • except語句:處理不同的異常,Exception是異常的種類,在爬蟲中常見如上文所述。
    • e:異常的資訊,可供後面列印輸出
    • else: 表示若沒有發生異常,當try執行完畢之後,就會執行else
  • try-except-finally語句

    假如try沒有捕獲到錯誤資訊,則直接跳過except語句轉而執行finally語句,其實無論是否捕獲到異常都會執行finally語句,因此一般我們都會將一些釋放資源的工作放到該步中,如關閉檔案控制程式碼或者關閉資料庫連線等。

4.4.3 實戰——爬取CSDN部落格

Exception異常捕獲輸出結果如下:

4.5 自動模擬HTTP請求

一般客戶端需要通過HTTP請求才能與服務端進行通訊,常見的HTTP請求有POST與GET兩種。例如我們開啟淘寶網頁後一旦HTML載入完成,瀏覽器將會傳送GET請求去獲取圖片等,這樣子我們才能看到一個完整的動態頁面,假如我們瀏覽後需要下單那麼還需要向伺服器傳遞登入資訊。

  • GET方式
    向伺服器發索取資料的一種請求,將請求資料融入到URL之中,資料在URL中可以看到。
  • POST方式向伺服器提交資料的一種請求,將資料放置在HTML HEADER內提交。從安全性講,POST方式相對於GET方式較為安全,畢竟GET方式是直接將請求資料以明文的形式展現在URL中。
  • 實戰——登入CSDN/百度搜尋簡書

4.6 cookies處理

cookies是某些網站為了辨別使用者身份、進行session跟蹤而儲存在使用者本地終端上的資料(通常經過加密)。

參考:零基礎自學用Python 3開發網路爬蟲(四): 登入

4.7 瀏覽器偽裝

  • 原理
    瀏覽器偽裝是防遮蔽的方法之一,簡言之,其原理就是在客戶端在向服務端傳送的請求中新增報頭資訊,告訴伺服器“我是瀏覽器”
  • 如何檢視客戶端資訊?
    通過Chrome瀏覽器按F12==》選擇Network==》重新整理後點選Name下任一個地址,便可以看到請求報文和相應報文資訊。以下是在百度上搜尋簡書的請求報文資訊,在爬蟲中我們只需新增報頭中的User-Agent便可實現瀏覽器偽裝。Python網路爬蟲二三事
  • 實戰——爬取CSDN部落格
    在上面的例項中我們已知道對CSDN部落格直接進行爬取的時候會返回403錯誤,接下來將我們偽裝成瀏覽器爬取CSDN部落格

4.8 代理伺服器

  • 原理
    代理伺服器原理如下圖,利用代理伺服器可以很好處理IP限制問題。Python網路爬蟲二三事
    個人認為IP限制這一點對爬蟲的影響是很大的,畢竟我們一般不會花錢去購買正規的代理IP,我們一般都是利用網際網路上提供的一些免費代理IP進行爬取,而這些免費IP的質量殘次不齊,出錯是在所難免的,所以在使用之前我們要對其進行有效性測試。另外,對開源IP池有興趣的同學可以學習Github上的開源專案:IPProxyPool
  • 實戰——代理伺服器爬取百度首頁

4.9 抓包分析

  • Ajax(非同步載入)的技術
    網站中使用者需求的資料如聯絡人列表,可以從獨立於實際網頁的服務端取得並且可以被動態地寫入網頁中。簡單講就是開啟網頁,先展現部分內容,再慢慢載入剩下的內容。顯然,這樣的網頁因為不用一次載入全部內容其載入速度特別快,但對於我們爬蟲的話就比較麻煩了,我們總爬不到我們想要的內容,這時候就需要進行抓包分析。
  • 抓包工具
    推薦Fiddler與Chrome瀏覽器
  • 實戰
    請轉《5.2 爬取基於Ajax技術網頁資料》。

4.10多執行緒爬蟲

一般我們程式是單執行緒執行,但多執行緒可以充分利用資源,優化爬蟲效率。實際上Python 中的多執行緒並行化並不是真正的並行化,但是多執行緒在一定程度上還是能提高爬蟲的執行效率,下面我們就針對單執行緒和多執行緒進行時間上的比較。

  • 實戰——爬取豆瓣科幻電影網頁
  • 結果:
  • 更多詳情請參考:
    Python 並行任務技巧
    Python中的多程式處理

4.11 資料儲存

  • 本地檔案(excel、txt)
  • 資料庫(如MySQL)

備註:具體實戰請看5.1

4.12 驗證碼處理

在登入過程中我們常遇到驗證碼問題,此時我們有必要對其進行處理。

5 綜合實戰案例

5.1 爬取靜態網頁資料

(1)需求

爬取豆瓣網出版社名字並分別儲存到excel、txt與MySQL資料庫中。

(2)分析

  • 檢視原始碼
  • Ctrl+F搜尋任意出版社名字,如博集天卷
  • 確定正則模式

(3)思路

  • 下載目標頁面
  • 正則匹配目標內容
  • Python列表儲存
  • 寫入Excel/txt/MySQL

(4)原始碼

(5)結果

Python網路爬蟲二三事

5.2 爬取基於Ajax技術網頁資料

(1)需求

爬取拉勾網廣州的資料探勘崗位資訊並儲存到本地Excel檔案中

(2)分析

  • 崗位資料在哪裡?
    開啟拉勾網==》輸入關鍵詞“資料探勘”==》檢視原始碼==》沒發現崗位資訊
    開啟拉勾網==》輸入關鍵詞“資料探勘”==》按F12==》Network重新整理==》按下圖操作
    Python網路爬蟲二三事

    我們可以發現存在position和company開頭的json檔案,這很可能就是我們所需要的崗位資訊,右擊選擇open link in new tab,可以發現其就是我們所需的內容。

    Python網路爬蟲二三事
  • 如何實現翻頁?
    我們在寫爬蟲的時候需要多頁爬取,自動模擬換頁操作。首先我們點選下一頁,可以看到url沒有改變,這也就是Ajax(非同步載入)的技術。點選position的json檔案,在右側點選Headers欄,可以發現最底部有如下內容:
    Python網路爬蟲二三事

    當我們換頁的時候pn則變為2且first變為false,故我們可以通過構造post表單進行爬取。

  • Json資料結構怎麼樣?Python網路爬蟲二三事

    (3)原始碼

5.3 利用Scrapy框架爬取

5.3.1 瞭解Scrapy

Scrapy使用了Twisted非同步網路庫來處理網路通訊。整體架構大致如下(注:圖片來自網際網路):

Python網路爬蟲二三事

詳情轉Scrapy:Python的爬蟲框架
關於Scrapy的使用方法請參考官方文件

5.3.2 Scrapy自動爬蟲

前面的實戰中我們都是通過迴圈構建URL進行資料爬取,其實還有另外一種實現方式,首先設定初始URL,獲取當前URL中的新連結,基於這些連結繼續爬取,直到所爬取的頁面不存在新的連結為止。

(1)需求

採用自動爬蟲的方式爬取糗事百科文章連結與內容,並將文章頭部內容與連結儲存到MySQL資料庫中。

(2)分析

  • 怎麼提取首頁文章連結?
    開啟首頁後檢視原始碼,搜尋首頁任一篇文章內容,可以看到”/article/118123230″連結,點選進去後發現這就是我們所要的文章內容,所以我們在自動爬蟲中需設定連結包含”article”Python網路爬蟲二三事
  • 怎麼提取詳情頁文章內容與連結
    • 內容
      開啟詳情頁後,檢視文章內容如下:
      Python網路爬蟲二三事

      分析可知利用包含屬性class且其值為content的div標籤可唯一確定文章內容,表示式如下:
      "//div[@class='content']/text()"

    • 連結開啟任一詳情頁,複製詳情頁連結,檢視詳情頁原始碼,搜尋連結如下:Python網路爬蟲二三事
      採用以下XPath表示式可提取文章連結。
      ["//link[@rel='canonical']/@href"]

(3)專案原始碼

建立爬蟲專案

開啟CMD,切換到儲存爬蟲專案的目錄下,輸入:
scrapy startproject qsbkauto

Python網路爬蟲二三事
  • 專案結構說明
    • spiders.qsbkspd.py:爬蟲檔案
    • items.py:專案實體,要提取的內容的容器,如噹噹網商品的標題、評論數等
    • pipelines.py:專案管道,主要用於資料的後續處理,如將資料寫入Excel和db等
    • settings.py:專案設定,如預設是不開啟pipeline、遵守robots協議等
    • scrapy.cfg:專案配置
建立爬蟲

進入建立的爬蟲專案,輸入:
scrapy genspider -t crawl qsbkspd qiushibaie=ke.com(域名)

定義items

編寫爬蟲
  • qsbkauto.py
  • pipelines.py
  • setting.py關閉ROBOTSTXT_OBEY
    設定USER_AGENT
    開啟ITEM_PIPELINES
執行爬蟲

結果

Python網路爬蟲二三事

參考:
[1] 天善社群韋瑋老師課程
[2] 文中所跳轉的URL
本文所有程式碼只用於技術交流,拒絕任何商用活動
文章相關專案程式碼已上傳至個人Github
後續的學習細節將會記錄在個人部落格whenif中,歡迎各路同學互相交流

相關文章