urllib 是 Python3 中自帶的 HTTP 請求庫,無需複雜的安裝過程便可正常使用,十分適合爬蟲入門html
urllib 中包含四個模塊,分別是python
如下咱們將會分別講解 urllib 中各模塊的使用方法,可是因爲篇幅問題,本文只會涉及模塊中比較經常使用的內容json
詳細內容能夠參考官方文檔:https://docs.python.org/3.7/library/urllib.html瀏覽器
在開始講解前,先給你們提供一個用於測試的網站,http://www.httpbin.org/cookie
這個網站能夠在頁面上返回所發送 請求 的相關信息,十分適合練習使用網絡
好了,下面正式開始!session
request 模塊是 urllib 中最重要的一個模塊,通常用於 發送請求和接收響應app
urllib.request.urlopen()
urlopen 方法無疑是 request 模塊中最經常使用的方法之一,常見的參數說明以下:dom
url
:必填,字符串,指定目標網站的 URLsocket
data
:指定表單數據
該參數默認爲 None,此時 urllib 使用 GET 方法 發送請求
當給參數賦值後,urllib 使用 POST 方法 發送請求,並在該參數中攜帶表單信息(bytes 類型)
timeout
:可選參數,用來指定等待時間,若超過指定時間還沒得到響應,則拋出一個異常
該方法始終返回一個 HTTPResponse 對象,HTTPResponse 對象常見的屬性和方法以下:
geturl()
:返回 URLgetcode()
:返回狀態碼getheaders()
:返回所有響應頭信息getheader(header)
:返回指定響應頭信息read()
:返回響應體(bytes 類型),一般須要使用 decode('utf-8')
將其轉化爲 str 類型例子1:發送 GET 請求
>>> import urllib.request >>> url = 'http://www.httpbin.org/get' >>> response = urllib.request.urlopen(url) >>> type(response) # <class 'http.client.HTTPResponse'> >>> response.geturl() # 'http://www.httpbin.org/get' >>> response.getcode() # 200 >>> response.getheaders() # [('Connection', 'close'), ('Server', 'gunicorn/19.9.0'), ('Date', 'Sat, 11 Aug 2018 01:39:14 GMT'), ('Content-Type', 'application/json'), ('Content-Length', '243'), ('Access-Control-Allow-Origin', '*'), ('Access-Control-Allow-Credentials', 'true'), ('Via', '1.1 vegur')] >>> response.getheader('Connection') # 'close' >>> print(response.read().decode('utf-8')) # { # "args": {}, # "headers": { # "Accept-Encoding": "identity", # "Host": "www.httpbin.org", # "User-Agent": "Python-urllib/3.7" # }, # "origin": "183.6.159.80, 183.6.159.80", # "url": "https://www.httpbin.org/get" # }
例子2:發送 POST 請求
urllib.parse.urlencode()
:進行 URL 編碼,其實是將 dict 類型數據轉化成 str 類型數據
encode('utf-8')
:將 str 類型數據轉化成 bytes 類型數據
>>> import urllib.request >>> import urllib.parse >>> url = 'http://www.httpbin.org/post' >>> params = { 'from':'AUTO', 'to':'AUTO' } >>> data = urllib.parse.urlencode(params).encode('utf-8') >>> response = urllib.request.urlopen(url=url,data=data) >>> html = response.read().decode('utf-8') >>> print(html) # { # "args": {}, # "data": "", # "files": {}, # "form": { # 這是咱們設置的表單數據 # "from": "AUTO", # "to": "AUTO" # }, # "headers": { # "Accept-Encoding": "identity", # "Connection": "close", # "Content-Length": "17", # "Content-Type": "application/x-www-form-urlencoded", # "Host": "www.httpbin.org", # "User-Agent": "Python-urllib/3.6" # }, # "json": null, # "origin": "116.16.107.180", # "url": "http://www.httpbin.org/post" # }
實際上,咱們還能夠給 urllib.request.open()
方法傳入一個 Request 對象做爲參數
爲何還須要使用 Request 對象呢?由於在上面的參數中咱們沒法指定 請求頭部,而它對於爬蟲而言又十分重要
不少網站可能會首先檢查請求頭部中的 USER-AGENT
字段來判斷該請求是否由網絡爬蟲程序發起
可是經過修改請求頭部中的 USER_AGENT
字段,咱們能夠將爬蟲程序假裝成瀏覽器,輕鬆繞過這一層檢查
這裏提供一個查找經常使用的 USER-AGENT 的網站:
urllib.request.Request()
參數說明以下:
url
:指定目標網站的 URLdata
:發送 POST 請求時提交的表單數據,默認爲 Noneheaders
:發送請求時附加的請求頭部,默認爲 {}origin_req_host
:請求方的 host 名稱或者 IP 地址,默認爲 Noneunverifiable
:請求方的請求沒法驗證,默認爲 Falsemethod
:指定請求方法,默認爲 None>>> import urllib.request >>> url = 'http://www.httpbin.org/headers' >>> headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' } >>> req = urllib.request.Request(url, headers=headers, method='GET') >>> response = urllib.request.urlopen(req) >>> html = response.read().decode('utf-8') >>> print(html) # { # "headers": { # "Accept-Encoding": "identity", # "Connection": "close", # "Host": "www.httpbin.org", # "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" 這是咱們設置的 User-Agent # } # }
什麼是 Cookie?
Cookie 是指某些網站爲了辨別用戶身份、進行 session 跟蹤而儲存在用戶本地終端上的數據
① 獲取 Cookie
>>> import urllib.request >>> import http.cookiejar >>> cookie = http.cookiejar.CookieJar() >>> cookie_handler = urllib.request.HTTPCookieProcessor(cookie) >>> opener = urllib.request.build_opener(cookie_handler) >>> response = opener.open('http://www.baidu.com') >>> for item in cookie: print(item.name + '=' + item.value) # BAIDUID=486AED46E7F22C0A7A16D9FE6E627846:FG=1 # BDRCVFR[RbWYmTxDkZm]=mk3SLVN4HKm # BIDUPSID=486AED46E7F22C0A7A16D9FE6E627846 # H_PS_PSSID=1464_21106_26920 # PSTM=1533990197 # BDSVRTM=0 # BD_HOME=0 # delPer=0
② 使用 Cookie
>>> import urllib.request >>> import http.cookiejar >>> # 將 Cookie 保存到文件 >>> cookie = http.cookiejar.MozillaCookieJar('cookie.txt') >>> cookie_handler = urllib.request.HTTPCookieProcessor(cookie) >>> opener = urllib.request.build_opener(cookie_handler) >>> response = opener.open('http://www.baidu.com') >>> cookie.save(ignore_discard=True,ignore_expires=True) >>> # 從文件讀取 Cookie 並添加到請求中 >>> cookie = http.cookiejar.MozillaCookieJar() >>> cookie = cookie.load('cookie.txt',ignore_discard=True,ignore_expires=True) >>> cookie_handler = urllib.request.HTTPCookieProcessor(cookie) >>> opener = urllib.request.build_opener(cookie_handler) >>> response = opener.open('http://www.baidu.com') >>> # 此時已經獲得帶有 Cookie 請求返回的響應
對於某些網站,若是同一個 IP 短期內發送大量請求,則可能會將該 IP 斷定爲爬蟲,進而對該 IP 進行封禁
因此咱們有必要使用隨機的 IP 地址來繞開這一層檢查,這裏提供幾個查找免費的 IP 地址的網站:
注意,免費的代理 IP 基本上十分不穩定,並且還可能隨時更新,因此最好本身寫一個爬蟲去維護
>>> import urllib.request >>> import random >>> ip_list = [ {'http':'61.135.217.7:80'}, {'http':'182.88.161.204:8123'} ] >>> proxy_handler = urllib.request.ProxyHandler(random.choice(ip_list)) >>> opener = urllib.request.build_opener(proxy_handler) >>> response = opener.open('http://www.httpbin.org/ip') >>> print(response.read().decode('utf-8')) # { # "origin": "61.135.217.7" # }
parse 模塊通常能夠用於處理 URL
當你在 URL 中使用中文時,你會發現程序會出現莫名其妙的錯誤
>>> import urllib.request >>> url = 'https://www.baidu.com/s?wd=爬蟲' >>> response = urllib.request.urlopen(url) # UnicodeEncodeError: 'ascii' codec can't encode characters in position 10-11: ordinal not in range(128)
這時,quote 方法就能夠派上用場了,它使用轉義字符替換特殊字符,從而將上面的 URL 處理成合法的 URL
>>> import urllib.parse >>> url = 'https://www.baidu.com/s?wd=' + urllib.parse.quote('爬蟲') >>> url # 'https://www.baidu.com/s?wd=%E7%88%AC%E8%99%AB'
urlencode 方法在上面的文章中曾經用到過,不知道你們還有沒有印象,這裏咱們再從新回顧一遍
簡單來講,urlencode 方法就是將 dict 類型數據轉化爲符合 URL 標準的 str 類型數據,請看演示:
>>> import urllib.parse >>> params = { 'from':'AUTO', 'to':'AUTO' } >>> data = urllib.parse.urlencode(params) >>> data # 'from=AUTO&to=AUTO'
urlparse 方法用於解析 URL,返回一個 ParseResult 對象
該對象能夠認爲是一個六元組,對應 URL 的通常結構:scheme://netloc/path;parameters?query#fragment
>>> import urllib.parse >>> url = 'http://www.example.com:80/python.html?page=1&kw=urllib' >>> url_after = urllib.parse.urlparse(url) >>> url_after # ParseResult(scheme='http', netloc='www.example.com:80', path='/python.html', params='', query='page=1', fragment='urllib') >>> url_after.port # 80
error 模塊通常用於進行異常處理,其中包含兩個重要的類:URLError
和 HTTPError
注意,HTTPError 是 URLError 的子類,因此捕獲異常時通常要先處理 HTTPError,經常使用的格式以下:
>>> import urllib.request >>> import urllib.error >>> import socket >>> try: response = urllib.request.urlopen('http://www.httpbin.org/get', timeout=0.1) except urllib.error.HTTPError as e: print("Error Code: ", e.code) print("Error Reason: ", e.reason) except urllib.error.URLError as e: if isinstance(e.reason, socket.timeout): print('Time out') else: print('Request Successfully') # Time out
【參考資料】
【爬蟲系列相關文章】