- urllib 是一個 python 內置包,不需要額外安裝即可使用,包里面包含了以下幾個用來處理 url 的模塊:
-
- urllib.request,用來打開和讀取 url,意思就是可以用它來模擬發送請求,就像在瀏覽器里輸入網址然后敲擊回車一樣,獲取網頁響應內容。
- urllib.error,用來處理 urllib.request 引起的異常,保證程序的正常執行。
- urllib.parse,用來解析 url,可以對 url 進行拆分、合並等。
- urllib.robotparse,用來解析 robots.txt 文件,判斷網站是否能夠進行爬取。
-
urllib.request 模塊
- urllib.request 模塊定義了以下幾個函數。
- urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
- 該函數主要用於模擬網站請求,返回一個 HTTPResponse 類型的對象
-
urlopen 函數中參數定義
-
- url,必選參數,是一個 str 字符串或者 Request 對象(后面會介紹)。
- data,bytes 類型的可選參數,如果傳遞的是字典型數據,可以用 urllib.parse.urlencode() 進行編碼,返回 str 字符串,再將 str 轉換成 bytes 字節流。如果傳遞 data 參數,urlopen 將使用 HTTP POST 方式請求,否則為 HTTP GET 請求。
- timeout,可選參數,設置超時時間(未設置時使用全局默認超時時間),以秒為單位計時,如果 urlopen 請求超出了設置時間還未得到響應則拋出異常。
- cafile 和 capath,可選參數,在 HTTPS 連接請求時指定已認證的 CA 證書以及證書路徑。
- cadefault,一般可忽略該參數。
- context,ssl.SSLContext 類型的可選參數,用來指定 SSL 設置。
-
urlopen 函數返回類型
-
urlopen 函數請求返回一個 HTTPResponse 響應上下文,或者請求異常拋出 URLError 協議錯誤,一般有如下屬性:
- geturl(),返回檢索的 url,通常用於判定是否進行了重定向。
- info(),返回網頁的頭信息。
- getcode(),返回 HTTPResponse 響應的狀態碼。
-
urlopen 函數的應用實例
-
# 創建一個 HTTP GET 請求,輸出響應上下文 from urllib.request import urlopen response = urlopen("http://www.python.org") print(response.read()) # 創建一個 HTTP POST 請求,輸出響應上下文 from urllib.request import urlopen from urllib.parse import urlencode data = {'kw' : 'python'} data = bytes(urlencode(data), encoding = 'utf-8') response = urlopen("https://fanyi.baidu.com/sug", data) print(response.read().decode('unicode_escape')) # 創建一個 HTTP GET 請求,設置超時時間為0.1s import urllib.request import urllib.error try: response=urllib.request.urlopen('http://www.python.org',timeout=0.1) print(response.read()) except urllib.error.URLError as e: print(e.reason)
-
urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
- 該函數主要用於構造一個 url,返回一個 urllib.request.Request 對象。
-
Request 函數中參數定義
- url,必選參數,請求的 url 地址。
- data,bytes 類型的可選參數。
- headers,字典類型,有些 HTTP 服務器僅允許來自瀏覽器的請求,因此通過 headers 來模擬瀏覽器對 url 的訪問,比如模擬谷歌瀏覽器時使用的 headers:"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36"。可以通過調用 add_header() 來添加 headers 信息。
- origin_req_host,請求方的 host 名稱或者 IP 地址。
- unverifiable,表示這個請求是否無法驗證,默認為 False。比如請求一張圖片,如果沒有權限獲取圖片那它的值就是 true。
- method,是一個字符串,用來指示請求使用的方法,如:GET,POST,PUT 等,默認是 GET 請求。
-
Request 函數返回類型
與 urlopen 函數請求返回一樣,一般返回一個 HTTPResponse 響應上下文。
-
Request 函數的應用實例
-
# 采用 HTTP GET 請求的方法模擬谷歌瀏覽器訪問網站,輸出響應上下文 from urllib import request,parse url = 'http://www.python.org' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36' } req = request.Request(url, headers = headers, method = 'GET') response = request.urlopen(req) print(response.read())
-
# 采用 HTTP POST 請求的方法模擬谷歌瀏覽器訪問網站,輸出響應上下文 from urllib import request from urllib import parse url = 'https://fanyi.baidu.com/sug' data = {'kw' : 'python'} data = bytes(parse.urlencode(data), encoding = 'utf-8') headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36' } req = request.Request(url, data, headers, method = 'POST') response = request.urlopen(req) print(response.read().decode('unicode_escape'))
-
# 創建一個 HTTP GET 請求,通過 add_header 添加一個 UserAgent import urllib.request import random url = 'http://www.python.org' headerUserAgentList = ['Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0'] randomHeaderUserAgent = random.choice(headerUserAgentList) # 隨機選取一個 UserAgent req = urllib.request.Request(url) req.add_header('User-Agent', randomHeaderUserAgent) # 添加 UserAgent response=urllib.request.urlopen(req) print(req.get_header('User-agent')) print(req.headers) # 打印請求的 header 信息
-
urllib.error 模塊
- urllib.error 模塊定義了由 urllib.request 模塊引發的異常,異常主要包含 URLError 和 HTTPError。
-
urllib.error.URLError 異常
URLError 類繼承自 OSError 類,是 error 異常模塊的基類,由request模塊產生的異常都可以通過捕獲這個類來處理。URLError 只有一個屬性 reason,即返回錯誤的原因。
應用實例:
-
# 在請求連接時候捕獲網址錯誤引發的異常 from urllib import request, error try: response = request.urlopen('https://www,baidu,com') except error.URLError as e: print(e.reason)
-
urllib.error.HTTPError 異常
HTTPError 是 URLError 的子類,專門用來處理 HTTP 請求錯誤,比如認證請求失敗,包含以下三個屬性:
- code:返回 HTTP 響應的狀態碼,如404頁面不存在等。
- reason:返回錯誤的原因。
- headers:返回 HTTP 響應頭信息。
應用舉例:
-
# 返回401未授權錯誤 from urllib import request,error try: response=request.urlopen('http://pythonscraping.com/pages/auth/login.php') print(response.getcode()) except error.HTTPError as e: print('1.錯誤原因:\n%s\n2.狀態碼:\n%s\n3.響應頭信息:\n%s' %(e.reason, e.code, e.headers)) except error.URLError as e: print(e.reason)
-
urllib.parse 模塊
urllib.parse 模塊定義了一個處理 url 的標准接口,用來實現 url 字符串的抽取、合並以及鏈接轉換。該模塊主要用到的函數如下。
-
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
用於實現 url 字符串的識別和分段,可以分為六個字符串,分別是 scheme (協議),netloc (域名),path (路徑),params (參數),query (查詢條件)和 fragment (錨點),其結構如下所示:“scheme://netloc/path;parameters?query#fragment”。實際上具體 url 某些字段可能會不存在,比如 “http://www.baidu.com” 只包含了協議和域名。
-
urlparse 函數中參數定義
- urlstring,待解析的 url 字符串。
- scheme,是默認的協議,比如 http 或者 https,url 字符串中如果不攜帶相關協議,可以通過 scheme 來指定,如果 url 中指定了相關協議則在 url 中生效。
- allow_fragments,是否忽略錨點,設置為 False 即 fragment 部分會被忽略,反之不會忽略。
-
urlparse 的返回類型
函數返回的是一個 urllib.parse.ParseResult 對象,獲取解析出來的 url 六個字段。
-
urlparse 應用舉例
-
# 解析並輸出 url 中每個字段的字符串 import urllib url = 'http://www.baidu.com/urllib.parse.html;python?kw=urllib.parse#module-urllib' result = urllib.parse.urlparse(url) print(result) print(result.scheme, result.netloc, result.path, result.params, result.query, result.fragment, sep = '\n')
-
urllib.parse.urlunparse(parts)
與 urlparse 相反,通過列表或者元祖的形式將分段的字符串組合成一個完整的 url 字符串。
-
urlunparse 函數中參數定義
- parts,可以是列表或者元組。
-
urlunparse 的返回類型
urlunparse 函數返回一個構造好的 url 字符串。
-
應用舉例
# 通過 data 列表或元組構造一個 url 並輸出 import urllib dataList = ['http', 'www.baidu.com', '/urllib.parse.html', 'python', 'kw=urllib.parse', 'modul-urllib'] # 六個字符串都必須填寫,否則會出現 ValueError 錯誤,如果某一字符串不存在則填入空字符 dataTuple = ('http', 'www.baidu.com', '/urllib.parse.html', '', 'kw=urllib.parse', 'modul-urllib') # 六個字符串都必須填寫,否則會出現 ValueError 錯誤,如果某一字符串不存在則填入空字符 urlList = urllib.parse.urlunparse(dataList) urlTuple = urllib.parse.urlunparse(dataTuple) print('1.urlList:%s\n2.urlTuple:%s' % (urlList, urlTuple))
-
urllib.parse.urlsplit(urlstring, scheme='', allow_fragments=True)
- 與 urlparse 函數類似,但它只返回 url 字符串的5個字段,把 params 合並到 path 中。
-
urlsplit 應用舉例
-
# 解析並輸出 url 中每個字段的字符串,params 會合並到 path 中。 import urllib url = 'http://www.baidu.com/urllib.parse.html;python?kw=urllib.parse#modul-urllib' result = urllib.parse.urlsplit(url) print(result) print(result.scheme, result.netloc, result.path, result.query, result.fragment, sep = '\n')
-
urllib.parse.urlunsplit(parts)
- 與 urlunparse 函數類似,它也是將 url 中各部分字段組合完整的 url 字符串的方法,唯一的區別是列表或元組的長度必須是5個,因為它把 params 省略了。
-
urlunsplit 應用舉例
-
# 通過 data 列表或元組構造一個 url 並輸出 import urllib dataList = ['http', 'www.baidu.com', '/urllib.parse.html;python', 'kw=urllib.parse', 'modul-urllib'] # 五個字符串都必須填寫,否則會出現 ValueError 錯誤,如果某一字符串不存在則填入空字符 dataTuple = ('http', 'www.baidu.com', '/urllib.parse.html;python', 'kw=urllib.parse', 'modul-urllib') # 五個字符串都必須填寫,否則會出現 ValueError 錯誤,如果某一字符串不存在則填入空字符 urlList = urllib.parse.urlunsplit(dataList) urlTuple = urllib.parse.urlunsplit(dataTuple) print('1.urlList:%s\n2.urlTuple:%s' % (urlList, urlTuple))
-
urllib.parse.quote(string, safe='/', encoding=None, errors=None)
使用 %xx 轉義字符替換字符串中的特殊字符,比如漢字。字母、數字和‘_.-~’字符不會被替換。
-
quote 函數中參數定義
- string,可以是 str 字符串或 bytes 類型。
- safe,可選參數,默認是'/',指明不應該被替換的附加 ASCII 字符。
- encoding 和 errors,可選參數,用來定義如何處理 non-ASCII 字符。一般默認設置編碼方法為 encoding='utf-8',errors='strict',這意味着編碼錯誤將引發 UnicodeError。如果 string 是 bytes 類型,不能設置 encoding 和 errors,否則將引發 TypeError。
-
quote 函數的返回類型
quote 函數返回一個編碼后的字符串。
-
# 采用 quote 對 url 中的漢字進行編碼,輸出編碼后的結果 import urllib url = 'http://www.baidu.com/爬蟲' result = urllib.parse.quote(url) print(result) url = 'http://www.baidu.com/+爬蟲' result = urllib.parse.quote(url, '+') # 更改 safe 參數 print(result)
-
urllib.parse.unquote(string, encoding='utf-8', errors='replace')
與 quote 函數相反,把 %xx 轉義字符替換成字符
-
unquote 函數的參數定義
-
- string,必須是 str 字符串。
- encoding 和 errors,可選參數,定義如何將 %xx 轉義字符解碼為 Unicode 字符。encoding 默認為 'utf-8',errors 默認為 'replace',表示無效的轉義字符將會用占位符替換。
-
unquote 函數的返回類型
unquote 函數返回一個解碼后的字符串。
-
# 解碼經過 quote 函數處理后的 url,輸出解碼后的結果。 import urllib url = 'http://www.baidu.com/爬蟲' result = urllib.parse.quote(url) print(result) result = urllib.parse.unquote(url) print(result)
-
urllib.parse.urljoin(base, url, allow_fragments=True)
該函數用來將基本 url 與另一個 url 組合,更新基本 url 字符串。它會使用 url 對基本 url 中缺失的部分進行補充,比如 scheme (協議)、netloc (域名)和 path (路徑)。即根據 url 字符串中帶有的字段,對基本 url 中沒有的字段進行補充,已存在的字段進行替換。
-
urljoin 函數中參數定義
- base,是一個基本 url。
- url,將 scheme (協議)、netloc (域名)或 path (路徑)字段組合進基本 url 的 url。
- allow_fragments,是否忽略錨點,設置為 False 即 fragment 部分會被忽略,反之不會忽略。
-
urljoin 函數返回類型
返回組合成功的 url 字符串。
-
# 基於 url 對 base_url 進行重新組合,並輸出組合結果。 import urllib base_url = 'http://www.baidu.com' url = 'https://www.google.com/urllib.parse.html;python?kw=urllib.parse#module-urllib' result = urllib.parse.urljoin(base_url,url,False) print(result)
-
urllib.parse.urlencode(query, doseq=False, safe='', encoding=None, errors=None, quote_via=quote_plus)
urlencode 函數可以將字典轉化為 GET 請求中的 query (查詢條件),或者將字典轉化為 POST 請求中需要上傳的數據。
-
urlencode 函數中參數定義
- query,字典類型。
- doseq,允許字典中一個鍵對應多個值,編碼成 query (查詢條件)。
- safe、encoding 和 errors,這三個參數由 quote_via 指定。
-
urlencode 函數返回類型
urlencode 函數返回 str 字符串。
-
# 創建 GET 請求 import urllib params = {'username':'xxx','password':'123'} base_url='http://www.baidu.com' url=base_url + '?' + urllib.parse.urlencode(params) print(url) params = {'username':['xxx', 'yyy'], 'password':'123'} # username 鍵對應多個值 base_url='http://www.baidu.com' url=base_url + '?' + urllib.parse.urlencode(params) # doseq 設置為 False,會解析成亂碼 print(url) url=base_url + '?' + urllib.parse.urlencode(params, True) # doseq 設置為 True print(url)
-
urllib.robotparse 模塊
rebotparser 模塊提供了一個 RobotFileParser 類,主要用來解析網站上發布的 robots.txt,然后根據解析內容判斷爬蟲是否有權限來爬取這個網頁。
-
robots.txt 文件
robots.txt,存放於網站根目錄下,采用 ASCII 編碼的文本文件,記錄此網站中的哪些內容是不應被爬蟲獲取的,哪些是可以被爬蟲獲取的。
-
robots.txt 文件內容舉例
User-agent: * Disallow: / Allow: /public/
- User-agent,爬蟲的名稱,將其設置為 * 代表協議對任何爬蟲有效,如果設置為 Baiduspider 則代表協議僅對百度爬蟲有效,要是有多條則對多個爬蟲有效,至少需要指定一條。
- Disallow,網頁中不允許抓取的目錄,上述例子中設置的 / 代表不允許抓取所有的頁面。
- Allow,一般和 Disallow 一起使用,用來排除單獨的某些限制,上述例子中設置為 /public/ 表示所有頁面不允許抓取,但可以抓取 public 目錄。
-
urllib.robotparser.RobotFileParser(url='') 類及其常用方法
- set_url(url),設置引用 robots.txt 文件的 url,如果在創建 RobotFileParser 對象時傳入了 url,那么就不需要使用這個方法設置 url。
- read(),讀取 robots.txt 文件並將其提供給解析器,不返回任何內容。
- parse(lines),用來解析 robots.txt 某些行的內容,並安裝語法規則來分析內容。
- can_fetch(useragent, url),傳入兩個參數,用戶代理以及要爬取的網站,返回的內容是該用戶代理否可以抓取這個網站,結果為 True 或 False。
-
# 使用兩種爬蟲代理分別查看是否可以對 'http://www.baidu.com' 網站進行爬取 from urllib.robotparser import RobotFileParser rp = RobotFileParser() rp.set_url("http://www.baidu.com/robots.txt") rp.read() print(rp.can_fetch('Baiduspider', 'http://www.baidu.com')) print(rp.can_fetch('*', 'http://www.baidu.com'))