爬蟲小白:02-urllib的使用

urllib的使用

一、request模塊

http://httpbin.org 是github的http測試的接口。httpbin.org 這個網站能測試 HTTP 請求和響應的各種信息,比如 cookie、ip、headers 和登錄驗證等,且支持 GET、POST 等多種方法,對 web 開發(fā)和測試很有幫助。

導入模塊:
1、import urllib
使用:urllib.request.
但這樣會報錯: AttributeError: module 'urllib' has no attribute 'request'
原因:在python3中request被作為一個模塊,而不是方法。
解決方法:將request作為一個模塊,如import urllib.request。

2、from urllib import request
requset.
?
1、urlopen()方法:是一個簡單發(fā)送網絡請求的方法。它接收一個字符串格式的 url ,它會向傳入的 url發(fā)送網絡請求,然后返回結果。
參數:
(1)url='' #字符串格式
例:
import urllib
response =urllib.request.urlopen(url='http://httpbin.org/get')

(2)data:是可選的,傳入它則會發(fā)起POST請求,否則默認會發(fā)送get請求。data參數是字節(jié) 類型、或者類文件對象或可迭代對象。
import urllib import request
response = request.urlopen(url='http://httpbin.org/post',
data=b'username=wsq&password=123')

用data就是post請求,字節(jié)類型,用b''來轉換成字節(jié),且data中的數據會作為表單中的數據。

(3)timeout:設置超時時間,以秒為單位。如果請求超過設置時間,則拋出異常;若沒有指定 則用系統(tǒng)默認設置。timeout參數只對 http、https以及ftp連接起作用。
報錯會出現: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ā)起最基本的請求,但這幾個參數不足以構件一個完整的請求,可以利用 Request對象來構建更加完整的請求。
(1) 請求頭添加:
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:這個涉及防盜鏈技術,假如爬取一個圖片出現403,在請求頭里添加上它,大多數都 可以解決。

(2) 操作Cookie。(但不會用它操作,日后常用request)
(3) 設置代理:自己寫個代理庫。(間接請求,保護自己的IP地址)
(4) 驗證:
?</pre>

3、Response對象:
urllib庫中的類或者方法,在發(fā)送網絡請求后,都會返回一個urllib.response的對象(例如: http.client.HTTPResponse object at ......)
它包含了請求回來的數據結果。它包含一些屬性和方法,供我們處理返回的結果。

(1)、read():獲取響應返回的數據,只能用一次。和文件句柄一樣,只能運行一次。#返回的是字節(jié)碼,decode() 解碼成字符串。
(2)、readline():讀取一行。沒必要。
while True:
data = response.readline()
if data:
print(data)
(3)、info():獲取響應頭信息。 print(response.info())
(4)、geturl():獲取訪問的url。 print(response.geturl())
(5)、getcode() :返回狀態(tài)碼。 print(response.getcode())</pre>

二、parse模塊

parse模塊是一個工具模塊,提供了需要對url處理的方法,用于解析url。
注意: url中只能包含ascii字符,在實際操作過程中,get請求通過url傳遞的參數中會有大量特殊字符 (非ascii字符),例如漢字,那么就需要進行url編碼。(一個中文用UTF-8有3個字節(jié)。)
導包:from urllib import parse(import urllib不行問題同上)

方法:
1、parse.quote():編碼
例: url = 'http://httpbin.org/get?username={}'
result = url.format(parse.quote('思齊')) #format方法別忘了
print(result)

結果為: http://httpbin.org/get?username=%E6%80%9D%E9%BD%8A

2、parse.unquote():反編碼,看看具體參數是什么。
例1:
print(parse.unquote(result))

結果為: http://httpbin.org/get?username=思齊

3、parse.urlencode():在發(fā)送請求時,往往會需要傳遞很多的參數,如果用字符串拼接會很麻 煩,該方法就是用來拼接url參數的。
例1: args = {'username':'思齊','password':'小淘'}
res = parse.urlencode(args) #注意字典形式
print(res)

結果為: 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)

結果為: http://httpbin.org/get?username=%E6%80%9D%E9%BD%8A&pd=123

注:url中規(guī)定多個參數 & 連接。

4、parse.parse_qs(): 和parse.urlencode()是相反的,將它轉會字典。
例:print(parse.parse_qs(res))

結果為:{'username': ['思齊'], 'pd': ['123']}

{'http://httpbin.org/get?username': ['思齊'], 'pd': ['123']}

錯誤信息:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) #當出現這種錯誤時就是參數用的不是ascii碼。</pre>

三、error模塊

error模塊主要負責異常處理,如果請求出現錯誤,我們可以用error模塊進行處理,該模塊主要包含
URLError和HTTPError
?
導包:from urllib import error
1.URLError:是error模塊的基類,由request模塊產生的的異常都可以用這個類來處理。
?
2.HTTPError:是的子類,主要包含三個屬性:code:請求的狀態(tài)碼、reason:錯誤的原因、headers: 響應的報頭。
例:
try:
request.urlopen('http://www.itdecent.cn')#不是合法的用戶會被 ban。
except error.HTTPError as e:
print(e.code)
print(e.reason)
print(e.headers)</pre>

四、robotparse模塊

robotparse模塊主要負責處理爬蟲協議文件,robots.txt的文件。
導包:from urllib import robotparse
https://www.amazon.cn/robots.txt #亞馬遜中國的爬蟲協議,如圖1</pre>

urllib3的使用

介紹:是一個基于python3的功能強大,友好的http客戶端。
保證線程安全(不需考慮鎖的問題),連接池保持(而不向之前的一樣連一下關一下),支持重復請求、重定位,保證代碼百分百被使用。
?
導包:import urllib3
?
(1)構造請求(request):
1.實例化一個PoolManager對象構造請求,這個實例對象處理了連接池和線程安全的所有細節(jié),所以我們不用自行處 理。
例: http = urllib3.PoolManager()
在這里我出現了一個錯誤,如下:
AttributeError: module 'urllib3的使用' has no attribute 'PoolManager',我出現 這個原因是py文件所在的文件夾命名為urllib3。

2.用request()方法發(fā)送請求,可以用request()方法發(fā)送任意請求,GET POST....
第一個參數是何種類型的請求;第二個參數是請求的網站。

例1:發(fā)送get請求
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')
此處傳的二進制數據報錯

例2:發(fā)送POST請求
response = http.request('POST','http://httpbin.org/post',
fields={'hello':'world'})

3.請求傳入數據(data):

  • Headers:加入請求頭
    在request方法中添加字典格式的headers參數來指定請求頭。
    例:http = urllib3.PoolManager()
    response = http.request('POST','http://httpbin.org/get ',
    headers={'key':'value'})

  • Query parameters(字符串參數):
    *get,head,delete請求,可通過提供字典類型的參數fields來添加查詢參數。(復習一 下:在urllib中我們通過parse.quote()編碼這里只需提供fields參數即可)
    例:http = urllib3.PoolManager()
    response = http.request('get','http://httpbin.org/get ',
    fields={'key':'value'})

*對于post,put請求,如果需要查詢參數,需要通過url編碼將參數編碼正確格式再拼接到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(表單數據):
對于post,put,需要提供字典類型的參數fields來傳遞form表單數據。
response = http.request('post','http://httpbin.org/get ',
fields={'key':'value'})

*json數據
當我們需要發(fā)送json數據時,我們需要在request方法中傳入編碼后的二進制數據類型的body參數,并 指定Content-Type的請求頭。

*文件上傳(通常不用這個上傳)
對于文件上傳,我們可以模仿瀏覽器表單的方式

對于二進制數據上傳,我們用指定body的方式,并設置Content-Type的請求頭。

*注意:get,head,delete請求中提供fields參數會自動拼接到url中,而對post,put請求中你提供的 fields參數會填寫到form表單中,若你想拼接到url中只能主動的使用字符串拼接的方法。
(2)http響應對象提供 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響應對象

print(response.data) #返回的是二進制數據
print(response.headers)#返回的是<class 'urllib3._collections.HTTPHeaderDict'>

字典形式,因此可以通過鍵名看鍵值

print(response.status)

(3)返回的是 json格式數據 可以通過json模塊,loads為字典數據類型。
例:
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)返回的數據都是字節(jié)類型,對于大量的數據我們通過stream(流)來處理更好,也可以當作一個文件對象來處理。
例1:流
import urllib3
http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/bytes/1024',
preload_content = False)
for i in response.stream(32): #一點點讀對內存好,下圖片就可以用這種方法
print(i)

例2:文件對象
import urllib3
http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/bytes/1024', preload_content = False)
for line in response: #比如說大文件可能5G大小,不能一次性回來,一批一批的回來
print(line)

(5)代理
例1:import urllib3
proxy = urllib3.ProxyManager('http://ip:端口號')
//用這個ip來幫助你來向某網站發(fā)送請求,保護了你自己的ip地址不被暴露。

response = proxy.request('get','http://httpbin.org/ip')
//http://httpbin.org/ip 查看請求的ip地址

print(response.data)

//遇到如下錯誤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',))) 如果是初次使用代理,以上三 種錯誤出現的原因基本是1.端口錯誤2.代理類型不正確。 明確的一點是訪問https站點,要用https類型的代理。http同理。(當然我找的是免費代理,可能不好用。)
?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯系作者。

相關閱讀更多精彩內容

友情鏈接更多精彩內容