Python 爬蟲庫 urllib 使用詳解

來源:海豚數據科學實驗室

一、Python urllib 庫

Python urllib 庫用於操作網頁 URL,並對網頁的內容進行抓取處理。

Python3 的 urllib。

urllib 包 包含以下幾個模塊:

需要用的就是每個模塊的內置方法和函數。大概方法如下圖:

二、urllib.request 模塊

urllib.request 定義了一些打開 URL 的函數和類,包含授權驗證、重定向、瀏覽器 cookies 等。

urllib.request 可以模擬瀏覽器的一個請求發起過程。

這裏主要介紹兩個常用方法,urlopen 和 Request。

1. urlopen 函數

語法格式如下:

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

示例:

import urllib.request
#導入urllib.request模塊
url=urllib.request.urlopen("https://www.baidu.com")
#打開讀取baidu信息
print(url.read().decode('utf-8'))
#read獲取所有信息,並decode()命令將網頁的信息進行解碼

運行結果:

<!DOCTYPE html><!--STATUS OK--><html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta content="always" name="
html{color:#000;overflow-y:scroll;overflow:-moz-scrollbars}                     
body,button,input,select,textarea{font-size:12px;font-family:Arial,sans-serif}  
h1,h2,h3,h4,h5,h6{font-size:100%}                                               
em{font-style:normal}                                                           
small{font-size:12px}                                                           
ol,ul{list-style:none}                                                          
a{text-decoration:none}                                                         
a:hover{text-decoration:underline}                                              
legend{color:#000}                                                              
fieldset,img{border:0}                                                          
button,input,select,textarea{font-size:100%} 
...

response 對象是 http.client. HTTPResponse 類型,主要包含 read、readinto、getheader、getheaders、fileno 等方法,以及 msg、version、status、reason、debuglevel、closed 等屬性。

常用方法:

2、Request 類

我們抓取網頁一般需要對 headers(網頁頭信息)進行模擬,否則網頁很容易判定程序爲爬蟲,從而禁止訪問。這時候需要使用到 urllib.request.Request 類:

class urllib.request.Request(url, data=None, headers={}origin_req_host=None, unverifiable=False, method=None)

示例:

import urllib.request
#導入模塊
url = "https://www.baidu.com"
#網頁連接
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36"
}
#定義headers,模擬瀏覽器訪問
req = urllib.request.Request(url=url,headers=headers)
#模擬瀏覽器發送,訪問網頁
response = urllib.request.urlopen(req)
#獲取頁面信息
print(response.read().decode("utf-8"))

三、urllib.error 模塊

urllib.error 模塊爲 urllib.request 所引發的異常定義了異常類,基礎異常類是 URLError。

urllib.error 包含了兩個方法,URLError 和 HTTPError。

URLError 是 OSError 的一個子類,用於處理程序在遇到問題時會引發此異常(或其派生的異常),包含的屬性 reason 爲引發異常的原因。

HTTPError 是 URLError 的一個子類,用於處理特殊 HTTP 錯誤例如作爲認證請求的時候,包含的屬性 code 爲 HTTP 的狀態碼, reason 爲引發異常的原因,headers 爲導致 HTTPError 的特定 HTTP 請求的 HTTP 響應頭。

區別:

關係:

1. URLError 示例

from urllib import request
from urllib import error
if __name__ == "__main__":
    #一個不存在的連接
    url = "http://www.baiiiduuuu.com/"
    req = request.Request(url)
    try:
        response = request.urlopen(req)
        html = response.read().decode('utf-8')
        print(html)
    except error.URLError as e:
        print(e.reason)

返回結果:

[Errno -2] Name or service not known

reason:

此錯誤的原因。它可以是一個消息字符串或另一個異常實例。

2. HTTPError 示例

from urllib import request
from urllib import error
if __name__ == "__main__":
    #網站服務器上不存在資源
    url = "http://www.baidu.com/no.html"
    req = request.Request(url)
    try:
        response = request.urlopen(req)
        html = response.read().decode('utf-8')
        print(html)
    except error.HTTPError as e:
        print(e.code)

返回結果:

404

code

一個 HTTP 狀態碼,具體定義見 RFC 2616。這個數字的值對應於存放在

http.server.BaseHTTPRequestHandler.responses 代碼字典中的某個值。

reason

這通常是一個解釋本次錯誤原因的字符串。

headers

導致 HTTPError 的特定 HTTP 請求的 HTTP 響應頭。

3. URLError 和 HTTPError 混合使用

注意:由於 HTTPError 是 URLError 的子類,所以捕獲的時候 HTTPError 要放在 URLError 的上面。

示例:

from urllib import request
from urllib import error
if __name__ == "__main__":
    #網站服務器上不存在資源
    url = "http://www.baidu.com/no.html"
    req = request.Request(url)
    try:
        response = request.urlopen(req)
 #       html = response.read().decode('utf-8')
    except error.HTTPError as e:
        print(e.code)
    except error.URLError as e:
        print(e.code)

如果不用上面的方法,可以直接用判斷的形式。

from urllib import request
from urllib import error
if __name__ == "__main__":
    #網站服務器上不存在資源
    url = "http://www.baidu.com/no.html"
    req = request.Request(url)
    try:
        response = request.urlopen(req)
 #       html = response.read().decode('utf-8')
    except error.URLError as e:
        if hasattr(e, 'code'):
            print("HTTPError")
            print(e.code)
        elif hasattr(e, 'reason'):
            print("URLError")
            print(e.reason)

執行結果:

HTTPError
404

四、urllib.parse 模塊

模塊定義的函數可分爲兩個主要門類: URL 解析和 URL 轉碼。

4.1 URL 解析

4.1.1 urlparse()

urllib.parse 用於解析 URL,格式如下:

urllib.parse.urlparse(urlstring, scheme=''allow_fragments=True)

urlstring 爲 字符串的 url 地址,scheme 爲協議類型。

allow_fragments 參數爲 false,則無法識別片段標識符。相反,它們被解析爲路徑,參數或查詢組件的一部分,並 fragment 在返回值中設置爲空字符串。

標準鏈接格式爲:

scheme://netloc/path;params?query#fragment

對象中包含了六個元素,分別爲:協議(scheme)、域名(netloc)、路徑(path)、路徑參數(params)、查詢參數(query)、片段(fragment)。

示例:

from urllib.parse import urlparse
o = urlparse("https://docs.python.org/zh-cn/3/library/urllib.parse.html#module-urllib.parse")
print('scheme  :', o.scheme)
print('netloc  :', o.netloc)
print('path    :', o.path)
print('params  :', o.params)
print('query   :', o.query)
print('fragment:', o.fragment)
print('hostname:', o.hostname)

執行結果:

scheme  : https                                                                                                                                                                                          
netloc  : docs.python.org                                                       
path    : /zh-cn/3/library/urllib.parse.html                                    
params  :                                                                       
query   :                                                                       
fragment: module-urllib.parse                                                   
hostname: docs.python.org

以上還可以通過索引獲取,如通過

print(o[0])
...
print(o[5])

4.1.2 urlunparse()

urlunparse() 可以實現 URL 的構造。(構造 URL)

urlunparse() 接收一個是一個長度爲 6 的可迭代對象,將 URL 的多個部分組合爲一個 URL。若可迭代對象長度不等於 6,則拋出異常。

示例:

from urllib.parse import urlunparse
url_compos = ['http','www.baidu.com','index.html','user= test','a=6','comment']
print(urlunparse(url_compos))

結果:

http://www.baidu.com/index.html;user= test?a=6#comment

4.1.3 urlsplit()

urlsplit() 函數也能對 URL 進行拆分,所不同的是, urlsplit() 並不會把 路徑參數 (params) 從 路徑 (path) 中分離出來。

當 URL 中路徑部分包含多個參數時,使用 urlparse() 解析是有問題的,這時可以使用 urlsplit() 來解析.

4.1.4 urlsplit()

urlunsplit() 與 urlunparse() 類似,(構造 URL),傳入對象必須是可迭代對象,且長度必須是 5。

示例:

from urllib.parse import urlunsplit
url_compos = ['http','www.baidu.com','index.html','user= test','a = 2']
print(urlunsplit(url_compos))urlunsplit()

結果:

http://www.baidu.com/index.html?user= test#a = 2

4.1.5 urljoin()

同樣可以構造 URL。

傳遞一個基礎鏈接, 根據基礎鏈接可以將某一個不完整的鏈接拼接爲一個完整鏈接.

注:連接兩個參數的 url, 將第二個參數中缺的部分用第一個參數的補齊, 如果第二個有完整的路徑,則以第二個爲主。

4.2 URL 轉碼

python 中提供 urllib.parse 模塊用來編碼和解碼,分別是 urlencode() 與 unquote()。

4.2.1 編碼 quote(string)

URL 轉碼函數的功能是接收程序數據並通過對特殊字符進行轉碼並正確編碼非 ASCII 文本來將其轉爲可以安全地用作 URL 組成部分的形式。它們還支持逆轉此操作以便從作爲 URL 組成部分的內容中重建原始數據,如果上述的 URL 解析函數還未覆蓋此功能的話

語法:

urllib.parse.quote(string, safe='/'encoding=None, errors=None)

使用 %xx 轉義符替換 string 中的特殊字符。字母、數字和 '_.-~' 等字符一定不會被轉碼。在默認情況下,此函數只對 URL 的路徑部分進行轉碼。可選的 safe 形參額外指定不應被轉碼的 ASCII 字符 --- 其默認值爲 '/'。

string 可以是 str 或 bytes 對象。

示例:

from urllib import parse
url = "http://www.baidu.com/s?wd={}"
words = "爬蟲"
#quote()只能對字符串進行編碼
query_string = parse.quote(words)
url = url.format(query_string)
print(url)

執行結果:

http://www.baidu.com/s?wd=%E7%88%AC%E8%99%AB

4.2.2 編碼 urlencode()

quote() 只能對字符串編碼,而 urlencode() 可以對查詢字符串進行編碼。

# 導入parse模塊
from urllib import parse
#調用parse模塊的urlencode()進行編碼
query_string = {'wd':'爬蟲'}
result = parse.urlencode(query_string)
# format函數格式化字符串,進行url拼接
url = 'http://www.baidu.com/s?{}'.format(result)
print(url)

結果:

http://www.baidu.com/s?wd=%E7%88%AC%E8%99%AB

4.2.3 解碼 unquote(string)

解碼就是對編碼後的 url 進行還原。

示例:

from urllib import parse
string = '%E7%88%AC%E8%99%AB'
result = parse.unquote(string)
print(result)

執行結果:

爬蟲

五、urllib.robotparser 模塊

(在網絡爬蟲中基本不會用到,使用較少,僅作了解)

urllib.robotparser 用於解析 robots.txt 文件。

robots.txt(統一小寫)是一種存放於網站根目錄下的 robots 協議,它通常用於告訴搜索引擎對網站的抓取規則。

Robots 協議也稱作爬蟲協議,機器人協議,網絡爬蟲排除協議,用來告訴爬蟲哪些頁面是可以爬取的,哪些頁面是不可爬取的。它通常是一個 robots.txt 的文本文件,一般放在網站的根目錄上。

當爬蟲訪問一個站點的時候,會首先檢查這個站點目錄是否存在 robots.txt 文件,如果存在,搜索爬蟲會根據其中定義的爬取範圍進行爬取。如果沒有找到這個文件,搜索爬蟲會訪問所有可直接訪問的頁面。

urllib.robotparser 提供了 RobotFileParser 類,語法如下:

class urllib.robotparser.RobotFileParser(url='')

這個類提供了一些可以讀取、解析 robots.txt 文件的方法:



本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/KnToAx7KeLsLGZjV4uSUyA