本文全面講解urllib庫基本使用、高級應用、異常處理,建議收藏!!!
一、urllib庫基本使用語法:urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
注意:data參數,當給這個參數賦值時,HTTP的請求就使用POST方法,如果data=None或者不寫,則使用get方法。1.1、url庫他是python內置的HTTP請求庫他主要包含4個模塊
request: 最基本的HTTP請求模塊,可以用來模擬發送請求。只需要傳入URL和額外參數,就可以模擬實現這個過程import urllib.request
url="https://me.csdn.net/column/weixin_41685388"
response = urllib.request.urlopen(url)
print(response.read().decode('utf-8'))
# read()獲取響應體的內容,內容是bytes字節流,需要轉換成字符串
parse:一個工具模塊提供了很多URL的處理方法,如:拆分、解析、合併、格式轉換等。robotparser:主要用於識別網站的robots.txt文件,判斷哪些連結可以爬。很少使用。1.2、第一個簡單的get請求#!/usr/bin/python
# -*- coding: UTF-8 -*-
import urllib.request
url="https://me.csdn.net/column/weixin_41685388"
response = urllib.request.urlopen(url)
print(type(response)) #輸出:<class 'http.client.HTTPResponse'>
# 一個HTTPResponse類型的對象,
# 主要包含read()、readinto()、getheader(name)、getheaders()、fileno()等方法,
# 以及msg、version、status、reason、debuglevel、closed等屬性。
# 常用status屬性得到返回結果的狀態碼
print(response.status) #返回200 表示正常請求
# getheaders()返回頭部信息
print(response.getheaders())
# 返回頭部信息中'Server'的值,伺服器的搭建相關信息
print(response.getheader('Server'))
# 常用.read().decode('utf-8')返回網頁內容,read()獲取響應體的內容,內容是bytes字節流,需要轉換成字符串
print(response.read().decode('utf-8')) #網頁內容
1.3、判斷是get請求和post請求問題來了,如何判斷是get請求和post請求,谷歌瀏覽器為例:打開網頁-->右擊,檢查(N)-->Network-->F5刷新,找到我們需要的Name,Method的值一看就知道了,注意往往第一次使用的時候檢查功能的時候默認沒有打開Method,需手動勾選一下。
get請求,如:https://blog.csdn.net/weixin_41685388/category_9426224.html連結
如何查看是否是我們需要的Name?
請求時需要的內容:
來一個post請求,看長啥樣如:http://fanyi.youdao.com/
請求時需要的內容:具體看4中代碼
1.4、post請求表單的提交在使用urllib.request.urlopen()函數有一個data參數,當給這個參數賦值時,HTTP的請求就使用POST方法,如果data=None或者不寫,則HTTP的請求就使用get方法。data參數的格式必須符合application/x-www-form-urlencoded的格式。需要urllib.parse.urlencode()將字符串轉化為這個格式。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import urllib.request
import urllib.parse
import json
import time
def youdao(input):
#url=r"http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
# 調試後發現設置了反爬機制,需要將「_o」刪除即可。
url=r"http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
#用於隱藏身份,Headers必須是字典,在網頁檢查的Request Headers中,常調用Cookie和User-Agent,
# 使用urllib.request.Request()才能調用該功能。
Headers = { }
Headers["Cookie"]=r'OUTFOX_SEARCH_USER_ID_NCOO=1564612197.2237918; OUTFOX_SEARCH_USER_ID="1638006579@10.108.160.19"; _ga=GA1.2.269278628.1571982437; _ntes_nnid=db62add68d78e9de1c202b8b131b32a4,1579175684866; JSESSIONID=aaaGcKLB2j8UhdX6Q3V_w; SESSION_FROM_COOKIE=unknown; ___rl__test__cookies=1579203741289'
Headers["User-Agent"]=r"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"
data = { } #post請求需要的data參數,在網頁檢查的Form Data中,
#data["i"]="I am jalen" #認真一點你會發現這就是我們輸入的值,自己做一個簡單的有道翻譯只需要修改這裡就可以實現
data["i"] = input #那就按照習慣在函數外單獨輸入經常變化的值
data["from"]="AUTO"
data["to"]="AUTO"
data["smartresult"]="dict"
data["client"]="fanyideskweb"
data["salt"]="15792037412906"
data["sign"]="324404ee89ccb63c2ea1efb7d311db26"
data["ts"]="1579203741290"
data["bv"]="74b3450c611e373bdb05dc0a4ecdedd0"
data["doctype"]="json"
data["version"]="2.1"
data["keyfrom"]="fanyi.web"
data["action"]="FY_BY_CLICKBUTTION"
data = urllib.parse.urlencode(data).encode("utf-8") #post請求的data參數格式轉化
req = urllib.request.Request(url,data,Headers)
response = urllib.request.urlopen(req,timeout=30)
html = response.read().decode("utf-8") #返回網頁內容
# print(type(html),html) #後面就可以解析了,解析部分在後面的文章中有單獨講解,但這裡還是繼續寫完本例
target = json.loads(html) #json解析後面的文章會單獨講解
print("翻譯結果:%s" % (target['translateResult'][0][0]['tgt']))
# 翻譯結果:我是羅斯
if __name__ == '__main__':
input = "I am jalen"
time.sleep(5) #延時提交
youdao(input)
1.5、隱藏、請求超時、延時提交在4中得代碼中已經有體現了,簡單的回顧一下:
(1)隱藏:隱藏身份,Headers必須是字典,在網頁檢查的Request Headers中,常調用和修改Cookie和User-Agent,使用urllib.request.Request()才能調用該功能。如:req = urllib.request.Request(url,data,Headers)(2)請求超時:在設定的時間範圍內如果網頁沒有成功請求,則返回錯誤如:response = urllib.request.urlopen(req,timeout=0.3)(3)延時提交:time.sleep(n) ,n表示秒數二、urllib庫高級應用2.1、Handler和Opener簡介Handler類,可以把他理解為各種處理器,有處理登錄驗證的,有處理cookies的,有處理代理設置的等。
urllib.request模塊裡的 BaseHandler 類,是Handler 的父類 。它提供了如 default_open ()、 protocol_request ()等方法。
各種Handler子類繼承這個BaseHandler類。如:
HTTPDefaultErrorHandler:用於處理HTTPError類型的異常。HTTPRedirectHandler:用於處理重定向。HTTPCookiesProcessor:用於處理cookies。ProxyHandler:用於設置代理,默認代理為空。HTTPpasswordMgr:用於管理密碼,它維護了用戶名和密碼的表。HTTPBasicAuthHandler:用於管理認證,如果一個了解打開時需要認證,那麼可以用它來解決認證問題。其他,查看參考文檔:https://docs.python.org/3/library/urllib.request.html#urllib.request.BaseHandler.Opener類, 也就是OpenerDirector類 。urlopen()這個方法,就是urllib提供的一個Opener 。Request 和 urlopen( )相當於類庫已經封裝好了常用來做get或post請求的方法,利用它們可以完成基本的請求。實現更高級的功能時,需要深入一層進行個性化配置,使用更底層的實例來完成操作,就用到了 Opener 。通常利用 Handler 來構建 Opener 。Opener 可以使用 open ()方法,返回的類型和 urlopen ()一樣。
案例說明:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener
from urllib.error import URLError
username = 'username'
password = 'password'
url = 'http://localhost:5000/' #DB2默認埠號為:5000;
# 1. 構建一個密碼管理對象,用來保存需要處理的用戶名和密碼
p = HTTPPasswordMgrWithDefaultRealm()
# 2. 添加帳戶信息,第一個參數realm是與遠程伺服器相關的域信息,一般沒人管它都是寫None,後面三個參數分別是 Web伺服器、用戶名、密碼
p.add_password(None, url, username, password)
# 3. 構建一個HTTP基礎用戶名/密碼驗證的HTTPBasicAuthHandler處理器對象,參數是創建的密碼管理對象
auth_handler = HTTPBasicAuthHandler(p)
# 4. 通過 build_opener()方法使用這些代理Handler對象,創建自定義opener對象,參數包括構建的 proxy_handler
opener = build_opener(auth_handler)
try:
result = opener.open(url)
html = result.read().decode("utf-8")
print(html)
except URLError as e:
print(e.reason)
'''
這裡首先實例化 HTTPBasicAuthHandler 對象,其參數是 HTTPPasswordMgrWithDefaultRealm 對象,
它利用 add_password ()添加進去用戶名和密碼,這樣就建立了一個處理驗證的 Handler.
接下來,利用這個Handler 並使用 build_opener ()方法構建一個 Opener ,這個 Opener 在發送請求
時就相當於已經驗證成功了 。
接下來,利用 Opener 的 open ()方法打開連結,就可以完成驗證了 。 這裡獲取到的結果就是驗證
'''
2.2、urllib庫免費代理ip的使用from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
proxy_handler = ProxyHandler({'http':'http://139.108.123.4:3128','https':'https://157.245.54.87:8080'})
opener = build_opener(proxy_handler)
try:
response = opener.open('https://www.baidu.com')
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)
2.3、urllib庫Cookies 的處理#網站的 Cookies 獲取
import http.cookiejar, urllib.request
cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open ('http://www.baidu.com')
for item in cookie:
print(item.name +'= '+ item.value)
'''
輸出:
BAIDUID= C8BD9A03380D17E0F44167FD4DCE452E:FG=1
BIDUPSID= C8BD9A03380D17E01BB36C142C466E1D
H_PS_PSSID= 1431_21118_30495_26350_30481
PSTM= 157****043
delPer= 0
BDSVRTM= 0
BD_HOME= 0
'''#Cookies 實際上也是以文本形式保存
import http.cookiejar, urllib.request
filename = 'cookies.txt'
cookie = http.cookiejar.MozillaCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open("http://www.baidu.com")
cookie.save(ignore_discard=True, ignore_expires=True)#保存成 libwww-perl(LWP)格式的 Cookies 文件
import http.cookiejar, urllib.request
filename = 'cookies.txt'
cookie = http. cookiejar. LWPCookieJar (filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open("http://www.baidu.com")
cookie.save(ignore_discard=True, ignore_expires=True)#利用cookie
import http.cookiejar, urllib.request
cookie = http.cookiejar.LWPCookieJar( ) #LWPCookie格式
# cookie = http.cookiejar.MozillaCookieJar( ) #MozillaCookie格式
cookie.load(r'cookies.txt',ignore_discard=True,ignore_expires=True)
handler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handler)
response=opener.open('http://www.baidu.com')
print(response.read().decode('utf-8'))
三、urllib庫異常處理urllib的error模塊定義了由request模塊產生的異常。如果出現了問題,request模塊便會拋出error模塊中定義的異常。
#基本用法:
from urllib import request, error
from urllib.error import HTTPError ,URLError
try:
"代碼塊"
except error.URLError as e:
print(e.reason,e.code,e.headers,sep='\n')
except (HTTPError, URLError, socket.timeout, AttributeError,UnicodeEncodeError) as e1:
return
else:
print("Request Successfully")我們打開一個不存在的頁面,照理來說應該會報錯,但是這時我們捕獲了URLError這個異常,運行結果程序沒有直接報錯,而是輸出了指定輸出的內容並跳過執行下一條。在很多請求連結的時候避免程序異常終止,同時異常得到了有效處理,通常我們會記錄下異常的url,異常原因,單獨將結果保存,然後先跳過繼續下面的爬去,最後再進一步處理異常值(不同的異常採取不同的處理方法)。
常見異常:URLError, HTTPError, socket.timeout 等
code:返回HTTP狀態碼,比如404表示網頁不存在,500表示伺服器內部錯。