urllib庫(kù)是python內(nèi)置的HTTP請(qǐng)求庫(kù)。
包含以下四個(gè)模塊:
1) request 最基本的HTTP請(qǐng)求模塊,可以用來(lái)模擬發(fā)送請(qǐng)求壹店。
2)error 異常處理模塊
3)parse 一個(gè)工具模塊扫茅,提供了許多URL處理方法哥牍,比如拆分卒暂,解析饶号,合并等激率。
4)robotparser 用來(lái)識(shí)別網(wǎng)站的robots.txt文件咳燕,從而判斷哪些網(wǎng)站可以爬,哪些網(wǎng)站不可以爬乒躺。
1.request 模塊
1.1 urlopen()
import urllib.request
response = urllib.request.urlopen(url)
得到的response是一個(gè)HTTPResponse類型的對(duì)象招盲,主要包含read(),readinto(),getheader(name),getheaders(),fileno()等方法,以及msg,version,status,reason等屬性嘉冒。
通過(guò)urlopen()得到response這個(gè)對(duì)象后曹货,就可以調(diào)用上面提到的這些方法和屬性,從而得到返回結(jié)果的一系列對(duì)象讳推,
-
urlopen函數(shù)的API
Urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None,cadefault=False,context=None)
-
data 參數(shù)
data參數(shù)是可選的顶籽,如果要添加這個(gè)參數(shù),就需要使用bytes()方法將參數(shù)轉(zhuǎn)化為字節(jié)流編碼格式的內(nèi)容银觅,即bytes類型礼饱。如果使用了這個(gè)參數(shù)就不在是GET請(qǐng)求而是POST請(qǐng)求了。import urllib.parse import urllib.request data = bytes(urllib.parse.urlencode({'word':'hello'}),encoding='utf8') response = urllib.request.urlopen(url,data=data) print(response.read())
在這里我們傳遞了一個(gè)參數(shù)為word,值是hello究驴。它需要被轉(zhuǎn)碼成bytes類型镊绪,采用的方法就是bytes()方法,該方法的第一個(gè)參數(shù)需要的是str類型洒忧,需要使用urllib.parse模塊里的urlencode方法來(lái)將參數(shù)字典轉(zhuǎn)換為字符串蝴韭,第二個(gè)參數(shù)指定編碼格式,這里指定為utf8跑慕。
-
timeout參數(shù)
該參數(shù)用于設(shè)置超時(shí)時(shí)間万皿,單位為秒摧找,超過(guò)設(shè)置的這個(gè)時(shí)間還沒(méi)有得到響應(yīng)就會(huì)拋出異常核行,如果不指定牢硅,就會(huì)使用全局默認(rèn)時(shí)間。
-
1.2 Request
urllib.request.Request(url,data=None,headers={},origin_req_host=None,unverifiable=False,method=None)
URL用來(lái)請(qǐng)求URL芝雪,必傳參數(shù)减余,其他的都是可選參數(shù)
data如果要傳,就必須傳bytes類型的惩系,如果參數(shù)為字典位岔,可以先用urllib.parse模塊里的urlencode編碼。
headers是一個(gè)字典堡牡,請(qǐng)求頭抒抬,可以在構(gòu)造請(qǐng)求是通過(guò)headers參數(shù)直接構(gòu)造,也可以通過(guò)調(diào)用請(qǐng)求實(shí)例的add_header()方法添加re晤柄。
Method是一個(gè)字符串擦剑,用來(lái)指示請(qǐng)求使用的方法
1.3高級(jí)用法
-
代理
from urllib.error import UELError from urllib.request import ProxyHandler,build_opener proxy_handler = ProxyHandler({ 'http':'http://', 'https':'https://' }) opener = build_opener(proxy_handler) try: response = opener.open(url) print(response.read().decode('utf-8')) except URLError as e: print(e.reason)
這里使用了ProxyHandler其參數(shù)是一個(gè)字典,鍵名是協(xié)議類型(http或者h(yuǎn)ttps)芥颈,鍵值是代理鏈接惠勒,可以添加多個(gè)代理IP。
然后利用這個(gè)Handler以及build_opener()方法構(gòu)造了一個(gè)Opener爬坑,之后發(fā)送即可纠屋。
-
Cookies
-
獲取網(wǎng)站的Cookies
import http.cookiejar,urllib.request cookie = http.cookiejar.CookieJar() handler = urllib.request.HTTPCookieProcessor(cookie) opener = urllib.request.build_opener(handler) response = opener.oepn(url) for item in cookie: print(item.name+"="+item.value)
首先聲明一個(gè)CookieJar對(duì)象,然后利用HTTPCookieProcessor來(lái)構(gòu)建一個(gè)Handler,最后利用build_opener()方法來(lái)構(gòu)建出opener,執(zhí)行open即可盾计。
-
以文件形式獲取Cookie
filename = 'cookies.txt' cookie = http.cookiejar.MozillaCookieJar(filename) handler = urllib.request.HTTPCookieProcessor(cookie) opener = urllib.request.build_opener(handler) response = opener.oepn(url) cookie.save(ignore_discard=True,ignore_expires=True)
-
2.處理異常
urllib的error模塊定義了由request模塊產(chǎn)生的異常售担。
2.1URLError
URLError類來(lái)自u(píng)rllib庫(kù)的error模塊,它繼承自O(shè)SError類署辉,是error異常模塊的基類灼舍,由request模塊產(chǎn)生的異常都可以通過(guò)捕獲和這個(gè)類來(lái)處理
這個(gè)類具有一個(gè)reason屬性,即返回的錯(cuò)誤的原因涨薪。
from urllib import request,error
try:
.....
except error.URLError as e:
print(e.reason)
2.2HTTPError
它是URLError的子類骑素,專門用來(lái)處理HTTP請(qǐng)求錯(cuò)誤。它有三個(gè)屬性
code 返回HTTP狀態(tài)碼
reason 返回錯(cuò)誤信息
headers 返回請(qǐng)求頭
3解析鏈接
urllib庫(kù)里提供了一個(gè)parse模塊刚夺,定義處理URL的標(biāo)準(zhǔn)接口献丑,例如實(shí)現(xiàn)URL各部分的抽取,合并以及鏈接轉(zhuǎn)換
3.1 urlparse(urlstring,shcme='',allow_fragments=True)
- urlstring 必填項(xiàng) 待解析的url
- Scheme 默認(rèn)的協(xié)議侠姑,如果這個(gè)鏈接沒(méi)有帶協(xié)議信息创橄,會(huì)將這個(gè)作為默認(rèn)的協(xié)議。
- allow_fragments 即是否忽略fragment莽红,如果設(shè)置為False妥畏,則fragment部分就會(huì)被忽略邦邦,會(huì)成為其他的一部分,而fragment則為空
from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html;user?id=5#comment')
print(type(result),result)
<class 'urllib.parse.ParseResult'> ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')
從打印的結(jié)果可以看出醉蚁,返回的是一個(gè)ParseResult類型的對(duì)象燃辖,它包含了6個(gè)部分,分別是scheme(協(xié)議网棍,比如http,https),netloc(域名),path(訪問(wèn)路徑),params(參數(shù)),query(問(wèn)號(hào)后面的查詢條件),fragment(#后面的內(nèi)容).
一個(gè)標(biāo)準(zhǔn)的鏈接格式: scheme://netloc/path;params?query#fragment
3.2urlunparse()
與urlparse()方法的對(duì)立黔龟。它接受的參數(shù)是一個(gè)可迭代對(duì)象,長(zhǎng)度必須為6滥玷,即傳入6個(gè)參數(shù)氏身,返回的結(jié)果是組裝好的URL.
data = ['http','www.baidu.com','index.html','user','a=6','comment']
print(urlunparse(data))
得到的結(jié)果為
http://www.baidu.com/index.html;user?a=6#comment
3.3urlsplit()與urlunsplit()
這個(gè)方法和urlparse()方法類似,只不過(guò)不在解析parms這個(gè)部分惑畴,只返回五個(gè)結(jié)果蛋欣。parms部分會(huì)合并到path中。
3.4 urljoin()
使用URLjoin方法 需要提供一個(gè)base_url作為第一參數(shù)如贷,將新的鏈接作為第二個(gè)參數(shù)陷虎,然后會(huì)合成一個(gè)新的鏈接。
Base_url 提供了三項(xiàng)內(nèi)容倒得,scheme,netloc,path.如果這三項(xiàng)在新的鏈接中不存在就補(bǔ)充泻红,如果新的鏈接存在,就使用新的鏈接中的部分霞掺。
3.5 urlencode() 與 parse_qs()
from urllib.parse import urlencode
params = {
'name':'germey',
'age':22
}
base_url = 'http://www.baidu.com?'
url = base_url + urlencode(params)
print(url)
結(jié)果為:
http://www.baidu.com?name=germey&age=22
將字典類型轉(zhuǎn)換為GET請(qǐng)求參數(shù)谊路。
如果我們有一串GET請(qǐng)求參數(shù),利用parse_qs()方法菩彬,就可以將參數(shù)轉(zhuǎn)換為字典
3.5 quote()與unquote()
Quote將中文轉(zhuǎn)化為URL編碼的格式
from urllib.parse import quote
url_word = quote(keyword)
unquote將URL編碼解碼成中文