天天看點

Scrapy學習筆記-基本庫的使用urllib

了解一下​​urllib庫​​,它是Python内置的HTTP 請求庫,也就是說不需要額外安裝即可使用它,包含如下4 個子產品。

Scrapy學習筆記-基本庫的使用urllib

發送請求

使用urllib的request子產品,我們可以友善地實作請求的發送并得到響應。本節就來看下它的具體用法。

urlopen

urllib.request子產品提供了最基本的構造HTTP請求的方法, 利用它可以模拟浏覽器的一個請求發起過程, 同時它還帶有處理授權驗證( authenticaton )、重定向( redirection) 、浏覽器Cookies 以及其他内容。

利用最基本的urlopen方法,可以完成最基本的簡單網頁的GET請求抓取

import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(type(response))
print(response.read().decode('utf-8'))      
Scrapy學習筆記-基本庫的使用urllib

response是一個HTTPResponse類型的對象,主要包含read、readinto、getheader、getheaders、fileno等方法,以及msg、version、status、reason、debuglevel、closed等屬性。調用read方法可以得到傳回的網頁内容,調用status 屬性可以得到傳回結果的狀态碼前兩個輸出分别輸出了響應的狀态碼和響應的頭資訊,最後一個輸出通過調用getheader方法并傳遞一個參數Server 擷取了響應頭中的Server 值,結果是nginx ,意思是伺服器是用Nginx搭建的。

Scrapy學習筆記-基本庫的使用urllib
Scrapy學習筆記-基本庫的使用urllib

data 參數是可選的。如果要添加該參數,并且如果它是位元組流編碼格式的内容,即bytes類型,則需要通過bytes方法轉化。另外,如果傳遞了這個參數,則它的請求方式就不再是GET 方式,而是POST 方式。

Scrapy學習筆記-基本庫的使用urllib

傳遞了一個參數word ,值是hello o 它需要被轉碼成bytes (位元組流)類型。其中轉位元組流采用了bytes方法,該方法的第一個參數需要是str (字元串)類型,需要用urllib.parse子產品裡的urlencode方法來将參數字典轉化為字元串;第二個參數指定編碼格式,這裡指定為utf8 。我們傳遞的參數州現在了form 字段中,這表明是模拟了表單送出的方式,以POST 方式傳輸資料。timeout參數用于設定逾時時間,機關為秒,意思就是如果請求超出了設定的這個時間, 還沒有得到響應, 就會抛出異常。如果不指定該參數,就會使用全局預設時間。它支援HTTP , HTTPS 、FTP請求。

Scrapy學習筆記-基本庫的使用urllib

抛出了URLError異常,該異常屬于urllib.error子產品,錯誤原因是逾時。是以,可以通過設定這個逾時時間來控制一個網頁如果長時間未響應,就跳過它的抓取。這可以利用try except語句來實作。

Scrapy學習筆記-基本庫的使用urllib

這裡我們請求測試連結,設定逾時時間是O l 秒,然後捕獲了URLError 異常,接着判斷異常是socket.timeout 類型(意思就是逾時異常)。

context參數,它必須是ssl.SSLContext類型,用來指定SSL設定。cafile 和capath這兩個參數分别指定CA 證書和它的路徑,這個在請求HTTPS連結時會有用。cadefault參數現在已經棄用了,其預設值為False 。

Request

利用urlopen方法可以實作最基本請求的發起,但這幾個簡單的參數并不足以建構一個完整的請求。如果請求中需要加入Headers 等資訊,就可以利用更強大的Request類來建構。依然是用urlopen方法來發送這個請求,隻不過這次該方法的參數不再是URL,而是一個Request類型的對象。

Scrapy學習筆記-基本庫的使用urllib
Scrapy學習筆記-基本庫的使用urllib

第一個參數url用于請求URL ,這是必傳參數,其他都是可選參數。第二個參數data 如果要傳,必須傳bytes(位元組流)類型的。如果它是字典,可以先用urllib.parse 子產品裡的urlencode()編碼。

第三個參數headers 是一個字典,它就是請求頭,我們可以在構造請求時通過headers 參數直接構造,也可以通過調用請求執行個體的add_ header方法添加。添加請求頭最常用的用法就是通過修改User-Agent 來僞裝浏覽器,預設的User-Agent 是一Python-urllib ,我們可以通過修改它來僞裝浏覽器。比如要僞裝火狐浏覽器,你可以把它設定為:Mozilla/s.o (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11

第四個參數origin_req_host 指的是請求方的host 名稱或者IP 位址。

第五個參數unverifiable 表示這個請求是否是無法驗證的,預設是False ,意思就是說使用者沒有足夠權限來選擇接收這個請求的結果。例如,我們請求一個HTML 文檔中的圖檔,但是我們沒有向動抓取圖像的權限,這時unverifiable 的值就是True。

第六個參數method是一個字元串,用來訓示請求使用的方法,比如GET 、POST 和PUT 等。

Scrapy學習筆記-基本庫的使用urllib
Scrapy學習筆記-基本庫的使用urllib

urllib.request子產品裡的BaseHandler 類,它是所有其他Handler 的父類,它提供了最基本的方法,例如default_open 、protocol_request 等。接下來,就有各種Handler子類繼承這個BaseHandler 類,舉例如下。

Scrapy學習筆記-基本庫的使用urllib

另一個比較重要的類就是OpenerDirector ,我們可以稱為Opener 。我們之前用過urlopen這個方法,實際上它就是urllib 為我們提供的一個Opener。那麼,為什麼要引人Opener 呢?因為需要實作更進階的功能。之前使用的Request 和urlopen相當于類庫為你封裝好了極其常用的請求方法,利用它們可以完成基本的請求,但是現在不一樣了,我們需要實作更進階的功能,是以需要深入一層進行配置,使用更底層的執行個體來完成操作,是以這裡就用到了Opener 。

Opener 可以使用open方法,傳回的類型和urlopen如出一轍。那麼,它和Handler 有什麼關系呢?簡而言之,就是利用Handler來建構Opener 。

驗證

Scrapy學習筆記-基本庫的使用urllib

首先執行個體化HTTPBasicAuthHandler 對象,其參數是HTTPPasswordMgrWithDefaultRealm 對象,它利用add_password 添加進去使用者名和密碼,這樣就建立了一個處理驗證的Handler。接下來,利用這個Handler 并使用build_opener方法建構一個Opener ,這個Opener 在發送請求時就相當于已經驗證成功了。接下來,利用Opener的open方法打開連結,就可以完成驗證了。

代理

Scrapy學習筆記-基本庫的使用urllib

這裡在本地搭建了一個代理,它運作在9743端口上。使用了ProxyHandler ,其參數是一個字典,鍵名是協定類型(比如HTTP 或者HTTPS 等),鍵值是代理連結,可以添加多個代理。Cookies

将網站的Cookies 擷取下來

Scrapy學習筆記-基本庫的使用urllib
Scrapy學習筆記-基本庫的使用urllib

聲明一個CookieJar對象。接下來,就需要利用HTTPCookieProcessor來建構一個Handler ,最後利用build_opener方法建構出Opener ,執行open函數即可。

輸出成檔案格式,CookieJar 就需要換成問ozillaCookieJar ,它在生成檔案時會用到,是CookieJar 的子類,可以用來處理Cookies 和檔案相關的事件,比如讀取和儲存Cookies ,可以将Cookies 儲存成Mozilla 型浏覽器的Cookies 格式。

LWPCookieJar 同樣可以讀取和儲存Cookies ,但是儲存的格式和MozillaCookieJar 不一樣,它會儲存成libwww-perl(LWP)格式的Cookies 檔案。

Scrapy學習筆記-基本庫的使用urllib

生成了Cookies 檔案後,怎樣從檔案中讀取并利用呢?以LWPCookieJar 格式為例來看一下:

Scrapy學習筆記-基本庫的使用urllib

這裡調用load方法來讀取本地的Cookies 檔案,擷取到了Cookies 的内容。不過前提是我們首先生成了LWPCookieJar格式的Cookies ,并儲存成檔案,然後讀取Cookies 之後使用同樣的方法建構Handler 和Opener 即可完成操作。

處理異常

urllib的error子產品定義了由request 子產品産生的異常。如果出現了問題, request子產品便會抛出error子產品中定義的異常。

URLError

URLError類來自urllib庫的error子產品,它繼承自OSError類,是error異常子產品的基類,由request子產品生的異常都可以通過捕獲這個類來處理。它具有一個屬性reason ,即傳回錯誤的原因。

Scrapy學習筆記-基本庫的使用urllib

打開一個不存在的頁面照理來說應該會報錯,但是這時我們捕獲了URL Error 這個異常,運作結果如下:Not Found 程式沒有直接報錯,而是輸歸了如上内容,這樣通過如上操作,我們就可以避免程式異常終止,同時異常得到了有效處理。

HTTPError

它是URLError 的子類,專門用來處理HTTP 請求錯誤,比如認證請求失敗等。它有如下3 個屬性

code : 傳回HTTP 狀态碼,比如404 表示網頁不存在, 500 表示伺服器内部錯誤等。

reason :同父類一樣,用于傳回錯誤的原因。

headers : 傳回請求頭。

Scrapy學習筆記-基本庫的使用urllib

因為URLError是HTTPError的父類,是以可以先選擇捕獲子類的錯誤,再去捕獲父類的錯誤,是以上述代碼更好的寫法如下:

Scrapy學習筆記-基本庫的使用urllib

這樣就可以做到先捕獲HTTPError ,擷取它的錯誤狀态碼、原因、headers 等資訊。如果不是HTTPError 異常,就會捕獲URLError 異常,輸出錯誤原因。最後,用else 來處理正常的邏輯。

有時候, reason 屬性傳回的不一定是字元串,也可能是一個對象

Scrapy學習筆記-基本庫的使用urllib

可以發現, reason 屬性的結果是socket.timeout 類。是以,這裡我們可以用isinstance方法來判斷它的類型,作出更詳細的異常判斷。

解析連結

urllib庫裡還提供了parse子產品,它定義了處理URL的标準接口,例如實作URL各部分的抽取、合并以及連結轉換。它支援如下協定的URL處理:file、ftp、gopher、hdl、http、https、imap、mailto、mms、news、nntp、prospero、rsync、rtsp、rtspu、sftp、sip、sips、snews、svn、svn+ssh、telnet和wais。

urlparse方法可以實作URL 的識别和分段

Scrapy學習筆記-基本庫的使用urllib

傳回結果是一個ParseResult類型的對象,它包含6個部分,分别是scheme、netloc、path、params、query和fragment 。可以發現, urlparse方法将其拆分成了6 個部分。大體觀察可以發現,解析時有特定的分隔符。比如,😕/前面的就是scheme ,代表協定;第一個/符号前面便是netloc ,即域名,後面是path,即通路路徑;分号;前面是params,代表參數;問号?後面是查詢條件query,一般用作GET類型的URL;井号#後面是錨點,用于直接定位頁面内部的下拉位置。

Scrapy學習筆記-基本庫的使用urllib
Scrapy學習筆記-基本庫的使用urllib

urlstring :這是必填項,即待解析的URL。scheme:它是預設的協定(比如http或https等)。假如這個連結沒有帶協定資訊,會将這.個作為預設的協定。allow_ fragments:即是否忽略fragment 。如果它被設定為False,fragment 部分就會被忽略,它會被解析為path、parameters或者query的一部分,而fragment部分為空。

傳回結果ParseResult實際上是一個元組,我們可以用索引順序來擷取,也可以用屬性名擷取

Scrapy學習筆記-基本庫的使用urllib

urlunparse實作URL的構造,接受的參數是一個可疊代對象,但是它的長度必須是6 , 否則會抛出參數數量不足或者過多的問題。

Scrapy學習筆記-基本庫的使用urllib

urlsplit和urlparse方法非常相似, 隻不過它不再單獨解析params這一部分,隻運回5個結果。params會合并到path中。傳回結果是SplitResult , 它其實也是一個元組類型, 既可以用屬性擷取值,也可以用索引來擷取。

Scrapy學習筆記-基本庫的使用urllib

urlunsplit是将連結各個部分組合成完整連結的方法,傳人的參數也是一個可疊代對象,例如清單、元組等,唯一的差別是長度必須為5

Scrapy學習筆記-基本庫的使用urllib

urljoin 提供一個base_url(基礎連結)作為第一個參數,将新的連結作為第二個參數,該方法會分析base_url的scheme 、netloc和path這3 個内容并對新連結缺失的部分進行補充,最後傳回結果。base_url提供了三項内容scheme、netloc和path。如果這3 項在新的連結裡不存在,就予以補充;如果新的連結存在,就使用新的連結的部分。而base_url中的params 、query和fragment是不起作用的。

Scrapy學習筆記-基本庫的使用urllib

urlencode 構造GET 請求參數

Scrapy學習筆記-基本庫的使用urllib

首先聲明了一個字典來将參數表示出來,然後調用urlencode方法将其序列化為GET請求參數。

parse_qs GET 請求參數轉回字典

Scrapy學習筆記-基本庫的使用urllib

parse_qsl 将參數轉化為元組組成的清單

Scrapy學習筆記-基本庫的使用urllib

quote 将内容轉化為URL編碼的格式。URL中帶有中文參數時,有時可能會導緻亂碼的問題,此時用這個方法可以将巾文字元轉化為URL編碼

Scrapy學習筆記-基本庫的使用urllib

unquote URL 解碼

分析Robots協定

利用urllib的robotparser子產品,可以實作網站Robots協定的分析。robots.txt檔案,放在網站的根目錄下,和網站的人口檔案(比如index.php 、index.html 和index.jsp 等)放在一起。

禁止所有爬蟲通路任何目錄的代碼如下:

Scrapy學習筆記-基本庫的使用urllib

允許所有爬蟲通路任何目錄的代碼如下:

Scrapy學習筆記-基本庫的使用urllib

禁止所有爬蟲通路網站某些目錄的代碼如下:

Scrapy學習筆記-基本庫的使用urllib

隻允許某一個爬蟲通路的代碼如下:

Scrapy學習筆記-基本庫的使用urllib
Scrapy學習筆記-基本庫的使用urllib

robotparser提供了一個類RobotFileParser,它可以根據某網站的robots.txt 檔案來判斷一個爬取爬蟲是否有權限來爬取這個網頁。

該類用起來非常簡單,隻需要在構造方法裡傳人robots.txt 的連結即可。當然,也可以在聲明時不傳人,預設為空,最後再使用set_url方法設定一下也可。

Scrapy學習筆記-基本庫的使用urllib
Scrapy學習筆記-基本庫的使用urllib
Scrapy學習筆記-基本庫的使用urllib