首頁 > 軟體

Python爬蟲之urllib庫詳解

2022-02-09 13:00:50

一、說明:

urllib庫是python內建的一個http請求庫,requests庫就是基於該庫開發出來的,雖然requests庫使用更方便,但作為最最基本的請求庫,瞭解一下原理和用法還是很有必要的。

二、urllib四個模組組成:

urllib.request  
請求模組(就像在瀏覽器輸入網址,敲回車一樣)

urllib.error   
例外處理模組(出現請求錯誤,可以捕捉這些異常)

urllib.parse  
url解析模組

urllib.robotparser
robots.txt解析模組,判斷哪個網站可以爬,哪個不可以爬,用的比較少

在python2與python3中有所不同

在python2中:

import urllib2
response = urllib2.urlopen('http://www.baidu.com')

在python3中:

import  urllib.request
response = urllib.request.urlopen('http://www.baidu.com')

三、urllib.request

1、urlopen函數

urllib.request.urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,*, cafile=None, capath=None, cadefault=False, context=None)

url引數

from urllib import request
response = request.urlopen('http://www.baidu.com')
print(response.read().decode('utf-8'))

data引數

沒有data引數時,傳送的是一個get請求,加上data引數後,請求就變成了post方式(利用’http://httpbin.org測試網址)

import urllib.request
import urllib.parse

data1= bytes(urllib.parse.urlencode({'word':'hello'}),encoding='utf-8')
response = urllib.request.urlopen('http://httpbin.org/post',data = data1)
print(response.read())

data引數需要bytes型別,所以需要使用bytes()函數進行編碼,而bytes函數的第一個引數需要時str型別,所以使用urllib.parse.urlencode將字典轉化為字串。

timeout引數

設定一個超時的時間,如果在這個時間內沒有響應,便會丟擲異常

import urllib.request

try:
    response = urllib.request.urlopen('http://www.baidu.com', timeout=0.001)
    print(response.read())
except:
    print('error') 

將超時時間設定為0.001秒,在這個時間內,沒有響應,輸出error

2、response 響應型別

import urllib
from urllib import request
 
response = urllib.request.urlopen('http://www.baidu.com')
print(type(response))

狀態碼與響應頭

import urllib
from urllib import request

response = urllib.request.urlopen('http://www.baidu.com')
print(response.status)
print(response.getheaders())
print(response.getheader('Server'))

read方法

import urllib.request

response = urllib.request.urlopen('http://www.baidu.com')
print(type(response.read()))
print(response.read().decode('utf-8'))

response.read()返回的是bytes形式的資料,所以需要用decode(‘utf-8’)進行解碼。

3、Request物件 

如果我們需要傳送複雜的請求,在urllib庫中就需要使用一個Request物件

import urllib.request
 
#直接宣告一個Request物件,並把url當作引數直接傳遞進來
request = urllib.request.Request('http://www.baidu.com')
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))

宣告了一個Request物件,把url當作引數傳遞給這個物件,然後把這個對昂作為urlopen函數的引數

更復雜的請求,加headers

#利用Request物件實現一個post請求

import urllib.request
url = 'http://httpbin.org/post'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
}
data = {'word':'hello'}
data = bytes(str(data),encoding='utf-8')
req = urllib.request.Request(url = url,data = data,headers = headers,method = 'POST')
response = urllib.request.urlopen(req)
print(response.read().decode('utf-8'))

上面的這個請求包含了請求方式、url,請求頭,請求體,邏輯清晰。

Request物件還有一個add_header方法,這樣也可以新增多個鍵值對的header

4、高階請求方式

設定代理

很多網站會檢測某一段時間某個IP的存取次數(通過流量統計,系統紀錄檔等),如果存取次數多的不像正常人,它會禁止這個IP的存取。ProxyHandler(設定代理的handler),可以變換自己的IP地址。

from urllib import request # 匯入request模組
 
url = 'http://httpbin.org' # url地址
handler = request.ProxyHandler({'http': '122.193.244.243:9999'}) # 使用request模組ProxyHandler類建立代理
#handler = request.ProxyHandler({"http":"賬號:密碼@'122.193.244.243:9999'"})
#付費代理模式 
opener = request.build_opener(handler) # 用handler建立opener
resp = opener.open(url) # 使用opener.open()傳送請求
print(resp.read()) # 列印返回結果

cookie

import urllib.request
import urllib.parse

url = 'https://weibo.cn/5273088553/info'
# 正常的方式進行存取
# headers = {
#     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36'
# }
#攜帶cookie進行存取
headers = {
    'GET https': '//weibo.cn/5273088553/info HTTP/1.1',
    'Host': ' weibo.cn',
    'Connection': ' keep-alive',
    'Upgrade-Insecure-Requests': ' 1',
    'User-Agent': ' Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36',
    'Accept': ' text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    # 'Referer: https':'//weibo.cn/',
    'Accept-Language': ' zh-CN,zh;q=0.9',
    'Cookie': ' _T_WM=c1913301844388de10cba9d0bb7bbf1e; SUB=_2A253Wy_dDeRhGeNM7FER-CbJzj-IHXVUp7GVrDV6PUJbkdANLXPdkW1NSesPJZ6v1GA5MyW2HEUb9ytQW3NYy19U; SUHB=0bt8SpepeGz439; SCF=Aua-HpSw5-z78-02NmUv8CTwXZCMN4XJ91qYSHkDXH4W9W0fCBpEI6Hy5E6vObeDqTXtfqobcD2D32r0O_5jSRk.; SSOLoginState=1516199821',
}
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
# 輸出所有
# print(response.read().decode('gbk'))
# 將內容寫入檔案中
with open('weibo.html', 'wb') as fp:
    fp.write(response.read())

四、urllib.error

可以捕獲三種異常:URLError,HTTPError(是URLError類的一個子類),ContentTooShortError

URLError只有一個reason屬性

HTTPError有三個屬性:code,reason,headers

import urllib.request
from urllib import error

try:
    response = urllib.request.urlopen('http://123.com')
except error.URLError as e:
    print(e.reason)
import urllib
from urllib import request
from urllib import error
#先捕捉http異常,再捕捉url異常
try:
    response = urllib.request.urlopen('http://123.com')
except error.HTTPError as e:
    print(e.reason, e.code, e.headers)
except error.URLError as e:
    print(e.reason)
else:
    print('RequestSucess!')

五、URL解析urllib.parse

urlparse函數

該函數是對傳入的url進行分割,分割成幾部分,並對每部分進行賦值

import urllib
from urllib import parse

result = urllib.parse.urlparse('http://www,baidu.com/index.html;user?id=5#comment')
print(type(result))
print(result)

結果方便的拆分了url

<class 'urllib.parse.ParseResult'>
ParseResult(scheme='http', netloc='www,baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')
Process finished with exit code 0

從輸出結果可以看出,這幾部分包括:協定型別、域名、路徑、引數、query、fragment

urlparse有幾個引數:url,scheme,allow_fragments

在使用urlparse時,可以通過引數scheme = 'http’的方式來指定預設的協定型別,如果url有協定型別,scheme引數就不會生效了

urlunparse函數

與urlparse函數作用相反,是對url進行拼接的 

urljoin函數

用來拼接url

urlencode函數

可以把一個字典轉化為get請求引數

六、urllib.robotparser

使用較少,可作為了解

總結

到此這篇關於Python爬蟲之urllib庫詳解的文章就介紹到這了,更多相關Python urllib庫內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com