透過前面的介紹,小猿們已經弄清楚了爬蟲是什麼,它是幹什麼的。接下來我們就開始在技術層面上探究一下它是如何工作的。
網際網路上,公開資料(各種網頁)都是以http(或加密的http即https)協議傳輸的。所以,我們這裡介紹的爬蟲技術都是基於http(https)協議的爬蟲。
在Python的模組海洋裡,支援http協議的模組是相當豐富的,既有官方的urllib,也有大名鼎鼎的社群(第三方)模組 requests。它們都很好的封裝了http協議請求的各種方法,因此,我們只需要熟悉這些模組的用法,不再進一步討論http協議本身。
認識瀏覽器和伺服器
小猿們對瀏覽器應該一點都不陌生,可以說,只要上過網的人都知道瀏覽器。可是,明白瀏覽器各種原理的小猿可不一定多哦。
作為要開發爬蟲的小猿,是一定一定要明白瀏覽器的工作原理的。這是你寫爬蟲的必備工具,別無他。
不知道的小猿們在面試的時候,有沒有遇到這麼一個非常宏觀而又處處細節的解答題:
- 請說說從你在瀏覽器位址列輸入網站到你看到網頁中間都發生了什麼?
這真是一個考驗知識面的題啊,經驗老道的老猿既可以滔滔不絕的講上三天三夜,也可以提煉出幾分鐘的精華講個大概。而小猿們恐怕對整個過程就一知半解了。
巧的是,對這個問題理解的越透徹,越對寫爬蟲有幫助。換句話說,爬蟲是一個考驗綜合技能的領域。那麼,小猿們準備好迎接這個綜合技能挑戰了嗎?
廢話不多說,我們就從解答這個題目開始,認識瀏覽器和伺服器,看看這中間有哪些知識是爬蟲要用到的。
前面也說過,這個問題可以講上三天三夜,但我們沒那麼多時間,其中一些細節就略過,把大致流程結合爬蟲講一講,分成三部分:
- 瀏覽器發出請求
- 伺服器做出響應
- 瀏覽器接收響應
1. 瀏覽器發出請求
在瀏覽器位址列輸入網址後回車,瀏覽器請伺服器提出網頁請求,也就是告訴伺服器,我要看你的某個網頁。
上面短短一句話,蘊藏了無數玄機啊,讓我不得不費點口舌一一道來。主要講述:
- 網址是不是有效的?
- 伺服器在哪裡?
- 瀏覽器向伺服器傳送了些什麼?
- 伺服器返回了些什麼?
1) 網址是不是有效的?
首先,瀏覽器要判斷你輸入的網址(URL)是否合法有效。對應URL,小猿們並不陌生吧,以http(s)開頭的那一長串的字元,但是你知道它還可以以ftp, mailto, file, data, irc開頭嗎?下面是它最完整的語法格式:
URI = scheme:[//authority]path[?query][#fragment]
# 其中, authority 又是這樣的:
authority = [userinfo@]host[:port]
# userinfo可以同時包含user name和password,以:分割
userinfo = [user_name:password]
用圖更形象的表現處理就是這樣的:
老猿經驗:要判斷URL的合法性
Python裡面可以用urllib.parse來進行URL的各種操作
In [1]: import urllib.parse
In [2]: url = 'http://dachong:the_password@www.yuanrenxue.com/user/info?page=2'
In [3]: zz = urllib.parse.urlparse(url)
Out[4]: ParseResult(scheme='http', netloc='dachong:the_password@www.yuanrenxue.com', path='/user/info', params='', query='page=2', fragment='')
我們看到,urlparse函式把URL分析成了6部分:
scheme://netloc/path;params?query#fragment
需要主要的是 netloc 並不等同於 URL 語法定義中的host
2) 伺服器在哪裡?
上面URL定義中的host,就是網際網路上的一臺伺服器,它可以是一個IP地址,但通常是我們所說的域名。域名透過DNS繫結到一個(或多個)IP地址上。瀏覽器要訪問某個域名的網站就要先透過DNS伺服器解析域名,得到真實的IP地址。
這裡的域名解析一般是由作業系統完成的,爬蟲不需要關心。然而,當你寫一個大型爬蟲,像Google、百度搜尋引擎那樣的爬蟲的時候,效率變得很主要,爬蟲就要維護自己的DNS快取。
老猿經驗:大型爬蟲要維護自己的DNS快取
3) 瀏覽器向伺服器傳送些什麼?
瀏覽器獲得了網站伺服器的IP地址,就可以向伺服器傳送請求了。這個請求就是遵循http協議的。寫爬蟲需要關心的就是http協議的headers,下面是訪問 en.wikipedia.org/wiki/URL 時瀏覽器傳送的請求 headers:
小猿們可能已經從圖中看出來些端倪,傳送的http請求頭是類似一個字典的結構:
- authority: 就是訪問的目標機器;
- method: http請求的方法有很多:
- GET
- HEAD
- POST
- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH
一般,爬蟲使用最多的是GET和POST
- path: 訪問的網站的路徑
- scheme: 請求的協議型別,這裡是https
- accept: 能夠接受的回應內容型別(Content-Types)
- accept-encoding: 能夠接受的編碼方式列表
- accept-language: 能夠接受的回應內容的自然語言列表
- cache-control: 指定在這次的請求/響應鏈中的所有快取機制 都必須 遵守的指令
- cookie: 之前由伺服器透過 Set- Cookie傳送的一個 超文字傳輸協議Cookie
這是爬蟲很關心的一個東東,登入資訊都在這裡。 - upgrade-insecuree-requests: 非標準請求欄位,可忽略之。
- user-agent: 瀏覽器身份標識
這也是爬蟲很關心的部分。比如,你需要得到手機版頁面,就要設定瀏覽器身份標識為手機瀏覽器的user-agent。
老猿經驗: 透過設定headers跟伺服器溝通
4) 伺服器返回了些什麼?
如果我們在瀏覽器位址列輸入一個網頁網址(不是檔案下載地址),回車後,很快就看到了一個網頁,裡面包含排版文字、圖片、影片等資料,是一個豐富內容格式的頁面。然而,我透過瀏覽器檢視原始碼,看到的卻是一對文字格式的html程式碼。
沒錯,就是一堆的程式碼,卻讓瀏覽器給渲染成了漂亮的網頁。這對程式碼裡面有:
- css: 瀏覽器根據它來排版,安排文字、圖片等的位置;
- JavaScript: 瀏覽器執行它可以讓使用者和網頁互動;
- 圖片等連結: 瀏覽器再去下載這些連結,最終渲染成網頁。
而我們想要爬取的資訊就藏在html程式碼中,我們可以透過解析方法提取其中我們想要的內容。如果html程式碼裡面沒有我們想要的資料,但是在網頁裡面卻看到了,那就是瀏覽器透過ajax請求非同步載入(偷偷下載)了那部分資料。
這個時候,我們就要透過觀察瀏覽器的載入過程來發現具體是哪個ajax請求載入了我們需要的資料。
這一節說到了瀏覽器,那接下來這一篇我們就來說說:
使用谷歌chrome瀏覽器來抓包吧
我的公眾號:猿人學 Python 上會分享更多心得體會,敬請關注。
***版權申明:若沒有特殊說明,文章皆是猿人學 yuanrenxue.com 原創,沒有猿人學授權,請勿以任何形式轉載。***