urllib的使用
一贾虽、request模塊
http://httpbin.org 是github的http測(cè)試的接口省骂。httpbin.org 這個(gè)網(wǎng)站能測(cè)試 HTTP 請(qǐng)求和響應(yīng)的各種信息器联,比如 cookie蕉世、ip、headers 和登錄驗(yàn)證等狭姨,且支持 GET宰啦、POST 等多種方法,對(duì) web 開(kāi)發(fā)和測(cè)試很有幫助饼拍。
導(dǎo)入模塊:
1赡模、import urllib
使用:urllib.request.
但這樣會(huì)報(bào)錯(cuò): AttributeError: module 'urllib' has no attribute 'request'
原因:在python3中request被作為一個(gè)模塊,而不是方法师抄。
解決方法:將request作為一個(gè)模塊漓柑,如import urllib.request。
2叨吮、from urllib import request
requset.
?
1辆布、urlopen()方法:是一個(gè)簡(jiǎn)單發(fā)送網(wǎng)絡(luò)請(qǐng)求的方法。它接收一個(gè)字符串格式的 url 茶鉴,它會(huì)向傳入的 url發(fā)送網(wǎng)絡(luò)請(qǐng)求锋玲,然后返回結(jié)果。
參數(shù):
(1)url='' #字符串格式
例:
import urllib
response =urllib.request.urlopen(url='http://httpbin.org/get')
(2)data:是可選的涵叮,傳入它則會(huì)發(fā)起POST請(qǐng)求惭蹂,否則默認(rèn)會(huì)發(fā)送get請(qǐng)求伞插。data參數(shù)是字節(jié) 類型、或者類文件對(duì)象或可迭代對(duì)象盾碗。
import urllib import request
response = request.urlopen(url='http://httpbin.org/post',
data=b'username=wsq&password=123')
用data就是post請(qǐng)求,字節(jié)類型,用b''來(lái)轉(zhuǎn)換成字節(jié),且data中的數(shù)據(jù)會(huì)作為表單中的數(shù)據(jù)蜂怎。
(3)timeout:設(shè)置超時(shí)時(shí)間,以秒為單位置尔。如果請(qǐng)求超過(guò)設(shè)置時(shí)間杠步,則拋出異常;若沒(méi)有指定 則用系統(tǒng)默認(rèn)設(shè)置榜轿。timeout參數(shù)只對(duì) http幽歼、https以及ftp連接起作用。
報(bào)錯(cuò)會(huì)出現(xiàn):urllib.error.URLError: <urlopen error timed out>
from urllib
response =urllib.request.urlopen(url='http://www.baidu.com',
timeout=0.1)
2谬盐、Request類:
解釋:利用urlopen()可以發(fā)起最基本的請(qǐng)求甸私,但這幾個(gè)參數(shù)不足以構(gòu)件一個(gè)完整的請(qǐng)求,可以利用 Request對(duì)象來(lái)構(gòu)建更加完整的請(qǐng)求飞傀。
(1) 請(qǐng)求頭添加:
from urllib import request
headers={
'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64rv:73.0) Gecko/20100101 Firefox/73.0"
} #注意:一定是字典形式皇型。
req = request.Request(url='http://www.baidu.com',headers = headers)
reponse = request.urlopen(req)
Referer:這個(gè)涉及防盜鏈技術(shù),假如爬取一個(gè)圖片出現(xiàn)403砸烦,在請(qǐng)求頭里添加上它弃鸦,大多數(shù)都 可以解決。
(2) 操作Cookie幢痘。(但不會(huì)用它操作唬格,日后常用request)
(3) 設(shè)置代理:自己寫個(gè)代理庫(kù)。(間接請(qǐng)求颜说,保護(hù)自己的IP地址)
(4) 驗(yàn)證:
?</pre>
3购岗、Response對(duì)象:
urllib庫(kù)中的類或者方法,在發(fā)送網(wǎng)絡(luò)請(qǐng)求后门粪,都會(huì)返回一個(gè)urllib.response的對(duì)象(例如: http.client.HTTPResponse object at ......)
它包含了請(qǐng)求回來(lái)的數(shù)據(jù)結(jié)果喊积。它包含一些屬性和方法,供我們處理返回的結(jié)果玄妈。
(1)乾吻、read():獲取響應(yīng)返回的數(shù)據(jù),只能用一次措近。和文件句柄一樣溶弟,只能運(yùn)行一次。#返回的是字節(jié)碼,decode() 解碼成字符串瞭郑。
(2)辜御、readline():讀取一行。沒(méi)必要屈张。
while True:
data = response.readline()
if data:
print(data)
(3)擒权、info():獲取響應(yīng)頭信息袱巨。 print(response.info())
(4)、geturl():獲取訪問(wèn)的url碳抄。 print(response.geturl())
(5)愉老、getcode() :返回狀態(tài)碼。 print(response.getcode())</pre>
二剖效、parse模塊
parse模塊是一個(gè)工具模塊嫉入,提供了需要對(duì)url處理的方法,用于解析url璧尸。
注意: url中只能包含ascii字符咒林,在實(shí)際操作過(guò)程中,get請(qǐng)求通過(guò)url傳遞的參數(shù)中會(huì)有大量特殊字符 (非ascii字符)爷光,例如漢字垫竞,那么就需要進(jìn)行url編碼。(一個(gè)中文用UTF-8有3個(gè)字節(jié)蛀序。)
導(dǎo)包:from urllib import parse(import urllib不行問(wèn)題同上)
方法:
1欢瞪、parse.quote():編碼
例: url = 'http://httpbin.org/get?username={}'
result = url.format(parse.quote('思齊')) #format方法別忘了
print(result)
結(jié)果為: http://httpbin.org/get?username=%E6%80%9D%E9%BD%8A
2、parse.unquote():反編碼徐裸,看看具體參數(shù)是什么遣鼓。
例1:
print(parse.unquote(result))
結(jié)果為: http://httpbin.org/get?username=思齊
3、parse.urlencode():在發(fā)送請(qǐng)求時(shí)倦逐,往往會(huì)需要傳遞很多的參數(shù)譬正,如果用字符串拼接會(huì)很麻 煩,該方法就是用來(lái)拼接url參數(shù)的宫补。
例1: args = {'username':'思齊','password':'小淘'}
res = parse.urlencode(args) #注意字典形式
print(res)
結(jié)果為: username=%E6%80%9D%E9%BD%8A&pd=123
例2:
args = {'username':'思齊','pd':'123'}
result = 'http://httpbin.org/get?{}'.format(parse.urlencode(args))
print(res)
結(jié)果為: http://httpbin.org/get?username=%E6%80%9D%E9%BD%8A&pd=123
注:url中規(guī)定多個(gè)參數(shù) & 連接檬姥。
4、parse.parse_qs(): 和parse.urlencode()是相反的粉怕,將它轉(zhuǎn)會(huì)字典健民。
例:print(parse.parse_qs(res))
結(jié)果為:{'username': ['思齊'], 'pd': ['123']}
{'http://httpbin.org/get?username': ['思齊'], 'pd': ['123']}
錯(cuò)誤信息:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) #當(dāng)出現(xiàn)這種錯(cuò)誤時(shí)就是參數(shù)用的不是ascii碼。</pre>
三贫贝、error模塊
error模塊主要負(fù)責(zé)異常處理秉犹,如果請(qǐng)求出現(xiàn)錯(cuò)誤,我們可以用error模塊進(jìn)行處理稚晚,該模塊主要包含
URLError和HTTPError
?
導(dǎo)包:from urllib import error
1.URLError:是error模塊的基類,由request模塊產(chǎn)生的的異常都可以用這個(gè)類來(lái)處理崇堵。
?
2.HTTPError:是的子類,主要包含三個(gè)屬性:code:請(qǐng)求的狀態(tài)碼客燕、reason:錯(cuò)誤的原因鸳劳、headers: 響應(yīng)的報(bào)頭。
例:
try:
request.urlopen('http://www.reibang.com')#不是合法的用戶會(huì)被 ban也搓。
except error.HTTPError as e:
print(e.code)
print(e.reason)
print(e.headers)</pre>
四赏廓、robotparse模塊
robotparse模塊主要負(fù)責(zé)處理爬蟲協(xié)議文件涵紊,robots.txt的文件。
導(dǎo)包:from urllib import robotparse
https://www.amazon.cn/robots.txt #亞馬遜中國(guó)的爬蟲協(xié)議幔摸,如圖1</pre>
urllib3的使用
介紹:是一個(gè)基于python3的功能強(qiáng)大摸柄,友好的http客戶端。
保證線程安全(不需考慮鎖的問(wèn)題)既忆,連接池保持(而不向之前的一樣連一下關(guān)一下)驱负,支持重復(fù)請(qǐng)求、重定位患雇,保證代碼百分百被使用电媳。
?
導(dǎo)包:import urllib3
?
(1)構(gòu)造請(qǐng)求(request):
1.實(shí)例化一個(gè)PoolManager對(duì)象構(gòu)造請(qǐng)求,這個(gè)實(shí)例對(duì)象處理了連接池和線程安全的所有細(xì)節(jié),所以我們不用自行處 理。
例: http = urllib3.PoolManager()
在這里我出現(xiàn)了一個(gè)錯(cuò)誤庆亡,如下:
AttributeError: module 'urllib3的使用' has no attribute 'PoolManager'匾乓,我出現(xiàn) 這個(gè)原因是py文件所在的文件夾命名為urllib3。
2.用request()方法發(fā)送請(qǐng)求,可以用request()方法發(fā)送任意請(qǐng)求又谋,GET POST....
第一個(gè)參數(shù)是何種類型的請(qǐng)求;第二個(gè)參數(shù)是請(qǐng)求的網(wǎng)站拼缝。
例1:發(fā)送get請(qǐng)求
response = http.request('GET','http://httpbin.org/get ',b'User- Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64rv:73.0) Gecko/20100101 Firefox/73.0')
此處傳的二進(jìn)制數(shù)據(jù)報(bào)錯(cuò)
例2:發(fā)送POST請(qǐng)求
response = http.request('POST','http://httpbin.org/post',
fields={'hello':'world'})
3.請(qǐng)求傳入數(shù)據(jù)(data):
Headers:加入請(qǐng)求頭
在request方法中添加字典格式的headers參數(shù)來(lái)指定請(qǐng)求頭。
例:http = urllib3.PoolManager()
response = http.request('POST','http://httpbin.org/get ',
headers={'key':'value'})Query parameters(字符串參數(shù)):
*get,head,delete請(qǐng)求彰亥,可通過(guò)提供字典類型的參數(shù)fields來(lái)添加查詢參數(shù)咧七。(復(fù)習(xí)一 下:在urllib中我們通過(guò)parse.quote()編碼這里只需提供fields參數(shù)即可)
例:http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/get ',
fields={'key':'value'})
*對(duì)于post,put請(qǐng)求,如果需要查詢參數(shù)任斋,需要通過(guò)url編碼將參數(shù)編碼正確格式再拼接到url中继阻。
例: 如圖1、2废酷、3
import urllib3
import urllib.parse import urlencode
import json
http = urllib3.PoolManager()
args = {'username':'思齊','password':'小淘'}
方法一:
result = urlencode(args)
url = 'http://httpbin.org/post?' + result #字符串拼接
方法二:
url1 = 'http://httpbin.org/post?{}'
url1 = url.format(parse.urlencode(args))
response = http.request('POST',url)
print(json.loads(response.data.decode('utf-8')))
*form data(表單數(shù)據(jù)):
對(duì)于post,put瘟檩,需要提供字典類型的參數(shù)fields來(lái)傳遞form表單數(shù)據(jù)。
response = http.request('post','http://httpbin.org/get ',
fields={'key':'value'})
*json數(shù)據(jù)
當(dāng)我們需要發(fā)送json數(shù)據(jù)時(shí)澈蟆,我們需要在request方法中傳入編碼后的二進(jìn)制數(shù)據(jù)類型的body參數(shù)墨辛,并 指定Content-Type的請(qǐng)求頭。
*文件上傳(通常不用這個(gè)上傳)
對(duì)于文件上傳,我們可以模仿瀏覽器表單的方式
對(duì)于二進(jìn)制數(shù)據(jù)上傳趴俘,我們用指定body的方式睹簇,并設(shè)置Content-Type的請(qǐng)求頭。
*注意:get,head,delete請(qǐng)求中提供fields參數(shù)會(huì)自動(dòng)拼接到url中寥闪,而對(duì)post,put請(qǐng)求中你提供的 fields參數(shù)會(huì)填寫到form表單中太惠,若你想拼接到url中只能主動(dòng)的使用字符串拼接的方法。
(2)http響應(yīng)對(duì)象提供 status疲憋、data凿渊、headers等屬性
例1:
import urllib3
http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/get')
print(type(response))#返回的是<class 'urllib3.response.HTTPResponse'>
也就是http響應(yīng)對(duì)象
print(response.data) #返回的是二進(jìn)制數(shù)據(jù)
print(response.headers)#返回的是<class 'urllib3._collections.HTTPHeaderDict'>
字典形式,因此可以通過(guò)鍵名看鍵值
print(response.status)
(3)返回的是 json格式數(shù)據(jù) 可以通過(guò)json模塊,loads為字典數(shù)據(jù)類型。
例:
import urllib3
import json
http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/ip')
print(json.load(response.data.decode('utf-8')))
// response.data.decode('utf-8') 解碼成字符串嗽元。
(4)返回的數(shù)據(jù)都是字節(jié)類型敛纲,對(duì)于大量的數(shù)據(jù)我們通過(guò)stream(流)來(lái)處理更好,也可以當(dāng)作一個(gè)文件對(duì)象來(lái)處理剂癌。
例1:流
import urllib3
http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/bytes/1024',
preload_content = False)
for i in response.stream(32): #一點(diǎn)點(diǎn)讀對(duì)內(nèi)存好淤翔,下圖片就可以用這種方法
print(i)
例2:文件對(duì)象
import urllib3
http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/bytes/1024', preload_content = False)
for line in response: #比如說(shuō)大文件可能5G大小,不能一次性回來(lái)佩谷,一批一批的回來(lái)
print(line)
(5)代理
例1:import urllib3
proxy = urllib3.ProxyManager('http://ip:端口號(hào)')
//用這個(gè)ip來(lái)幫助你來(lái)向某網(wǎng)站發(fā)送請(qǐng)求旁壮,保護(hù)了你自己的ip地址不被暴露。
response = proxy.request('get','http://httpbin.org/ip')
//http://httpbin.org/ip 查看請(qǐng)求的ip地址
print(response.data)
//遇到如下錯(cuò)誤urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='115.210.79.22', port=8118): Max retries exceeded with url: http://httpbin.org/ip (Caused by ProxyError('Cannot connect to proxy.', NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f7ed4c1aef0>: Failed to establish a new connection: [Errno 111] Connection refused',))) 如果是初次使用代理谐檀,以上三 種錯(cuò)誤出現(xiàn)的原因基本是1.端口錯(cuò)誤2.代理類型不正確抡谐。 明確的一點(diǎn)是訪問(wèn)https站點(diǎn),要用https類型的代理。http同理桐猬。(當(dāng)然我找的是免費(fèi)代理麦撵,可能不好用。)
?