【Python】urllib庫——下載網頁、爬蟲彙總

注:urllib2 ,這個包是基於python2的,官方已經對python2停止更新了並且不再免費,我覺得這個urllib2沒必要再學習和使用

urllib 這個是python的標準庫,在python3裏整合了python2的urllib和urllib2,有時間的可以學習一下。

urllib3,這個是第三方庫,是對第二種方式urllib的升級,做了很多改善,有時間可以學習一下。

requests,各種請求的方法非常的優雅和人性化,其底層是urllib3,簡化headers、proxy、cookie等的操作。這個重點學習。

一、簡介

urllib是Python中請求url連接的官方標準庫,在Python2中主要爲urllib和urllib2,在Python3中整合成了urllib。基本上涵蓋了基礎的網絡請求功能。

該庫有四個模塊

  • urllib.request 發送http請求
  • urllib.error 處理請求過程中,出現的異常。
  • urllib.parse 解析url
  • urllib.robotparser 解析robots.txt 文件

常見三種形式:

import urllib.request
import urllib.parse
from http import cookiejar

'''方法1'''
response = urllib.request.urlopen('www.baidu.com')
print(response.getcode)  # 獲取狀態碼
cont = response.read()  # 讀取內容

'''方法2,add info.'''
# create Request target
request = urllib.request.Request(url)
request.add_data('a', '1')  # 添加數據
request.add_header('User-Agent', 'Mozilla/5.0')  # 添加頭文件
response = urllib.request.urlopen(request)  # 獲取結果


'''方法3,add handler,cookielib庫
HTTPCookieProcessor  賬號密碼   
ProxyHandler         代理
HTTPSHandler        加密訪問
HTTPRedirectHandler 相互自動跳轉關係
'''
cj = cookiejar.CookieJar()  # create cookie container
handler = urllib.request.HTTPCookieProcessor(cj)  # create a opener
opener = urllib.request.build_opener(handler)  # create target
urllib.request.install_opener(opener)  # install opener into request
response = urllib.request.urlopen(request)  # 同2

二、請求方式

1、get請求

#第一步導包
from  urllib import request

url = "http://httpbin.org"
#第二步請求
response = request.urlopen(url,timeout=1)
#第三步打印返回數據
print(response.read().decode())

訪問的結果會是一個http.client.HTTPResponse對象,使用此對象的read()方法,則可以獲取訪問網頁獲得的數據。但是要注意的是,獲得的數據會是bytes的二進制格式,所以需要decode()一下,轉換成字符串格式。

urlopen()

urllib發送請求是用urlopen()
源碼如下:

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
  • 第一個參數 String 類型的地址
  • data 是 bytes 類型的內容,可通過 bytes()函數或者encode()轉爲化字節流。它也是可選參數。使用 data 參數,請求方式變成以 POST 方式提交表單。使用標準格式是application/x-www-form-urlencoded
  • timeout 參數是用於設置請求超時時間。單位是秒。

  • cafilecapath代表 CA 證書和 CA 證書的路徑。如果使用HTTPS則需要用到。
  • context參數必須是ssl.SSLContext類型,用來指定SSL設置
  • cadefault參數已經被棄用,可以不用管了。
  • 該方法也可以單獨傳入urllib.request.Request對象
  • 該函數返回結果是一個http.client.HTTPResponse對象。

http.client.HTTPResponse對象。它具有msgversionstatusreasondebuglevelclosed等屬性以及read()readinto()getheader(name)getheaders()fileno()等函數。

# print(response.msg) # OK
# print(response.version)  #11
# print(response.status) #200
# print(response.reason) #OK
# print(response.getcode()) #200
# print(response.getheaders) # <bound method HTTPResponse.getheaders of <http.client.HTTPResponse object at 0x0000023C554DB588>>
# print(response.geturl()) #http://httpbin.org/headers

2、post請求

from  urllib import request,parse

url = "http://httpbin.org"
data = {
    'name':'xfy'
}

# data = bytes(parse.urlencode(data),encoding='utf8');
data = parse.urlencode(data).encode()
response = request.urlopen(url+"/post",data=data)
print(response.status) #200
print(response.read().decode())

data 需要被轉碼成字節流。而data 是一個字典。我們需要使用 parse.urlencode() 將字典轉化爲字符串。再使用 bytes()或者encode() 轉爲字節流。最後使用 urlopen() 發起請求,請求是模擬用 POST 方式提交表單數據。

這裏說一下http://httpbin.org,這個url專門是用來爬蟲請求測試的。

http://httpbin.org/get   測試get請求
http://httpbin.org/post  測試post請求
http://httpbin.org/headers  測試獲得headers  
http://httpbin.org/ip  測試獲得ip
http://httpbin.org/cookies  測試獲得cookies

三、創建 Request 對象

urlopen()還可以傳一個Request對象

req = request.Request(url+"/get")
response = request.urlopen(req)
print(response.read().decode())

urllib/request 包下有一個類Request
其初始化方法如下

    def __init__(self, url, data=None, headers={},
                 origin_req_host=None, unverifiable=False,
                 method=None):
  • url 參數是請求鏈接,這個是必傳參數,其他的都是可選參數。
  • data 參數跟 urlopen() 中的 data 參數用法相同。沒有addd_data
  • headers 參數是指定發起的 HTTP 請求的頭部信息。headers 是一個字典。
它除了在 Request 中添加,還可以通過調用 Reques t實例的 add_header() 方法來添加請求頭。
  • origin_req_host 參數指的是請求方的 host 名稱或者 IP 地址。
  • unverifiable 參數表示這個請求是否是無法驗證的,默認值是False。意思就是說用戶沒有足夠權限來選擇接收這個請求的結果。例如我們請求一個HTML文檔中的圖片,但是我們沒有自動抓取圖像的權限,我們就要將 unverifiable 的值設置成 True。
  • method 參數指的是發起的 HTTP 請求的方式,有 GET、POST、DELETE、PUT等

四、設置headers 模擬瀏覽器

通過urllib發起的請求會有默認的一個Headers:"User-Agent":"Python-urllib/3.6",指明請求是由urllib發送的。

所以遇到一些驗證User-Agent的網站時,我們需要自定義Headers,而這需要藉助於urllib.request中的Request對象。

headers = {
     'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'
}
req = request.Request(url+"/headers",headers=headers)
response = request.urlopen(req)
print(response.read().decode())

五、Request的高端使用

如果我們需要在請求中添加代理、處理請求的 Cookies,我們需要用到Handler和OpenerDirector。

  1. Handler

Handler 的中文意思是處理者、處理器。 Handler 能處理請求(HTTP、HTTPS、FTP等)中的各種事情。它的具體實現是這個類 urllib.request.BaseHandler。它是所有的 Handler 的基類,其提供了最基本的Handler的方法,例如default_open()、protocol_request()等。
繼承 BaseHandler 有很多個,我就列舉幾個比較常見的類:

  • ProxyHandler:爲請求設置代理
  • HTTPCookieProcessor:處理 HTTP 請求中的 Cookies
  • HTTPDefaultErrorHandler:處理 HTTP 響應錯誤。
  • HTTPRedirectHandler:處理 HTTP 重定向。
  • HTTPPasswordMgr:用於管理密碼,它維護了用戶名密碼的表。
  • HTTPBasicAuthHandler:用於登錄認證,一般和 HTTPPasswordMgr 結合使用。
  1. OpenerDirector

對於 OpenerDirector,我們可以稱之爲 Opener。我們之前用過 urlopen() 這個方法,實際上它就是 urllib 爲我們提供的一個Opener。那Opener 和 Handler 又有什麼關係?

  • opener 對象是由build_opener(handler) 方法來創建出來。
  • 我們需要創建自定義的opener,就需要使用 install_opener(opener)方法。
  • 值得注意的是,install_opener實例化會得到一個全局的 OpenerDirector 對象。

1、使用代理

有些網站做了瀏覽頻率限制。如果我們請求該網站頻率過高。該網站會被封IP,禁止我們的訪問。所以我們需要使用代理來突破這“枷鎖”。

proxy_header = request.ProxyHandler({
    'http':'101.236.19.165:8866'
})
opener = request.build_opener(proxy_header)
request.install_opener(opener)

response = request.urlopen(url+"/ip")
print(response.read().decode())

#打印結果
{"origin":"101.236.19.165"}

2、cookie的設置

如果請求的頁面每次需要身份驗證,我們可以使用 Cookies 來自動登錄,免去重複登錄驗證的操作。獲取 Cookies 需要使用http.cookiejar.CookieJar()實例化一個Cookies對象。再用rllib.request.HTTPCookieProcessor構建出handler對象。最後使用 opener 的 open()函數即可。

import http.cookiejar

# 創建一個cookiejar對象
cookie = http.cookiejar.CookieJar()
# 使用HTTPCookieProcessor創建handler處理器
handler = request.HTTPCookieProcessor(cookie)
# 並以它爲參數創建Opener對象
opener = request.build_opener(handler)
# 使用這個opener來發起請求
response = opener.urlopen("https://blog.csdn.net/keep_learn/article/details/68124190")
for item in cookie:
    print(item.name)
    print(item.value)

打印結果
dc_session_id
10_1531039395672.102673
uuid_tt_dd
10_19936141720-1531039395672-826694

六、請求異常處理

發起請求難免會出現各種異常,我們需要對異常進行處理,這樣會使得程序比較人性化。

異常處理主要用到兩個類,urllib.error.URLErrorurllib.error.HTTPError

  • URLError

URLError 是urllib.error異常類的基類, 可以捕獲由urllib.request產生的異常。它具有一個屬性reason,即返回錯誤的原因

from  urllib import request,error
data = {
    'name':'xfy'
}
data = parse.urlencode(data).encode()
try:
    response = request.urlopen(url,data=data)
except error.URLError as e:
    print(e.reason)
    
打印
METHOD NOT ALLOWED

  • HTTPError

HTTPError 是UEKRrror 的子類,專門處理 HTTP 和 HTTPS 請求的錯誤。它具有三個屬性。

  1. code:HTTP 請求返回的狀態碼。
  2. renson:與父類用法一樣,表示返回錯誤的原因。
  3. headers:HTTP 請求返回的響應頭信息。
from  urllib import request,error
data = {
    'name':'xfy'
}
data = parse.urlencode(data).encode()
from urllib import error
try:
    response = request.urlopen(url,data=data)
except error.HTTPError as e:
    print(e.reason)
    print(e.code)
    print(e.headers)
    
打印:
METHOD NOT ALLOWED
405
Connection: close
Server: gunicorn/19.8.1
Date: Sun, 08 Jul 2018 08:57:40 GMT
Content-Type: text/html
Allow: GET, OPTIONS, HEAD
Content-Length: 178
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Via: 1.1 vegur

七、下載數據到本地

在我們進行網絡請求時常常需要保存圖片或音頻等數據到本地,一種方法是使用python的文件操作,將read()獲取的數據保存到文件中。

urllib提供了一個urlretrieve()方法,可以簡單的直接將請求獲取的數據保存成文件。

from urllib import request

url = 'http://python.org/'
request.urlretrieve(url, 'python.html')

urlretrieve()方法傳入的第二個參數爲文件保存的位置,以及文件名。

注:urlretrieve()方法是python2直接移植過來的方法,以後有可能在某個版本中棄用。

八、urllib 處理 https 請求ssl 證書驗證(瞭解)

import ssl

#處理HTTPS請求 SSL證書驗證 忽略認證 比如12306 網站
url = "https://www.12306.cn/mormhweb/"
#添加忽略ssl證書驗證
context = ssl._create_unverified_context()
header = headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"}
req = request.Request(url, headers=header)
res = request.urlopen(req,context = context)
print(res.read().decode())

九、urllib.parse

urllib.parse是urllib中用來解析各種數據格式的模塊。

urllib.parse.quote

在url中,是隻能使用ASCII中包含的字符的,也就是說,ASCII不包含的特殊字符,以及中文等字符都是不可以在url中使用的。而我們有時候又有將中文字符加入到url中的需求,例如百度的搜索地址:

https://www.baidu.com/s?wd=周杰倫

?之後的wd參數,則是我們搜索的關鍵詞。那麼我們實現的方法就是將特殊字符進行url編碼,轉換成可以url可以傳輸的格式,urllib中可以使用quote()方法來實現這個功能。

from urllib import parse
keyword = '周杰倫'
parse.quote(keyword)

%E5%91%A8%E6%9D%B0%E4%BC%A6

如果需要將編碼後的數據轉換回來,可以使用unquote()方法。

parse.unquote('%E5%91%A8%E6%9D%B0%E4%BC%A6')
'周杰倫'

urllib.parse.urlencode

在訪問url時,我們常常需要傳遞很多的url參數,而如果用字符串的方法去拼接url的話,會比較麻煩,所以urllib中提供了urlencode這個方法來拼接url參數。

params = {'query':'徐繁韻','name':'xfy'}
data = parse.urlencode(params)
print(data)

query=%E5%BE%90%E7%B9%81%E9%9F%B5&name=xfy

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章