第一個爬蟲代碼的實現我想應該是從urllib開始吧,博主開始學習的時候就是使用urllib庫敲了幾行代碼就實現了簡單的爬數據功能,我想大多夥伴們也都是這麼過來的。當時的感受就是:哇,好厲害,短短几行居然就能夠搞定一個看似很複雜的任務,因而就在想這短短的幾行代碼究竟是怎麼實現的呢,如何進行更高級複雜的爬取呢?帶着這個問題我也就開始了urllib庫的學習。html
首先不得不提一下爬取數據的過程,弄清楚這究竟是怎樣一個過程,學習urllib的時候會更方便理解。前端
爬蟲的過程python
其實,爬蟲的過程和瀏覽器瀏覽網頁的過程是同樣的。道理你們應該都明白,就是當咱們在鍵盤上輸入網址點擊搜索以後,經過網絡首先會通過DNS服務器,分析網址的域名,找到了真正的服務器。而後咱們經過HTTP協議對服務器發出GET或POST請求,若請求成功,咱們就獲得了咱們想看到的網頁,通常都是用HTML, CSS, JS等前端技術來構建的,若請求不成功,服務器會返回給咱們請求失敗的狀態碼,常見到的503,403等。瀏覽器
爬蟲的過程亦是如此,經過對服務器發出請求獲得HTML網頁,而後對下載的網頁進行解析,獲得咱們想要的內容。固然,這是一個爬蟲過程的一個概況,其中還有不少細節的東西須要咱們處理的,這些在後續會繼續與你們分享。服務器
瞭解了爬蟲的基本過程後,就能夠開始咱們真正的爬蟲之旅了。網絡
urllib庫socket
Python有一個內置的urllib庫,可謂是爬蟲過程很是重要的一部分了。這個內置庫的使用就能夠完成向服務器發出請求並得到網頁的功能,因此也是學習爬蟲的第一步了。xss
博主用的是Python3.x,urllib庫的結構相對於Python2.x有一些出入,Python2.x中使用的urllib2和urllib庫,而Python3.x中合併成一個惟一的urllib庫。ide
首先,咱們來看看Python3.x的urllib庫都有什麼吧。學習
博主用的IDE是Pycharm,編輯調試很是方便,很贊。
在控制檯下輸入以下代碼:
>>importurllib
>>dir(urllib)
結果:
['__builtins__','__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__','__path__', '__spec__', 'error', 'parse', 'request', 'response']
能夠看到urllib除了以雙下劃線開頭結尾的內置屬性外,還有4個重要的屬性,分別是error,parse,request,response。
在Python的urllib庫中doc開頭是這樣簡短描述的:
Error:「Exception classesraised by urllib.」----就是由urllib舉出的exception類
Parse:「Parse (absolute andrelative) URLs.」----解析絕對和相對的URLs
Request:「An extensiblelibrary for opening URLs using a variety of protocols」
----用各類協議打開URLs的一個擴展庫
Response:「Response classesused by urllib.」----被urllib使用的response類
這4個屬性中最重要的當屬request了,它完成了爬蟲大部分的功能,咱們先來看看request是怎麼用的。
request
request請求最簡單的操做是用urlopen方法,代碼以下
urllib.request response urllib.request.urlopenresult response.readresult
運行結果以下:
b'<!doctype html>\n<!--[if lt IE 7]>...</body>\n</html>\n'
發現獲得的運行結果居然是亂碼!!彆着急,這是由於編碼的問題,咱們只須要將請求的類文件讀取再解碼就能夠了。
修改代碼以下:
urllib.request response urllib.request.urlopenresult response.read.result
運行結果:
<!doctype html>
<!--[if lt IE 7]> <html class="no-js ie6 lt-ie7 lt-ie8>..
<!--[if IE 7]> <html class="no-js ie7 lt-ie8 lt-ie9">..
<!--[if IE 8]> <html class="no-js ie8 lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--><html class="no-js" lang="en" dir="ltr"
<head>
<meta charset="utf-8">
...
獲得的就是咱們想要的html的網頁了,怎麼樣,簡單吧。
下面來介紹一下這個urlopen方法和其中應用的參數。
urlopen
url, data, timeoutsocket._GLOBAL_DEFAULT_TI MEOUT,, cafile, capath, cadefault, context
這個urlopen的功能是打開一個URL,能夠是一串字符串(如上例子中同樣),也能夠是Request對象(後面會提到)。它會返回一個類文件對象,並能夠針對這個對象進行各類操做(如上例中的read操做,將html所有讀出來,後面會介紹其它的幾個操做)。
<1>url:便是咱們輸入的url網址,(如:http://www.xxxx.com/);
<2>data:是咱們要發給服務器請求的額外信息(好比登陸網頁須要主動填寫的用戶信息)。若是須要添加data參數,那麼是POST請求,默認無data參數時,就是GET請求;
<2.1>通常來說,data參數只有在http協議下請求才有意義
<2.2>data參數被規定爲byte object,也就是字節對象
<2.3>data參數應該使用標準的結構,這個須要使用
urllib.parse.urlencode()將data進行轉換,而通常咱們把data設置成字典格 式再進行轉換便可;
data在之後實戰中會介紹如何使用
<3>timeout:是選填的內容,定義超時時間,單位是秒,防止請求時間過長,不填就是默認的時間;
<4>cafile:是指向單獨文件的,包含了一系列的CA認證 (不多使用,默認便可);
<5>capath:是指向文檔目標,也是用於CA認證(不多使用,默認便可);
<5>cafile:能夠忽略
<6>context:設置SSL加密傳輸(不多使用,默認便可);
對返回的類文件對象也能夠進行其它操做:
geturl(): 返回URL,用於看是否有重定向。
result = response.geturl()
結果:
https://www.python.org/
info():返回元信息,例如HTTP的headers。
result = response.info()
結果:
x-xss-protection: 1; mode=block X-Clacks-Overhead: GNU Terry Pratchett ... Vary: Cookie Strict-Transport-Security: max-age=63072000;includeSubDomains
getcode():返回回覆的HTTP狀態碼,成功是200,失敗多是503等,能夠用來檢查代理IP的可以使用性。
result = response.getcode()
結果:
200
Request
, url, data, headers, origin_req_host, unverifiable, method
如上定義,Request是一個類,初始化中包括請求須要的各類參數:
<1>url,data和上面urlopen中的提到的同樣。
<2>headers是HTTP請求的報文信息,如User_Agent參數等,它可讓爬蟲假裝成瀏覽器而不被服務器發現你正在使用爬蟲。
<3>origin_reg_host, unverifiable, method等不太經常使用
headers頗有用,有些網站設有反爬蟲機制,檢查請求若沒有headers就會報錯,所以博主爲保證爬蟲的穩定性,基本每次都會將headers信息加入進去,這是反爬的簡單策略之一。
那麼如何找到你所在瀏覽器的headers呢?
能夠經過進入瀏覽器F12查看到
好比,博主用的Chrome瀏覽器,按F12->network就能夠查看request的headers,能夠把這個瀏覽器的headers信息複製下來使用。
下面來看看Request如何使用吧,代碼以下:
urllib.request headers response urllib.request.Request, headershtml urllib.request.urlopenresponseresult html.read.decoderesult
結果和前面urlopen是同樣的,前面提到urlopen除了能夠接受指定參數,也能夠接受Request類的對象。
在須要headers的狀況下,使用Request對象仍是頗有必要的。
' '裏面填寫本身瀏覽器的信息便可。
urllib庫的requset屬性裏面還有不少其它方法,代理、超時、認證、HTTP的POST模式下請求等內容將在下次進行分享,此次主要介紹基本功能。
下面來講說異常,urllib庫的error方法。
error
error屬性裏面主要包括了兩個重要的exception類,URLError類和HTTPError類。
URLError類
, reason, filename.args reason, .reason reason filename .filename filename
URLError類是OSError的子類,繼承OSError,沒有本身的任何行爲特色,可是將做爲error裏面全部其它類型的基類使用。
URLError類初始化定義了reason參數,意味着當使用URLError類的對象時,能夠查看錯誤的reason。
HTTPErro類
, url, code, msg, hdrs, fp.code code .msg msg .hdrs hdrs .fp fp .filename url
HTTPError是URLError的子類,當HTTP發生錯誤將舉出HTTPError。
HTTPError也是HTTP有效迴應的實例,由於HTTP協議錯誤是有效的迴應,包括狀態碼,headers和body。因此看到在HTTPError初始化的時候定義了這些有效迴應的參數。
當使用HTTPError類的對象時,能夠查看狀態碼,headers等。
下面咱們用一個例子來看一下如何使用這兩個exception類。
urllib.request urllib.error headers response urllib.request.Request, headershtml urllib.request.urlopenresponseresult html.read.decodeurllib.error.URLError ee, e.reasonurllib.error.HTTPError ee, e.code
以上代碼使用了try..exception的結構,實現了簡單的網頁爬取,當有異常時,如URLError發生時,就會返回reason,或者HTTPError發生錯誤時就會返回code。異常的增長豐富了爬取的結構,使其更加健壯。
爲何說更加健壯了呢?
不要小看了這些異常的錯誤,這些異常的錯誤很是好用,也很是關鍵。想一想看,當你編寫一個須要不斷自動運行爬取並解析的代碼時,你是不但願程序中間被打斷而終止的。若是這些異常狀態沒有設置好,那麼就頗有可能彈出錯誤而被終止,但若是設置好了完整的異常,則遇到錯誤時就會執行發生錯誤的代碼而不被打斷(好比向上面代碼同樣打印錯誤code等)。
這些打斷程序的錯誤多是不少種,尤爲當你使用代理ip池的時候,會發生不少不一樣錯誤,這時異常就起到做用了。
總結
主要介紹了爬蟲的過程和urllib的使用和功能,針對爬蟲主要介紹瞭如下的使用方法:
request基本功能, urlopen, Request
error異常的使用
後續將會分享一些request的高級功能,如自定義opener使用代理ip、超時設置、認證等,以及如何POST請求主動發送信息等,也會利用這些內容作一次實戰爬取,但願你們能更加理解。