從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

在這個大數據時代,尤其是人工智能浪潮興起的時代,不論是工程領域還是研究領域,數據已經成為必不可少的一部分,而數據的獲取很大程度上依賴於爬蟲的爬取,所以爬蟲變得越來越火爆。

什麼是爬蟲?

我們可以把互聯網比作一張大網,而爬蟲(即網絡爬蟲)便是在網上爬行的蜘蛛。把網的節點比作一個個網頁,爬蟲爬到這就相當於訪問了該頁面,獲取了其信息。可以把節點間的連線比作網頁與網頁之間的鏈接關係,這樣蜘蛛通過一個節點後,可以順著節點連線繼續爬行到達下一個節點,即通過一個網頁繼續獲取後續的網頁,這樣整個網的節點便可以被蜘蛛全部爬行到,網站的數據就可以被抓取下來了。

怎麼學爬蟲?

在學習寫爬蟲之前,我們需要了解一些基礎知識,如 HTTP 原理、網頁的基礎知識、爬蟲的基本原理、Cookies 的基本原理等。本文,我們就對這些基礎知識做一個簡單的總結。

HTTP 基本原理

在本節中,我們會詳細瞭解 HTTP 的基本原理,瞭解在瀏覽器中敲入 URL 到獲取網頁內容之間發生了什麼。瞭解了這些內容,有助於我們進一步瞭解爬蟲的基本原理。

一、URI 和 URL

這裡我們先了解一下 URI 和 URL,URI 的全稱為 Uniform Resource Identifier,即統一資源標誌符,URL 的全稱為 Universal Resource Locator,即統一資源定位符。

舉例來說,https://github.com/favicon.ico 是 GitHub 的網站圖標鏈接,它是一個 URL,也是一個URI。即有這樣的一個圖標資源,我們用 URL/URI 來唯一指定了它的訪問方式,這其中包括了訪問協議 https、訪問路徑(/即根目錄)和資源名稱 favicon.ico。通過這樣一個鏈接,我們便可以從互聯網上找到這個資源,這就是 URL/URI。

URL 是 URI 的子集,也就是說每個 URL 都是 URI,但不是每個 URI 都是 URL。那麼,怎樣的URI 不是 URL 呢?URI 還包括一個子類叫作 URN,它的全稱為 Universal Resource Name,即統一資源名稱。URN 只命名資源而不指定如何定位資源,比如 urn:isbn:0451450523 指定了一本書的 ISBN,可以唯一標識這本書,但是沒有指定到哪裡定位這本書,這就是 URN。URL、URN 和 URI 的關係可以用圖 1 表示。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖1 URL、URN 和URI 關係圖

但是在目前的互聯網中,URN 用得非常少,所以幾乎所有的 URI 都是 URL,一般的網頁鏈接我們既可以稱為 URL,也可以稱為 URI,我個人習慣稱為 URL。

二、超文本

接下來,我們再瞭解一個概念——超文本,其英文名稱叫作 hypertext,我們在瀏覽器裡看到的網頁就是超文本解析而成的,其網頁源代碼是一系列 HTML 代碼,裡面包含了一系列標籤,比如 img 顯示圖片,p 指定顯示段落等。瀏覽器解析這些標籤後,便形成了我們平常看到的網頁,而網頁的源代碼 HTML 就可以稱作超文本。

例如,我們在 Chrome 瀏覽器裡面打開任意一個頁面,如淘寶首頁,右擊任一地方並選擇“檢查”項(或者直接按快捷鍵 F12),即可打開瀏覽器的開發者工具,這時在 Elements 選項卡即可看到當前網頁的源代碼,這些源代碼都是超文本,如圖 2 所示。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖2 源代碼

三、HTTP 和HTTPS

在淘寶的首頁https://www.taobao.com/中,URL 的開頭會有http 或https,這就是訪問資源需要的協議類型。有時,我們還會看到ftp、sftp、smb 開頭的URL,它們都是協議類型。在爬蟲中,我們抓取的頁面通常就是http 或https 協議的,這裡首先了解一下這兩個協議的含義。

HTTP 的全稱是Hyper Text Transfer Protocol,中文名叫作超文本傳輸協議。HTTP 協議是用於從網絡傳輸超文本數據到本地瀏覽器的傳送協議,它能保證高效而準確地傳送超文本文檔。HTTP 由萬維網協會(World Wide Web Consortium)和Internet 工作小組IETF(Internet Engineering Task Force)共同合作制定的規範,目前廣泛使用的是HTTP 1.1 版本。

HTTPS 的全稱是Hyper Text Transfer Protocol over Secure Socket Layer,是以安全為目標的HTTP通道,簡單講是HTTP 的安全版,即HTTP 下加入SSL 層,簡稱為HTTPS。

HTTPS 的安全基礎是SSL,因此通過它傳輸的內容都是經過SSL 加密的,它的主要作用可以分為兩種。

  • 建立一個信息安全通道來保證數據傳輸的安全
  • 確認網站的真實性,凡是使用了HTTPS 的網站,都可以通過點擊瀏覽器地址欄的鎖頭標誌來查看網站認證之後的真實信息,也可以通過CA 機構頒發的安全簽章來查詢

現在越來越多的網站和App 都已經向HTTPS 方向發展,例如:

  • 蘋果公司強制所有iOS App 在2017 年1 月1 日前全部改為使用HTTPS 加密,否則App 就無法在應用商店上架
  • 谷歌從2017 年1 月推出的Chrome 56 開始,對未進行HTTPS 加密的網址鏈接亮出風險提示,即在地址欄的顯著位置提醒用戶“此網頁不安全”
  • 騰訊微信小程序的官方需求文檔要求後臺使用HTTPS 請求進行網絡通信,不滿足條件的域名和協議無法請求

而某些網站雖然使用了HTTPS 協議,但還是會被瀏覽器提示不安全,例如我們在Chrome 瀏覽器裡面打開12306,鏈接為:https://www.12306.cn/,這時瀏覽器就會提示“您的連接不是私密連接”這樣的話,如圖3 所示。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖3 12306 頁面

這是因為12306 的CA 證書是中國鐵道部自行簽發的,而這個證書是不被CA 機構信任的,所以這裡證書驗證就不會通過而提示這樣的話,但是實際上它的數據傳輸依然是經過SSL 加密的。如果要爬取這樣的站點,就需要設置忽略證書的選項,否則會提示SSL 鏈接錯誤。

四、HTTP 請求過程

我們在瀏覽器中輸入一個URL,回車之後便會在瀏覽器中觀察到頁面內容。實際上,這個過程是瀏覽器向網站所在的服務器發送了一個請求,網站服務器接收到這個請求後進行處理和解析,然後返回對應的響應,接著傳回給瀏覽器。響應裡包含了頁面的源代碼等內容,瀏覽器再對其進行解析,便將網頁呈現了出來,模型如圖4 所示。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖4 模型圖

此處客戶端即代表我們自己的PC 或手機瀏覽器,服務器即要訪問的網站所在的服務器。

為了更直觀地說明這個過程,這裡用Chrome 瀏覽器的開發者模式下的Network 監聽組件來做下演示,它可以顯示訪問當前請求網頁時發生的所有網絡請求和響應。

打開Chrome 瀏覽器,右擊並選擇“檢查”項,即可打開瀏覽器的開發者工具。這裡訪問百度http://www.baidu.com/,輸入該URL 後回車,觀察這個過程中發生了怎樣的網絡請求。可以看到,在Network 頁面下方出現了一個個的條目,其中一個條目就代表一次發送請求和接收響應的過程,如圖5 所示。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖5 Network 面板

我們先觀察第一個網絡請求,即www.baidu.com。

其中各列的含義如下。

  • 第一列Name:請求的名稱,一般會將URL 的最後一部分內容當作名稱。
  • 第二列Status:響應的狀態碼,這裡顯示為200,代表響應是正常的。通過狀態碼,我們可以判斷髮送了請求之後是否得到了正常的響應。
  • 第三列Type:請求的文檔類型。這裡為document,代表我們這次請求的是一個HTML文檔,內容就是一些HTML 代碼。
  • 第四列Initiator:請求源。用來標記請求是由哪個對象或進程發起的。
  • 第五列Size:從服務器下載的文件和請求的資源大小。如果是從緩存中取得的資源,則該列會顯示from cache。
  • 第六列Time:發起請求到獲取響應所用的總時間。
  • 第七列Waterfall:網絡請求的可視化瀑布流。

點擊這個條目,即可看到更詳細的信息,如圖6 所示。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖6 詳細信息

首先是General 部分,Request URL 為請求的URL,Request Method 為請求的方法,Status Code為響應狀態碼,Remote Address 為遠程服務器的地址和端口,Referrer Policy 為Referrer 判別策略。

再繼續往下,可以看到,有Response Headers 和Request Headers,這分別代表響應頭和請求頭。請求頭裡帶有許多請求信息,例如瀏覽器標識、Cookies、Host 等信息,這是請求的一部分,服務器會根據請求頭內的信息判斷請求是否合法,進而作出對應的響應。圖中看到的Response Headers 就是響應的一部分,例如其中包含了服務器的類型、文檔類型、日期等信息,瀏覽器接受到響應後,會解析響應內容,進而呈現網頁內容。

下面我們分別來介紹一下請求和響應都包含哪些內容。

五、請求

請求,由客戶端向服務端發出,可以分為4 部分內容:請求方法(Request Method)、請求的網址(Request URL)、請求頭(Request Headers)、請求體(Request Body)。

1. 請求方法

常見的請求方法有兩種:GET 和POST。

在瀏覽器中直接輸入URL 並回車,這便發起了一個GET 請求,請求的參數會直接包含到URL裡。例如,在百度中搜索Python,這就是一個GET 請求,鏈接為https://www.baidu.com/s?wd=Python,其中URL 中包含了請求的參數信息,這裡參數wd 表示要搜尋的關鍵字。POST 請求大多在表單提交時發起。比如,對於一個登錄表單,輸入用戶名和密碼後,點擊“登錄”按鈕,這通常會發起一個POST請求,其數據通常以表單的形式傳輸,而不會體現在URL 中。

GET 和POST 請求方法有如下區別。

  • GET 請求中的參數包含在URL 裡面,數據可以在URL 中看到,而POST 請求的URL 不會包含這些數據,數據都是通過表單形式傳輸的,會包含在請求體中
  • GET 請求提交的數據最多隻有1024 字節,而POST 方式沒有限制

一般來說,登錄時,需要提交用戶名和密碼,其中包含了敏感信息,使用GET 方式請求的話,密碼就會暴露在URL 裡面,造成密碼洩露,所以這裡最好以POST 方式發送。上傳文件時,由於文件內容比較大,也會選用POST 方式。

我們平常遇到的絕大部分請求都是GET 或POST 請求,另外還有一些請求方法,如GET、HEAD、POST、PUT、DELETE、OPTIONS、CONNECT、TRACE 等,我們簡單將其總結為表1。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

表1 其他請求方法

本表參考:http://www.runoob.com/http/http-methods.html。

2. 請求的網址

請求的網址,即統一資源定位符URL,它可以唯一確定我們想請求的資源。

3. 請求頭

請求頭,用來說明服務器要使用的附加信息,比較重要的信息有Cookie、Referer、User-Agent 等。下面簡要說明一些常用的頭信息。

  • Accept:請求報頭域,用於指定客戶端可接受哪些類型的信息
  • Accept-Language:指定客戶端可接受的語言類型
  • Accept-Encoding:指定客戶端可接受的內容編碼
  • Host:用於指定請求資源的主機IP 和端口號,其內容為請求URL 的原始服務器或網關的位置。從HTTP 1.1 版本開始,請求必須包含此內容
  • Cookie:也常用複數形式 Cookies,這是網站為了辨別用戶進行會話跟蹤而存儲在用戶本地的數據。它的主要功能是維持當前訪問會話。例如,我們輸入用戶名和密碼成功登錄某個網站後,服務器會用會話保存登錄狀態信息,後面我們每次刷新或請求該站點的其他頁面時,會發現都是登錄狀態,這就是Cookies 的功勞。Cookies 裡有信息標識了我們所對應的服務器的會話,每次瀏覽器在請求該站點的頁面時,都會在請求頭中加上Cookies 並將其發送給服務器,服務器通過Cookies 識別出是我們自己,並且查出當前狀態是登錄狀態,所以返回結果就是登錄之後才能看到的網頁內容
  • Referer:此內容用來標識這個請求是從哪個頁面發過來的,服務器可以拿到這一信息並做相應的處理,如做來源統計、防盜鏈處理等
  • User-Agent:簡稱UA,它是一個特殊的字符串頭,可以使服務器識別客戶使用的操作系統及版本、瀏覽器及版本等信息。在做爬蟲時加上此信息,可以偽裝為瀏覽器;如果不加,很可能會被識別出為爬蟲
  • Content-Type:也叫互聯網媒體類型(Internet Media Type)或者MIME 類型,在HTTP 協議消息頭中,它用來表示具體請求中的媒體類型信息。例如,text/html 代表HTML 格式,image/gif 代表GIF 圖片,application/json 代表JSON 類型,更多對應關係可以查看此對照表:http://tool.oschina.net/commons

因此,請求頭是請求的重要組成部分,在寫爬蟲時,大部分情況下都需要設定請求頭。

4. 請求體

請求體一般承載的內容是POST 請求中的表單數據,而對於GET 請求,請求體則為空。

例如,這裡我登錄GitHub 時捕獲到的請求和響應如圖7 所示。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖7 詳細信息

登錄之前,我們填寫了用戶名和密碼信息,提交時這些內容就會以表單數據的形式提交給服務器,此時需要注意Request Headers 中指定Content-Type 為application/x-www-form-urlencoded。只有設置Content-Type 為application/x-www-form-urlencoded,才會以表單數據的形式提交。另外,我們也可以將Content-Type 設置為application/json 來提交JSON 數據,或者設置為multipart/form-data 來上傳文件。表2 列出了Content-Type 和POST 提交數據方式的關係。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

表2 Content-Type 和POST 提交數據方式的關係

在爬蟲中,如果要構造POST 請求,需要使用正確的Content-Type,並瞭解各種請求庫的各個參數設置時使用的是哪種Content-Type,不然可能會導致POST 提交後無法正常響應。

六、響應

響應,由服務端返回給客戶端,可以分為三部分:響應狀態碼(Response Status Code)、響應頭(Response Headers)和響應體(Response Body)。

1. 響應狀態碼

響應狀態碼錶示服務器的響應狀態,如200 代表服務器正常響應,404 代表頁面未找到,500 代表服務器內部發生錯誤。在爬蟲中,我們可以根據狀態碼來判斷服務器響應狀態,如狀態碼為200,則證明成功返回數據,再進行進一步的處理,否則直接忽略。表3 列出了常見的錯誤代碼及錯誤原因。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

表3 常見的錯誤代碼及錯誤原因

2. 響應頭

響應頭包含了服務器對請求的應答信息,如Content-Type、Server、Set-Cookie 等。下面簡要說明一些常用的頭信息。

  • Date:標識響應產生的時間。
  • Last-Modified:指定資源的最後修改時間。
  • Content-Encoding:指定響應內容的編碼。
  • Server:包含服務器的信息,比如名稱、版本號等。
  • Content-Type:文檔類型,指定返回的數據類型是什麼,如text/html 代表返回HTML 文檔,application/x-javascript 則代表返回JavaScript 文件,image/jpeg 則代表返回圖片。
  • Set-Cookie:設置Cookies。響應頭中的Set-Cookie 告訴瀏覽器需要將此內容放在Cookies中,下次請求攜帶Cookies 請求。
  • Expires:指定響應的過期時間,可以使代理服務器或瀏覽器將加載的內容更新到緩存中。如果再次訪問時,就可以直接從緩存中加載,降低服務器負載,縮短加載時間。

3. 響應體

最重要的當屬響應體的內容了。響應的正文數據都在響應體中,比如請求網頁時,它的響應體就是網頁的HTML 代碼;請求一張圖片時,它的響應體就是圖片的二進制數據。我們做爬蟲請求網頁後,要解析的內容就是響應體,如圖8 所示。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖8 響應體內容

在瀏覽器開發者工具中點擊Preview,就可以看到網頁的源代碼,也就是響應體的內容,它是解析的目標。

在做爬蟲時,我們主要通過響應體得到網頁的源代碼、JSON 數據等,然後從中做相應內容的提取。

七、總結

上面,我們瞭解了HTTP 的基本原理,大概瞭解了訪問網頁時背後的請求和響應過程。上面涉及的知識點需要好好掌握,因為分析網頁請求時會經常用到。

網頁基礎

用瀏覽器訪問網站時,頁面各不相同,你有沒有想過它為何會呈現這個樣子呢?下面,我們就來了解一下網頁的基本組成、結構和節點等內容。

一、網頁的組成

網頁可以分為三大部分——HTML、CSS 和JavaScript。如果把網頁比作一個人的話,HTML 相當於骨架,JavaScript 相當於肌肉,CSS 相當於皮膚,三者結合起來才能形成一個完善的網頁。下面我們分別來介紹一下這三部分的功能。

1. HTML

HTML 是用來描述網頁的一種語言,其全稱叫作Hyper Text Markup Language,即超文本標記語言。網頁包括文字、按鈕、圖片和視頻等各種複雜的元素,其基礎架構就是HTML。不同類型的文字通過不同類型的標籤來表示,如圖片用img 標籤表示,視頻用video 標籤表示,段落用p 標籤表示,它們之間的佈局又常通過佈局標籤div 嵌套組合而成,各種標籤通過不同的排列和嵌套才形成了網頁的框架。

在Chrome 瀏覽器中打開百度,右擊並選擇“檢查”項(或按F12 鍵),打開開發者模式,這時在Elements 選項卡中即可看到網頁的源代碼,如圖9 所示。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖9 源代碼

這就是HTML,整個網頁就是由各種標籤嵌套組合而成的。這些標籤定義的節點元素相互嵌套和組合形成了複雜的層次關係,就形成了網頁的架構。

2. CSS

HTML 定義了網頁的結構,但是隻有HTML 頁面的佈局並不美觀,可能只是簡單的節點元素的排列,為了讓網頁看起來更好看一些,這裡藉助了CSS。

CSS,全稱叫作Cascading Style Sheets,即層疊樣式表。“層疊”是指當在HTML 中引用了數個樣式文件,並且樣式發生衝突時,瀏覽器能依據層疊順序處理。“樣式”指網頁中文字大小、顏色、元素間距、排列等格式。

CSS 是目前唯一的網頁頁面排版樣式標準,有了它的幫助,頁面才會變得更為美觀。

上面圖9 中右側即為CSS,例如:

#head_wrapper.s-ps-islite .s-p-top {
position: absolute;
bottom: 40px;
width: 100%;
height: 181px;
}

就是一個CSS 樣式。大括號前面是一個CSS 選擇器。此選擇器的意思是首先選中id 為head_wrapper且class 為s-ps-islite 的節點,然後再選中其內部的class 為s-p-top 的節點。大括號內部寫的就是一條條樣式規則,例如position 指定了這個元素的佈局方式為絕對佈局,bottom 指定元素的下邊距為40 像素,width 指定了寬度為100%佔滿父元素,height 則指定了元素的高度。也就是說,我們將位置、寬度、高度等樣式配置統一寫成這樣的形式,然後用大括號括起來,接著在開頭再加上CSS 選擇器,這就代表這個樣式對CSS 選擇器選中的元素生效,元素就會根據此樣式來展示了。

在網頁中,一般會統一定義整個網頁的樣式規則,並寫入CSS 文件中(其後綴為css)。在HTML中,只需要用link 標籤即可引入寫好的CSS 文件,這樣整個頁面就會變得美觀、優雅。

3. JavaScript

JavaScript,簡稱JS,是一種腳本語言。HTML 和CSS 配合使用,提供給用戶的只是一種靜態信息,缺乏交互性。我們在網頁裡可能會看到一些交互和動畫效果,如下載進度條、提示框、輪播圖等,這通常就是JavaScript 的功勞。它的出現使得用戶與信息之間不只是一種瀏覽與顯示的關係,而是實現了一種實時、動態、交互的頁面功能。

JavaScript 通常也是以單獨的文件形式加載的,後綴為js,在HTML 中通過script 標籤即可引入,例如:

<script src="jquery-2.1.0.js"></script>

綜上所述,HTML 定義了網頁的內容和結構,CSS 描述了網頁的佈局,JavaScript 定義了網頁的行為。

二、網頁的結構

我們首先用例子來感受一下HTML 的基本結構。新建一個文本文件,名稱可以自取,後綴為html,內容如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>This is a Demo</title>
</head>
<body>
<div id="container">
<div class="wrapper">
<h2 class="title">Hello World</h2>
<p class="text">Hello, this is a paragraph.</p>
</div>
</div>
</body>
</html>

這就是一個最簡單的HTML 實例。開頭用DOCTYPE 定義了文檔類型,其次最外層是html 標籤,最後還有對應的結束標籤來表示閉合,其內部是head 標籤和body 標籤,分別代表網頁頭和網頁體,它們也需要結束標籤。head 標籤內定義了一些頁面的配置和引用,如:

<meta charset="UTF-8">

它指定了網頁的編碼為UTF-8。

title 標籤則定義了網頁的標題,會顯示在網頁的選項卡中,不會顯示在正文中。body 標籤內則是在網頁正文中顯示的內容。div 標籤定義了網頁中的區塊,它的id 是container,這是一個非常常用的屬性,且id 的內容在網頁中是唯一的,我們可以通過它來獲取這個區塊。然後在此區塊內又有一個div 標籤,它的class 為wrapper,這也是一個非常常用的屬性,經常與CSS 配合使用來設定樣式。然後此區塊內部又有一個h2 標籤,這代表一個二級標題。另外,還有一個p 標籤,這代表一個段落。在這兩者中直接寫入相應的內容即可在網頁中呈現出來,它們也有各自的class 屬性。

將代碼保存後,在瀏覽器中打開該文件,可以看到如圖10 所示的內容。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖10 運行結果

可以看到,在選項卡上顯示了This is a Demo 字樣,這是我們在head 中的title 裡定義的文字。而網頁正文是body 標籤內部定義的各個元素生成的,可以看到這裡顯示了二級標題和段落。

這個實例便是網頁的一般結構。一個網頁的標準形式是html 標籤內嵌套head 和body 標籤,head內定義網頁的配置和引用,body 內定義網頁的正文。

三、節點樹及節點間的關係

在HTML 中,所有標籤定義的內容都是節點,它們構成了一個HTML DOM 樹。

我們先看下什麼是DOM。DOM 是W3C(萬維網聯盟)的標準,其英文全稱Document Object Model,即文檔對象模型。它定義了訪問HTML 和XML 文檔的標準:

W3C 文檔對象模型(DOM)是中立於平臺和語言的接口,它允許程序和腳本動態地訪問和更新文檔的內容、結構和樣式。

W3C DOM 標準被分為3 個不同的部分。

  • 核心DOM:針對任何結構化文檔的標準模型
  • XML DOM:針對XML 文檔的標準模型
  • HTML DOM:針對HTML 文檔的標準模型

根據W3C 的HTML DOM 標準,HTML 文檔中的所有內容都是節點。

  • 整個文檔是一個文檔節點
  • 每個HTML 元素是元素節點
  • HTML 元素內的文本是文本節點
  • 每個HTML 屬性是屬性節點
  • 註釋是註釋節點

HTML DOM 將HTML 文檔視作樹結構,這種結構被稱為節點樹,如圖11 所示。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖11 節點樹

通過HTML DOM,樹中的所有節點均可通過JavaScript 訪問,所有HTML 節點元素均可被修改,也可以被創建或刪除。

節點樹中的節點彼此擁有層級關係。我們常用父(parent)、子(child)和兄弟(sibling)等術語描述這些關係。父節點擁有子節點,同級的子節點被稱為兄弟節點。

在節點樹中,頂端節點稱為根(root)。除了根節點之外,每個節點都有父節點,同時可擁有任意數量的子節點或兄弟節點。圖12 展示了節點樹以及節點之間的關係。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖12 節點樹及節點間的關係

本段參考W3SCHOOL,鏈接:http://www.w3school.com.cn/htmldom/dom_nodes.asp。

四、選擇器

我們知道網頁由一個個節點組成,CSS 選擇器會根據不同的節點設置不同的樣式規則,那麼怎樣來定位節點呢?

在CSS 中,我們使用CSS 選擇器來定位節點。例如,上例中div 節點的id 為container,那麼就可以表示為#container,其中#開頭代表選擇id,其後緊跟id 的名稱。另外,如果我們想選擇class為wrapper 的節點,便可以使用.wrapper,這裡以點(.)開頭代表選擇class,其後緊跟class 的名稱。

另外,還有一種選擇方式,那就是根據標籤名篩選,例如想選擇二級標題,直接用h2 即可。這是最常用的3 種表示,分別是根據id、class、標籤名篩選,請牢記它們的寫法。

另外,CSS 選擇器還支持嵌套選擇,各個選擇器之間加上空格分隔開便可以代表嵌套關係,如#container .wrapper p 則代表先選擇id 為container 的節點,然後選中其內部的class 為wrapper 的節點,然後再進一步選中其內部的p 節點。另外,如果不加空格,則代表並列關係,如div#container .wrapperp.text 代表先選擇id 為container 的div 節點,然後選中其內部的class 為wrapper 的節點,再進一步選中其內部的class 為text 的p 節點。這就是CSS 選擇器,其篩選功能還是非常強大的。

另外,CSS 選擇器還有一些其他語法規則,具體如表4 所示。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

表4 CSS 選擇器的其他語法規則

另外,還有一種比較常用的選擇器是XPath,這種選擇方式本文暫不介紹。

五、總結

本節介紹了網頁的基本結構和節點間的關係,瞭解了這些內容,我們才有更加清晰的思路去解析和提取網頁內容。

爬蟲的基本原理

一、爬蟲概述

簡單來說,爬蟲就是獲取網頁並提取和保存信息的自動化程序,下面概要介紹一下。

1. 獲取網頁

爬蟲首先要做的工作就是獲取網頁,這裡就是獲取網頁的源代碼。源代碼裡包含了網頁的部分有用信息,所以只要把源代碼獲取下來,就可以從中提取想要的信息了。

前面講了請求和響應的概念,向網站的服務器發送一個請求,返回的響應體便是網頁源代碼。所以,最關鍵的部分就是構造一個請求併發送給服務器,然後接收到響應並將其解析出來,那麼這個流程怎樣實現呢?總不能手工去截取網頁源碼吧?

不用擔心,Python 提供了許多庫來幫助我們實現這個操作,如 urllib、requests 等。我們可以用這些庫來幫助我們實現 HTTP 請求操作,請求和響應都可以用類庫提供的數據結構來表示,得到響應之後只需要解析數據結構中的 Body 部分即可,即得到網頁的源代碼,這樣我們可以用程序來實現獲取網頁的過程了。

2. 提取信息

獲取網頁源代碼後,接下來就是分析網頁源代碼,從中提取我們想要的數據。首先,最通用的方法便是採用正則表達式提取,這是一個萬能的方法,但是在構造正則表達式時比較複雜且容易出錯。另外,由於網頁的結構有一定的規則,所以還有一些根據網頁節點屬性、CSS 選擇器或 XPath 來提取網頁信息的庫,如 Beautiful Soup、pyquery、lxml 等。使用這些庫,我們可以高效快速地從中提取網頁信息,如節點的屬性、文本值等。

提取信息是爬蟲非常重要的部分,它可以使雜亂的數據變得條理清晰,以便我們後續處理和分析數據。

3. 保存數據

提取信息後,我們一般會將提取到的數據保存到某處以便後續使用。這裡保存形式有多種多樣,如可以簡單保存為 TXT 文本或 JSON 文本,也可以保存到數據庫,如 MySQL 和 MongoDB 等,也可保存至遠程服務器,如藉助 SFTP 進行操作等。

4. 自動化程序

說到自動化程序,意思是說爬蟲可以代替人來完成這些操作。首先,我們手工當然可以提取這些信息,但是當量特別大或者想快速獲取大量數據的話,肯定還是要藉助程序。爬蟲就是代替我們來完成這份爬取工作的自動化程序,它可以在抓取過程中進行各種異常處理、錯誤重試等操作,確保爬取持續高效地運行。

二、能抓怎樣的數據

在網頁中我們能看到各種各樣的信息,最常見的便是常規網頁,它們對應著 HTML 代碼,而最常抓取的便是 HTML 源代碼。

另外,可能有些網頁返回的不是 HTML 代碼,而是一個 JSON 字符串(其中 API 接口大多采用這樣的形式),這種格式的數據方便傳輸和解析,它們同樣可以抓取,而且數據提取更加方便。

此外,我們還可以看到各種二進制數據,如圖片、視頻和音頻等。利用爬蟲,我們可以將這些二進制數據抓取下來,然後保存成對應的文件名。

另外,還可以看到各種擴展名的文件,如 CSS、JavaScript 和配置文件等,這些其實也是最普通的文件,只要在瀏覽器裡面可以訪問到,就可以將其抓取下來。

上述內容其實都對應各自的 URL,是基於 HTTP 或 HTTPS 協議的,只要是這種數據,爬蟲都可以抓取。

三、JavaScript 渲染頁面

有時候,我們在用 urllib 或 requests 抓取網頁時,得到的源代碼實際和瀏覽器中看到的不一樣。

這是一個非常常見的問題。現在網頁越來越多地採用 Ajax、前端模塊化工具來構建,整個網頁可能都是由 JavaScript 渲染出來的,也就是說原始的 HTML 代碼就是一個空殼,例如:

<!DOCTYPE html> 
<html>
<head>
<meta charset="UTF-8">
<title>This is a Demo</title>
</head>
<body>
<div id="container">
</div>
</body>
<script src="app.js"></script>
</html>

body 節點裡面只有一個 id 為 container 的節點,但是需要注意在 body 節點後引入了 app.js,它便負責整個網站的渲染。

在瀏覽器中打開這個頁面時,首先會加載這個 HTML 內容,接著瀏覽器會發現其中引入了一個app.js 文件,然後便會接著去請求這個文件,獲取到該文件後,便會執行其中的 JavaScript 代碼,而JavaScript 則會改變 HTML 中的節點,向其添加內容,最後得到完整的頁面。

但是在用 urllib 或 requests 等庫請求當前頁面時,我們得到的只是這個 HTML 代碼,它不會幫助我們去繼續加載這個 JavaScript 文件,這樣也就看不到瀏覽器中的內容了。

這也解釋了為什麼有時我們得到的源代碼和瀏覽器中看到的不一樣。

因此,使用基本 HTTP 請求庫得到的源代碼可能跟瀏覽器中的頁面源代碼不太一樣。對於這樣的情況,我們可以分析其後臺 Ajax 接口,也可使用 Selenium、Splash 這樣的庫來實現模擬 JavaScript 渲染。

四、總結

本節介紹了爬蟲的一些基本原理,這可以幫助我們在後面編寫爬蟲時更加得心應手。

會話和Cookies

在瀏覽網站的過程中,我們經常會遇到需要登錄的情況,有些頁面只有登錄之後才可以訪問,而且登錄之後可以連續訪問很多次網站,但是有時候過一段時間就需要重新登錄。還有一些網站,在打開瀏覽器時就自動登錄了,而且很長時間都不會失效,這種情況又是為什麼?其實這裡面涉及會話(Session)和Cookies 的相關知識,本節就來揭開它們的神祕面紗。

一、靜態網頁和動態網頁

在開始之前,我們需要先了解一下靜態網頁和動態網頁的概念。這裡還是前面的示例代碼,內容如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>This is a Demo</title>
</head>
<body>
<div id="container">
<div class="wrapper">
<h2 class="title">Hello World</h2>
<p class="text">Hello, this is a paragraph.</p>
</div>
</div>
</body>
</html>

這是最基本的HTML 代碼,我們將其保存為一個.html 文件,然後把它放在某臺具有固定公網IP的主機上,主機上裝上Apache 或Nginx 等服務器,這樣這臺主機就可以作為服務器了,其他人便可以通過訪問服務器看到這個頁面,這就搭建了一個最簡單的網站。

這種網頁的內容是HTML 代碼編寫的,文字、圖片等內容均通過寫好的HTML 代碼來指定,這種頁面叫作靜態網頁。它加載速度快,編寫簡單,但是存在很大的缺陷,如可維護性差,不能根據URL 靈活多變地顯示內容等。例如,我們想要給這個網頁的URL 傳入一個name 參數,讓其在網頁中顯示出來,是無法做到的。

因此,動態網頁應運而生,它可以動態解析URL 中參數的變化,關聯數據庫並動態呈現不同的頁面內容,非常靈活多變。我們現在遇到的大多數網站都是動態網站,它們不再是一個簡單的HTML,而是可能由JSP、PHP、Python 等語言編寫的,其功能比靜態網頁強大和豐富太多了。

此外,動態網站還可以實現用戶登錄和註冊的功能。再回到開頭提到的問題,很多頁面是需要登錄之後才可以查看的。按照一般的邏輯來說,輸入用戶名和密碼登錄之後,肯定是拿到了一種類似憑證的東西,有了它,我們才能保持登錄狀態,才能訪問登錄之後才能看到的頁面。

那麼,這種神祕的憑證到底是什麼呢?其實它就是會話和Cookies 共同產生的結果,下面我們來一探究竟。

二、無狀態HTTP

在瞭解會話和Cookies 之前,我們還需要了解HTTP 的一個特點,叫作無狀態。

HTTP 的無狀態是指HTTP 協議對事務處理是沒有記憶能力的,也就是說服務器不知道客戶端是什麼狀態。當我們向服務器發送請求後,服務器解析此請求,然後返回對應的響應,服務器負責完成這個過程,而且這個過程是完全獨立的,服務器不會記錄前後狀態的變化,也就是缺少狀態記錄。這意味著如果後續需要處理前面的信息,則必須重傳,這導致需要額外傳遞一些前面的重複請求,才能獲取後續響應,然而這種效果顯然不是我們想要的。為了保持前後狀態,我們肯定不能將前面的請求全部重傳一次,這太浪費資源了,對於這種需要用戶登錄的頁面來說,更是棘手。

這時兩個用於保持HTTP 連接狀態的技術就出現了,它們分別是會話和Cookies。會話在服務端,也就是網站的服務器,用來保存用戶的會話信息;Cookies 在客戶端,也可以理解為瀏覽器端,有了Cookies,瀏覽器在下次訪問網頁時會自動附帶上它發送給服務器,服務器通過識別Cookies 並鑑定出是哪個用戶,然後再判斷用戶是否是登錄狀態,然後返回對應的響應。

我們可以理解為Cookies 裡面保存了登錄的憑證,有了它,只需要在下次請求攜帶Cookies 發送請求而不必重新輸入用戶名、密碼等信息重新登錄了。

因此在爬蟲中,有時候處理需要登錄才能訪問的頁面時,我們一般會直接將登錄成功後獲取的Cookies 放在請求頭裡面直接請求,而不必重新模擬登錄。

好了,瞭解會話和Cookies 的概念之後,我們在來詳細剖析它們的原理。

1. 會話

會話,其本來的含義是指有始有終的一系列動作/消息。比如,打電話時,從拿起電話撥號到掛斷電話這中間的一系列過程可以稱為一個會話。

而在Web 中,會話對象用來存儲特定用戶會話所需的屬性及配置信息。這樣,當用戶在應用程序的Web 頁之間跳轉時,存儲在會話對象中的變量將不會丟失,而是在整個用戶會話中一直存在下去。

當用戶請求來自應用程序的Web 頁時,如果該用戶還沒有會話,則Web 服務器將自動創建一個會話對象。當會話過期或被放棄後,服務器將終止該會話。

2. Cookies

Cookies 指某些網站為了辨別用戶身份、進行會話跟蹤而存儲在用戶本地終端上的數據。

● 會話維持

那麼,我們怎樣利用Cookies 保持狀態呢?當客戶端第一次請求服務器時,服務器會返回一個請求頭中帶有Set-Cookie 字段的響應給客戶端,用來標記是哪一個用戶,客戶端瀏覽器會把Cookies 保存起來。當瀏覽器下一次再請求該網站時,瀏覽器會把此Cookies 放到請求頭一起提交給服務器,Cookies 攜帶了會話ID 信息,服務器檢查該Cookies 即可找到對應的會話是什麼,然後再判斷會話來以此來辨認用戶狀態。

在成功登錄某個網站時,服務器會告訴客戶端設置哪些Cookies 信息,在後續訪問頁面時客戶端會把Cookies 發送給服務器,服務器再找到對應的會話加以判斷。如果會話中的某些設置登錄狀態的變量是有效的,那就證明用戶處於登錄狀態,此時返回登錄之後才可以查看的網頁內容,瀏覽器再進行解析便可以看到了。

反之,如果傳給服務器的Cookies 是無效的,或者會話已經過期了,我們將不能繼續訪問頁面,此時可能會收到錯誤的響應或者跳轉到登錄頁面重新登錄。

所以,Cookies 和會話需要配合,一個處於客戶端,一個處於服務端,二者共同協作,就實現了登錄會話控制。

● 屬性結構

接下來,我們來看看Cookies 都有哪些內容。這裡以知乎為例,在瀏覽器開發者工具中打開Application 選項卡,然後在左側會有一個Storage 部分,最後一項即為Cookies,將其點開,如圖13所示,這些就是Cookies。

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

圖13 Cookies 列表

可以看到,這裡有很多條目,其中每個條目可以稱為Cookie。它有如下幾個屬性。

  • Name:該Cookie 的名稱。一旦創建,該名稱便不可更改。
  • Value:該Cookie 的值。如果值為Unicode 字符,需要為字符編碼。如果值為二進制數據,則需要使用BASE64 編碼。
  • Domain:可以訪問該Cookie的域名。例如,如果設置為.zhihu.com,則所有以zhihu.com結尾的域名都可以訪問該Cookie。
  • Max Age:該Cookie 失效的時間,單位為秒,也常和Expires 一起使用,通過它可以計算出其有效時間。Max Age 如果為正數,則該Cookie 在Max Age 秒之後失效。如果為負數,則關閉瀏覽器時Cookie 即失效,瀏覽器也不會以任何形式保存該Cookie。
  • Path:該Cookie 的使用路徑。如果設置為/path/,則只有路徑為/path/的頁面可以訪問該Cookie。如果設置為/,則本域名下的所有頁面都可以訪問該Cookie。
  • Size 字段:此Cookie 的大小。
  • HTTP 字段:Cookie 的httponly 屬性。若此屬性為true,則只有在HTTP 頭中會帶有此Cookie 的信息,而不能通過document.cookie 來訪問此Cookie。
  • Secure:該Cookie 是否僅被使用安全協議傳輸。安全協議有HTTPS 和SSL 等,在網絡上傳輸數據之前先將數據加密。默認為false。

● 會話Cookie 和持久Cookie

從表面意思來說,會話Cookie 就是把Cookie 放在瀏覽器內存裡,瀏覽器在關閉之後該Cookie 即失效;持久Cookie 則會保存到客戶端的硬盤中,下次還可以繼續使用,用於長久保持用戶登錄狀態。

其實嚴格來說,沒有會話Cookie 和持久Cookie 之分,只是由Cookie 的Max Age 或Expires 字段決定了過期的時間。

因此,一些持久化登錄的網站其實就是把Cookie 的有效時間和會話有效期設置得比較長,下次我們再訪問頁面時仍然攜帶之前的Cookie,就可以直接保持登錄狀態。

三、常見誤區

在談論會話機制的時候,常常聽到這樣一種誤解——“只要關閉瀏覽器,會話就消失了”。可以想象一下會員卡的例子,除非顧客主動對店家提出銷卡,否則店家絕對不會輕易刪除顧客的資料。對會話來說,也是一樣,除非程序通知服務器刪除一個會話,否則服務器會一直保留。比如,程序一般都是在我們做註銷操作時才去刪除會話。

但是當我們關閉瀏覽器時,瀏覽器不會主動在關閉之前通知服務器它將要關閉,所以服務器根本不會有機會知道瀏覽器已經關閉。之所以會有這種錯覺,是因為大部分會話機制都使用會話Cookie來保存會話ID 信息,而關閉瀏覽器後Cookies 就消失了,再次連接服務器時,也就無法找到原來的會話了。如果服務器設置的Cookies 保存到硬盤上,或者使用某種手段改寫瀏覽器發出的HTTP 請求頭,把原來的Cookies 發送給服務器,則再次打開瀏覽器,仍然能夠找到原來的會話 ID,依舊還是可以保持登錄狀態的。

而且恰恰是由於關閉瀏覽器不會導致會話被刪除,這就需要服務器為會話設置一個失效時間,當距離客戶端上一次使用會話的時間超過這個失效時間時,服務器就可以認為客戶端已經停止了活動,才會把會話刪除以節省存儲空間。

由於涉及一些專業名詞知識,本節的部分內容參考來源如下。

會話百度百科:https://baike.baidu.com/item/session/479100。

Cookies 百度百科:https://baike.baidu.com/item/cookie/1119。

HTTP Cookie 維基百科:https://en.wikipedia.org/wiki/HTTP_cookie。

會話和幾種狀態保持方案理解:http://www.mamicode.com/info-detail-46545.html。

代理的基本原理

我們在做爬蟲的過程中經常會遇到這樣的情況,最初爬蟲正常運行,正常抓取數據,一切看起來都是那麼美好,然而一杯茶的功夫可能就會出現錯誤,比如403 Forbidden,這時候打開網頁一看,可能會看到“您的IP 訪問頻率太高”這樣的提示。出現這種現象的原因是網站採取了一些反爬蟲措施。

比如,服務器會檢測某個IP 在單位時間內的請求次數,如果超過了這個閾值,就會直接拒絕服務,返回一些錯誤信息,這種情況可以稱為封IP。

既然服務器檢測的是某個IP 單位時間的請求次數,那麼藉助某種方式來偽裝我們的IP,讓服務器識別不出是由我們本機發起的請求,不就可以成功防止封IP 了嗎?

一種有效的方式就是使用代理,後面會詳細說明代理的用法。在這之前,需要先了解下代理的基本原理,它是怎樣實現IP 偽裝的呢?

一、基本原理

代理實際上指的就是代理服務器,英文叫作proxy server,它的功能是代理網絡用戶去取得網絡信息。形象地說,它是網絡信息的中轉站。在我們正常請求一個網站時,是發送了請求給Web 服務器,Web 服務器把響應傳回給我們。如果設置了代理服務器,實際上就是在本機和服務器之間搭建了一個橋,此時本機不是直接向Web 服務器發起請求,而是向代理服務器發出請求,請求會發送給代理服務器,然後由代理服務器再發送給Web 服務器,接著由代理服務器再把Web 服務器返回的響應轉發給本機。這樣我們同樣可以正常訪問網頁,但這個過程中Web 服務器識別出的真實IP 就不再是我們本機的IP 了,就成功實現了IP 偽裝,這就是代理的基本原理。

二、代理的作用

那麼,代理有什麼作用呢?我們可以簡單列舉如下。

  • 突破自身IP 訪問限制,訪問一些平時不能訪問的站點。
  • 訪問一些單位或團體內部資源:比如使用教育網內地址段免費代理服務器,就可以用於對教育網開放的各類FTP 下載上傳,以及各類資料查詢共享等服務。
  • 提高訪問速度:通常代理服務器都設置一個較大的硬盤緩衝區,當有外界的信息通過時,同時也將其保存到緩衝區中,當其他用戶再訪問相同的信息時,則直接由緩衝區中取出信息,傳給用戶,以提高訪問速度。
  • 隱藏真實IP:上網者也可以通過這種方法隱藏自己的IP,免受攻擊。對於爬蟲來說,我們用代理就是為了隱藏自身IP,防止自身的IP 被封鎖。

三、爬蟲代理

對於爬蟲來說,由於爬蟲爬取速度過快,在爬取過程中可能遇到同一個IP 訪問過於頻繁的問題,此時網站就會讓我們輸入驗證碼登錄或者直接封鎖IP,這樣會給爬取帶來極大的不便。

使用代理隱藏真實的IP,讓服務器誤以為是代理服務器在請求自己。這樣在爬取過程中通過不斷更換代理,就不會被封鎖,可以達到很好的爬取效果。

四、代理分類

代理分類時,既可以根據協議區分,也可以根據其匿名程度區分。

1. 根據協議區分

根據代理的協議,代理可以分為如下類別。

  • FTP 代理服務器:主要用於訪問FTP 服務器,一般有上傳、下載以及緩存功能,端口一般為21、2121 等。
  • HTTP 代理服務器:主要用於訪問網頁,一般有內容過濾和緩存功能,端口一般為80、8080、3128 等。
  • SSL/TLS 代理:主要用於訪問加密網站,一般有SSL 或TLS 加密功能(最高支持128 位加密強度),端口一般為443。
  • RTSP 代理:主要用於訪問Real 流媒體服務器,一般有緩存功能,端口一般為554。
  • Telnet 代理:主要用於telnet 遠程控制(黑客入侵計算機時常用於隱藏身份),端口一般為23。
  • POP3/SMTP 代理:主要用於POP3/SMTP 方式收發郵件,一般有緩存功能,端口一般為110/25。
  • SOCKS 代理:只是單純傳遞數據包,不關心具體協議和用法,所以速度快很多,一般有緩存功能,端口一般為1080。SOCKS代理協議又分為SOCKS4和SOCKS5,前者只支持TCP,而後者支持TCP 和UDP,還支持各種身份驗證機制、服務器端域名解析等。簡單來說,SOCKS4 能做到的SOCKS5 都可以做到,但SOCKS5 能做到的SOCKS4 不一定能做到。

2. 根據匿名程度區分

根據代理的匿名程度,代理可以分為如下類別。

  • 高度匿名代理:會將數據包原封不動地轉發,在服務端看來就好像真的是一個普通客戶端在訪問,而記錄的IP 是代理服務器的IP。
  • 普通匿名代理:會在數據包上做一些改動,服務端上有可能發現這是個代理服務器,也有一定機率追查到客戶端的真實IP。代理服務器通常會加入的HTTP頭有HTTP_VIA和HTTP_X_FORWARDED_FOR。
  • 透明代理:不但改動了數據包,還會告訴服務器客戶端的真實IP。這種代理除了能用緩存技術提高瀏覽速度,能用內容過濾提高安全性之外,並無其他顯著作用,最常見的例子是內網中的硬件防火牆。
  • 間諜代理:指組織或個人創建的用於記錄用戶傳輸的數據,然後進行研究、監控等目的的代理服務器。

五、常見代理設置

  • 使用網上的免費代理:最好使用高匿代理,另外可用的代理不多,需要在使用前篩選一下可用代理,也可以進一步維護一個代理池。
  • 使用付費代理服務:互聯網上存在許多代理商,可以付費使用,質量比免費代理好很多。
  • ADSL 撥號:撥一次號換一次IP,穩定性高,也是一種比較有效的解決方案。

由於涉及一些專業名詞知識,本節的部分內容參考來源如下。

代理服務器維基百科:https://zh.wikipedia.org/wiki/代理服務器。

代理百度百科:https://baike.baidu.com/item/代理/3242667。

——本文節選自《Python 3網絡爬蟲開發實戰》

從沒想過,爬蟲基礎知識能講這麼簡單! // Python網絡爬蟲實戰

崔慶才 著

《Python 3網絡爬蟲開發實戰》

百萬訪問量博客作者靜覓力作!

作者博客:https://cuiqingcai.com/

為什麼會寫這本書?

我是在 2015 年開始接觸爬蟲的,當時爬蟲其實並沒有這麼火,我當時覺得能夠把想要的數據抓取下來就是一件非常有成就感的事情,而且也可以順便熟悉 Python,一舉兩得。

在學習的過程中,困難其實是非常多的,最早學習時使用的是 Python 2,當時因為編碼問題搞得焦頭爛額。另外,那時候相關的中文資料還比較少,很多情況下還得自己慢慢去啃官方文檔,踩了不少坑。隨著學習的進行,我發現爬蟲這部分內容涉及的知識點太多、太雜了。網頁的結構、渲染方式不同,我們就得換不同的爬取方案來進行鍼對性的爬取。另外,網頁信息的提取、爬取結果的保存也有五花八門的方案。隨著移動互聯網的興起,App 的爬取也成了一個熱點,而為了提高爬取速度又需要考慮並行爬取、分佈式爬取方面的內容,爬蟲的通用性、易用性、架構都需要好好優化。這麼多雜糅的知識點對於一個爬蟲初學者來說,學習的挑戰性會非常高,同時學習過程中大家或許也會走我之前走過的彎路,浪費很多時間。所以我把我學習爬蟲的很多經驗都寫了進了書中。

環境配置是學習的第一步,環境配置不好,其他工作就沒法開展,甚至可能很大程度上打擊學習的積極性,所以我在第1 章中著重介紹了環境的配置過程。而因為操作系統的不同,環境配置過程又各有不同,所以我把每個系統(Windows、Linux、Mac)的環境配置過程都親自實踐了一遍,並梳理記錄下來,希望為各位讀者在環境配置時多提供一些幫助。後面我又針對爬蟲網站的不同情形分門別類地進行了說明,如Ajax 分析爬取、動態渲染頁面爬取、App 爬取、使用代理爬取、模擬登錄爬取等知識,每個知識點我都選取了一些典型案例來說明,以便於讀者更好地理解整個過程和用法。為了提高代碼編寫和爬取的效率,還可以使用一些爬蟲框架輔助爬取,所以本書後面又介紹了兩個流行的爬蟲框架的用法,最後又介紹了一些分佈式爬蟲及部署方面的知識。總體來說,本書根據我個人覺得比較理想的學習路徑介紹了學習爬蟲的相關知識,並通過一些實戰案例幫助讀者更好地理解其中的原理。

第1章 開發環境配置

第2章 爬蟲基礎

第3章 基本庫的使用

第4章 解析庫的使用

第5章 數據存儲

第6章 Ajax數據爬取

第7章 動態渲染頁面爬取

第8章 驗證碼的識別

第9章 代理的使用

第10章 模擬登錄

第11章 App的爬取

第12章 pyspider框架的使用

第13章 Scrapy框架的使用

第14章 分佈式爬蟲

第15章 分佈式爬蟲的部署

相關推薦

推薦中...