爬虫学习笔记(四)—— urllib 与 urllib3
urllib 是一個內(nèi)置官方標準庫,無需下載;它是python2中的 urllib 與 urllib2 的合并,urllib3 庫是第三方標準庫, 解決了線程安全,增加了連接池等功能,urllib與urllib3 相互補充;
文章目錄
- 一、urllib庫
- 1.1、urllib.request模塊
- 1.1.1、發(fā)起網(wǎng)絡(luò)請求
- 1.1.2、添加請求頭
- 1.1.3、操作cookie
- 1.1.4、設(shè)置代理
- 1.2、urllib.parse模塊
- 1.2.1、單個參數(shù)轉(zhuǎn)碼
- 1.2.2、多個參數(shù)轉(zhuǎn)碼
- 1.3、urllib.error模塊
- 1.3.1、URLError與HTTPError
- 1.4、urllib.robotparse模塊
- 二、urllib3庫
- 2.1、特點
- 2.2、安裝
- 2.3、urllib3的使用
- 2.3.1、發(fā)起請求基本步驟
- 2.3.2、request方法
- 2.3.3、Proxies
- 2.3.4、Request data
- 2.3.4、response對象
- 三、小案例:下載百度圖片首頁圖片
- 3.1、使用urllib下載
- 3.2、使用urllib3下載
一、urllib庫
urllib庫主要包含4個模塊:
1.1、urllib.request模塊
request模塊主要負責(zé)構(gòu)造和發(fā)起網(wǎng)絡(luò)請求,并在其中添加Headers,Proxy等。
利用它可以模擬瀏覽器的請求發(fā)起過程。
1.發(fā)起網(wǎng)絡(luò)請求。
2.添加Headers。
3.操作cookie。
4.使用代理。
1.1.1、發(fā)起網(wǎng)絡(luò)請求
urlopen方法
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)功能:urlopen是一個發(fā)送簡單網(wǎng)絡(luò)請求的方法,然后返回結(jié)果。
參數(shù):
① url:必選;可以是一個字符串或一個 Request 對象。
② data:None–GET請求;有數(shù)據(jù)(字節(jié)類型/文件對象/可迭代對象)–POST請求(POST請求的話,data數(shù)據(jù)會放進form表單進行提交);
③ timeout:有默認設(shè)置;以秒為單位,例:設(shè)置timeout=0.1 超時時間為0.1秒(如果超出這個時間就報錯!)
返回值:urlib庫中的類或者方法,在發(fā)送網(wǎng)絡(luò)請求后,都會返回一個urllib.response的對象。它包含了請求回來的數(shù)據(jù)結(jié)果。它包含了一些屬性和方法,供我們處理返回的結(jié)果。
示例:
from urllib import request # test_url="http://httpbin.org/get" 注意使用get請求的話data要為空 test_url="http://httpbin.org/post" res=request.urlopen(test_url,data=b"spider") print(res.read())#字節(jié)串 所有的內(nèi)容 print(res.getcode())#獲取狀態(tài)碼 print(res.info())#獲取響應(yīng)頭信息 print(res.read())#字節(jié)串 再次讀取,為空Request對象
利用urlopen可以發(fā)起最基本的請求,但這幾個簡單的參數(shù)不足以構(gòu)建一個完整的請求(添加請求頭,添加不同請求方法),可以通過構(gòu)造來構(gòu)建更加完整的請求。
class Request:def __init__(self, url, data=None, headers={},origin_req_host=None, unverifiable=False,method=None):pass功能:Request是一個構(gòu)造完整網(wǎng)絡(luò)請求的對象,然后返回請求對象。
參數(shù):
① url:必選;是一個字符串
② data:字節(jié)類型
③ headers:請求頭信息
④ method:默認GET,可填寫 POST、PUT、DELETE等
返回值:一個請求對象
示例:
from urllib import request #Request對象 test_url="http://httpbin.org/get" headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"} req=request.Request(test_url,headers=headers) res=request.urlopen(req) print(res.read())#Request對象 data method 參數(shù)的使用 print("************************************") test_url="http://httpbin.org/put" req=request.Request(test_url,headers=headers,data=b"updatedata",method="PUT") res=request.urlopen(req) print(res.read())response對象
urlib 庫中的類或或者方法,在發(fā)送網(wǎng)絡(luò)請求后,都會返回一個urllib.response的對象。它包含了請求回來的數(shù)據(jù)結(jié)果。它包含了一些屬性和方法,供我們處理返回的結(jié)果。
- read() 獲取響應(yīng)返回的數(shù)據(jù),只能用一次
- readline() 讀取一行
- info() 獲取響應(yīng)頭信息
- geturl() 獲取訪問的url
- getcode() 返回狀態(tài)碼
1.1.2、添加請求頭
from urllib import request test_url="http://httpbin.org/get" headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"} req=request.Request(test_url,headers=headers) res=request.urlopen(req) print(res.read())1.1.3、操作cookie
from urllib import request from http import cookiejar #創(chuàng)建一個cookie對象 cookie=cookiejar.CookieJar() #創(chuàng)建一個cookie處理器 cookies=request.HTTPCookieProcessor(cookie) #以它為參數(shù)創(chuàng)建Openner對象 opener=request.build_opener(cookies) #使用這個openner來發(fā)送請求 res=opener.open("http://www.baidu.com")1.1.4、設(shè)置代理
from urllib import request url='http://httpbin.org/ip' #代理地址 proxy={'http':'180.76.111.69:3128'} #代理處理器 proxies=request.ProxyHandler(proxy) #創(chuàng)建openner對象 opener=request.build_opener(proxies)res=opener.open(url) print(res.read().decode())1.2、urllib.parse模塊
parse模塊是一個工具模塊,提供了需要對url處理的方法,用于解析url,url中只能包含ascii字符,在實際操作過程中,get請求通過url傳遞的參數(shù)中會有大量的特殊字符,例如漢字,那么就需要進行url編碼。
1.2.1、單個參數(shù)轉(zhuǎn)碼
- parse.quote() 漢字轉(zhuǎn)ascII碼
- parse.unquote() ascll轉(zhuǎn)中文
1.2.2、多個參數(shù)轉(zhuǎn)碼
在發(fā)送請求的時候,往往會需要傳遞很多的參數(shù),如果用字符串方法去拼接會比較麻煩,parse.urlencode()方法可以將字典轉(zhuǎn)換為url的請求參數(shù)并完成拼接。也可以通過parse.parse_qs()方法將它轉(zhuǎn)回字典。
- parse.urlencode()
- parse.parse_qs()
示例:
from urllib import parse,request #parse.urlencode()方法將字典轉(zhuǎn)換為url的請求參數(shù) params={"name":"電影","name2":"電視劇","name3":"動畫片"} asc_name=parse.urlencode(params)# 將要字典形式 轉(zhuǎn)成url請求參數(shù)形式 print(asc_name)#name=%E7%94%B5%E5%BD%B1&name2=%E7%94%B5%E8%A7%86%E5%89%A7&name3=%E5%8A%A8%E7%94%BB%E7%89%87 test_url="http://httpbin.org/get?{}".format(asc_name) print(test_url) res=request.urlopen(test_url) print(res.read())#parse_qs 轉(zhuǎn)換回原來的形式 new_params=parse.parse_qs(asc_name) print(new_params)#{'name': ['電影'], 'name2': ['電視劇'], 'name3': ['動畫片']}1.3、urllib.error模塊
1.3.1、URLError與HTTPError
error模塊主要負責(zé)處理異常,如果請求出現(xiàn)錯誤,我們可以用error模塊進行處理主要包含URLError和HTTPError。
- URLError:是error異常模塊的基類,由request模塊產(chǎn)生的異常都可以用這個類來處理。
- HTTPError:是URLError的子類,主要包含三個屬性:
- Code:請求的狀態(tài)碼
- reason:錯誤的原因
- headers:響應(yīng)的報頭
示例:
from urllib import error,request try:res=request.urlopen("https://jianshu.com")print(res.read()) except error.HTTPError as e:print('請求的狀態(tài)碼:',e.code)print('錯誤的原因:',e.reason)print('響應(yīng)的報頭:',e.headers)------------結(jié)果----------------- 請求的狀態(tài)碼: 403 錯誤的原因: Forbidden 響應(yīng)的報頭: Server: Tengine Date: Mon, 12 Jul 2021 04:40:02 GMT Content-Type: text/html Content-Length: 584 Connection: close Vary: Accept-Encoding Strict-Transport-Security: max-age=31536000; includeSubDomains; preload1.4、urllib.robotparse模塊
robotparse模塊主要負責(zé)處理爬蟲協(xié)議文件,robots.txt 的解析。(君子協(xié)定)爬蟲一般不會去遵守,所以基本不會使用這個模塊;
查看robots協(xié)議: 在網(wǎng)址之后添加robots.txt即可。
例如:百度的robots協(xié)議(http://www.baidu.com/robots.txt)
Robots協(xié)議(也稱為爬蟲協(xié)議、機器人協(xié)議等)的全稱是“網(wǎng)絡(luò)爬蟲排除標準”(Robots Exclusion Protocol),網(wǎng)站通過Robots協(xié)議告訴搜索引擎哪些頁面可以抓取,哪些頁面不能抓取。
robots.txt文件是一個文本文件,使用任何一個常見的文本編輯器,比如Windows系統(tǒng)自帶的Notepad,就可以創(chuàng)建和編輯它 。robots.txt是一個協(xié)議,而不是一個命令。robots.txt是搜索引擎中訪問網(wǎng)站的時候要查看的第一個文件。robots.txt文件告訴蜘蛛程序在服務(wù)器上什么文件是可以被查看的。
二、urllib3庫
2.1、特點
Urllib3是一個功能強大,條理清晰,用于HTTP客戶端的Python庫,許多Python的原生系統(tǒng)已經(jīng)開始使用urllib3。Urllib3提供了很多python標準庫里所沒有的重要特性:
1、 線程安全;2、 連接池;3、 客戶端SSL/TLS驗證;4、 文件分部編碼上傳;5、 協(xié)助處理重復(fù)請求和HTTP重定位;6、 支持壓縮編碼;7、 支持HTTP和SOCKS代理;8、 100%測試覆蓋率。
2.2、安裝
通過pip命令來安裝:
pip install urllib32.3、urllib3的使用
2.3.1、發(fā)起請求基本步驟
1、導(dǎo)入 urllib3庫
import utllib32、實例化一個PoolManager對象,這個對象處理了連接池與線程安全的所有細節(jié)
http=urllib3.PoolManager()3、用request方法發(fā)送一個請求
res=http.request("GET","http://www.baidu.com")2.3.2、request方法
request(self, method, url, fields=None, headers=None,**urlopen_kw)功能:發(fā)送完整的網(wǎng)絡(luò)請求
參數(shù):
① method:請求方法 GET ,POST,PUT,DELETE…
② url:字符串格式
③ fields:字典類型 GET請求時轉(zhuǎn)化為url參數(shù) POST請求時會轉(zhuǎn)化成form表單數(shù)據(jù)
④ headers:字典類型
返回值:response對象
示例:
import urllib3http = urllib3.PoolManager() url = 'http://httpbin.org/get' headers = {'header1':'python','header2':'java'} fields = {'name':'you','passwd':'12345'}res = http.request('GET',url,fields=fields,headers=headers)print('狀態(tài)碼:',res.status) print('響應(yīng)頭:',res.headers) print('data:',res.data)2.3.3、Proxies
可以利用ProxyManager進行http代理操作
import urllib3 proxy=urllib3.ProxyManager('http://180.76.111.69:31281') res=proxy.request('get','http://httpbin.org/ip') print(res.data)2.3.4、Request data
- get,head,delete請求,可以通過提供字典類型的參數(shù)fields來添加查詢參數(shù)
- 對于post和put請求,需要通過url編碼將參數(shù)編碼成正確格式然后拼接到url中
- JSON
在發(fā)起請求時,可以通過定義body 參數(shù)并定義headers的Content-Type參數(shù)來發(fā)送一個已經(jīng)過編譯的JSON數(shù)據(jù)
- Files
對于文件上傳,我們可以模仿瀏覽器表單的方式
- binary data
對于二進制的數(shù)據(jù)上傳,我們用指定body的方式,并設(shè)置Content-Type的請求頭
2.3.4、response對象
- http響應(yīng)對象提供status, data,和header等屬性
-
JSON content
返回的json格式數(shù)據(jù)可以通過json模塊,loads為字典數(shù)據(jù)類型 -
Binary content
響應(yīng)返回的數(shù)據(jù)都是字節(jié)類型,對于大量的數(shù)據(jù)我們通過stream來處理更好
也可以當(dāng)做一個文件對象來處理
import urllib3 http=urllib3.PoolManager() r=http.request('GET','http://httpbin.org/bytes/10241', preload_content=False) for line in r:print(line)三、小案例:下載百度圖片首頁圖片
(如果有想爬取多頁百度圖片的話,可以看我博客:使用 requests 爬取百度圖片,里面有詳細的過程)
3.1、使用urllib下載
from urllib import request import gzip from io import BytesIO import reimport osurl = 'https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=index&fr=&hs=0&xthttps=111110&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E7%8B%97&oq=%E7%8B%97&rsp=-1'headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Cache-Control': 'max-age=0', 'Connection': 'keep-alive', 'Cookie': 'BDqhfp=%E7%8B%97%26%260-10-1undefined%26%260%26%261; BIDUPSID=4B61D634D704A324E3C7E274BF11F280; PSTM=1624157516; BAIDUID=4B61D634D704A324C7EA5BA47BA5886E:FG=1; __yjs_duid=1_f7116f04cddf75093b9236654a2d70931624173362209; indexPageSugList=%5B%22%E7%8B%97%22%2C%22%E7%8C%AB%E5%92%AA%22%2C%22%E5%B0%8F%E9%80%8F%E6%98%8E%22%5D; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BAIDUID_BFESS=5DD3805F1A4CC3C9562CEAC3C22A1408:FG=1; __yjs_st=2_YTMzN2ZlYWQwNjg5NTFlNGY4NTMxMDBhOTc0ZDQxZjYwZWI0NzBiNjU1N2UyOGRiY2MzNWQ4OTM2YjU4MGU4MmNjYTNiZTk4ZDFkMWE1YmU2ODZhNGMwYzQ3OGE1YjcxZjNmZTEzYWY2ZjNiNGYxNjc0NWNlYjY5YmRhMTI3MmI2N2ZjOTkyYWUwYTZlZDUyMzY3NTc3YmU0MWUwNGM3MDk5NWE1ZTRhNzE4NjQwYWJlMjE3OTg5YzdkYjc0NmE4MjBhMjA2MDBkZmIwNDhjMjYzZjYxMTcyOGM2OTZmYjRlOGUwNTc1N2ZhYWI5YzEwZTVkODg0ZjI4OWM2ZjcyZF83XzM0OWQ2ZTJh; H_PS_PSSID=34268_34099_33969_34222_31660_34226_33848_34113_34073_34107_26350_22159; delPer=0; PSINO=6; BA_HECTOR=al21a125ag2l25851j1genv370q; BDRCVFR[X_XKQks0S63]=mk3SLVN4HKm; firstShowTip=1; cleanHistoryStatus=0; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; BDRCVFR[-pGxjrCMryR]=mk3SLVN4HKm; userFrom=null; ab_sr=1.0.1_NzczYjg1NGJiOWUwOGQwM2E4YTE0MDJkM2E0YjQ4M2E1ZDk0YWQ1MGUyMmNjZTg4NzhjZDNkZDI0YjcwMjU5N2MxYmQxNWIwZmRjMWEwZjVkNmZkYzkwYTNiYTE3NDUwYWFkZDkyZWM3Njg3ZjQ0OGQ5ZWU3YTkxNDk1M2FiZTAxZTY5NmY3ZjA1NDgxODE3ZWE4MWQxOWUwMmIwYmUxZA==', 'Host': 'image.baidu.com', 'Referer': 'https://image.baidu.com/', 'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"', 'sec-ch-ua-mobile': '?0', 'Sec-Fetch-Dest': 'document', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-User': '?1', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36' }req = request.Request(url,headers=headers) res = request.urlopen(req) # 做gzip的解壓 因為請求頭里有:'Accept-Encoding': 'gzip, deflate, br', #否則會出現(xiàn):UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0x8b in position 1: invalid start byte buff = BytesIO(res.read()) f = gzip.GzipFile(fileobj=buff) html= f.read().decode('utf-8')img_urls = re.findall('"thumbURL":"(.*?)"',html) for index,img_url in enumerate(img_urls):rq = request.Request(img_url)rs = request.urlopen(rq)if not os.path.exists('dog_image'): #判斷文件夾是否存在 不存在則創(chuàng)建img_file = os.mkdir("dog_image") #創(chuàng)建文件夾img_path = 'dog_image/'+'dog'+ str(index) +'.png'with open(img_path,'wb') as f:print(img_path)f.write(rs.read())結(jié)果:
3.2、使用urllib3下載
import reimport os import urllib3 #實例化一個PoolManager對象 http = urllib3.PoolManager() #目標url url = 'https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=index&fr=&hs=0&xthttps=111110&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E7%8B%97&oq=%E7%8B%97&rsp=-1' headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Cache-Control': 'max-age=0', 'Connection': 'keep-alive', 'Cookie': 'BDqhfp=%E7%8B%97%26%260-10-1undefined%26%260%26%261; BIDUPSID=4B61D634D704A324E3C7E274BF11F280; PSTM=1624157516; BAIDUID=4B61D634D704A324C7EA5BA47BA5886E:FG=1; __yjs_duid=1_f7116f04cddf75093b9236654a2d70931624173362209; indexPageSugList=%5B%22%E7%8B%97%22%2C%22%E7%8C%AB%E5%92%AA%22%2C%22%E5%B0%8F%E9%80%8F%E6%98%8E%22%5D; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BAIDUID_BFESS=5DD3805F1A4CC3C9562CEAC3C22A1408:FG=1; __yjs_st=2_YTMzN2ZlYWQwNjg5NTFlNGY4NTMxMDBhOTc0ZDQxZjYwZWI0NzBiNjU1N2UyOGRiY2MzNWQ4OTM2YjU4MGU4MmNjYTNiZTk4ZDFkMWE1YmU2ODZhNGMwYzQ3OGE1YjcxZjNmZTEzYWY2ZjNiNGYxNjc0NWNlYjY5YmRhMTI3MmI2N2ZjOTkyYWUwYTZlZDUyMzY3NTc3YmU0MWUwNGM3MDk5NWE1ZTRhNzE4NjQwYWJlMjE3OTg5YzdkYjc0NmE4MjBhMjA2MDBkZmIwNDhjMjYzZjYxMTcyOGM2OTZmYjRlOGUwNTc1N2ZhYWI5YzEwZTVkODg0ZjI4OWM2ZjcyZF83XzM0OWQ2ZTJh; H_PS_PSSID=34268_34099_33969_34222_31660_34226_33848_34113_34073_34107_26350_22159; delPer=0; PSINO=6; BA_HECTOR=al21a125ag2l25851j1genv370q; BDRCVFR[X_XKQks0S63]=mk3SLVN4HKm; firstShowTip=1; cleanHistoryStatus=0; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; BDRCVFR[-pGxjrCMryR]=mk3SLVN4HKm; userFrom=null; ab_sr=1.0.1_NzczYjg1NGJiOWUwOGQwM2E4YTE0MDJkM2E0YjQ4M2E1ZDk0YWQ1MGUyMmNjZTg4NzhjZDNkZDI0YjcwMjU5N2MxYmQxNWIwZmRjMWEwZjVkNmZkYzkwYTNiYTE3NDUwYWFkZDkyZWM3Njg3ZjQ0OGQ5ZWU3YTkxNDk1M2FiZTAxZTY5NmY3ZjA1NDgxODE3ZWE4MWQxOWUwMmIwYmUxZA==', 'Host': 'image.baidu.com', 'Referer': 'https://image.baidu.com/', 'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"', 'sec-ch-ua-mobile': '?0', 'Sec-Fetch-Dest': 'document', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-User': '?1', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36' } res = http.request('get',url,headers=headers) img_urls = re.findall('"thumbURL":"(.*?)"',res.data.decode()) for index,img_url in enumerate(img_urls):rs = http.request('get',img_url)if not os.path.exists('dog_image'): #判斷文件夾是否存在 不存在則創(chuàng)建img_file = os.mkdir("dog_image") #創(chuàng)建文件夾img_path = 'dog_image/'+'dog'+ str(index) +'.png'with open(img_path,'wb') as f:print(img_path)f.write(rs.data)結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的爬虫学习笔记(四)—— urllib 与 urllib3的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爬虫学习笔记(三)—— requests
- 下一篇: UnicodeDecodeError: