urllib是python中自帶的一個基於爬蟲的模塊,html
做用:urllib 模塊是一個高級的 web 交流庫,其核心功能就是模仿web瀏覽器等客戶端,去請求相應的資源,並返回一個類文件對象。可使用代碼模擬瀏覽器發起請求。python
詳見官網資料:2.7.5:urllib
— Open arbitrary resources by URLweb
3.7.1:urllib
— URL handling modulesajax
urllib模塊包括如下子模塊:
(1)urllib.request 請求模塊
(2)urllib.error 異常處理模塊
(3)urllib.parse url解析模塊
(4)urllib.robotparser robots.txt解析模塊json
其中最經常使用的兩個子模塊是:request、parse。瀏覽器
二、使用流程
(1)指定url
服務器
(2)發起請求:針對指定的url發起一個請求
cookie
(3)獲取頁面數據:獲取服務器響應回來的頁面數據
負載均衡
(4)持久化存儲
框架
import urllib.request import ssl import os ssl._create_default_https_context = ssl._create_unverified_context # 1.指定url url = "https://www.sogou.com/" # 2.發起請求:urlopen()能夠根據指定的url發起請求,且發回一個響應對象 # 出現報錯:urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)> response = urllib.request.urlopen(url=url) # 3.獲取頁面數據:read函數返回的就是響應對象中存儲的數據 page_text = response.read() # 4.持久化存儲 # print(page_text) file_path = os.path.join('first_Jupyter', "sougou.html") with open(file_path, "wb") as fp: fp.write(page_text) print("寫入數據成功")
注意:
不添加ssl執行會報錯,SSL: CERTIFICATE_VERIFY_FAILED。Python 升級到 2.7.9 以後引入了一個新特性,當使用urllib.urlopen打開一個 https 連接時,會驗證一次 SSL 證書。而當目標網站使用的是自簽名的證書時就會拋出此異常。
解決方案有以下兩種:
# 1)使用ssl建立未經驗證的上下文,在urlopen中傳入上下文參數 import ssl context = ssl._create_unverified_context() webPage = urllib.request.urlopen(req,context=context) # 2)全局取消證書驗證 import ssl ssl._create_default_https_context = ssl._create_unverified_context
另外,若是用的是requests模塊的get方法,裏面有一個verify參數,將其設成False就能夠了。
瀏覽器打開顯示效果以下:
import urllib.request import urllib.parse import ssl ssl._create_default_https_context = ssl._create_unverified_context # 指定url # url = "https://www.sogou.com/web?query=人民幣" url = 'https://www.sogou.com/web?query=' # url特性:url不能夠存在非ASCII編碼的字符數據 word = urllib.parse.quote("人民幣") # 用quote對非ascii的字符進行轉碼 url += word # 轉碼結果再拼接出有效的url # 發請求 response = urllib.request.urlopen(url=url) # 獲取頁面數據 page_text = response.read() with open('renminbi.html','wb') as fp: fp.write(page_text)
注意:
url特性:url不能夠存在非ASCII編碼的字符數據。若是存在則該url無效。若是對其發起請求,則會報以下錯誤:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 15-17: ordinal not in range
因此必須對url中的非ascii的數據進行ascii的編碼,則該url方可被髮起請求。
解決方法以下所示:
# 指定url # url = "https://www.sogou.com/web?query=人民幣" url = 'https://www.sogou.com/web?query=' # url特性:url不能夠存在非ASCII編碼的字符數據 word = urllib.parse.quote("人民幣") # 用quote對非ascii的字符進行轉碼 url += word # 轉碼結果再拼接出有效的url
網站檢查請求的UA,若是發現UA是爬蟲程序,則拒絕提供網站數據。
User-Agent參數,簡稱UA:當前請求所對應的請求載體的身份標識。
若是咱們經過瀏覽器發起的請求,則該請求的載體爲當前瀏覽器,則UA參數的值代表的是當前瀏覽器的身份標識表示的一串數據。若是咱們使用爬蟲程序發起的一個請求,則該請求的載體爲爬蟲程序,那麼該請求的UA爲爬蟲程序的身份標識表示的一串數據。有些網站會經過辨別請求的UA來判別該請求的載體是否爲爬蟲程序,若是爲爬蟲程序,則不會給該請求返回響應,那麼咱們的爬蟲程序則也沒法經過請求爬取到該網站中的數據值,這也是反爬蟲的一種初級技術手段。那麼爲了防止該問題的出現,則咱們能夠給爬蟲程序的UA進行假裝,假裝成某款瀏覽器的身份標識。
該工具用於抓取當前瀏覽器發起的任意請求。
查看某一個請求的user-agent請求頭信息所對應的鍵值數據(表明了當前請求載體的身份標識):
Headers選項卡包含了Response Headers(響應頭信息)、Request Headers(本次請求攜帶的請求頭信息)。
Response選項卡包含了服務器端響應給客戶端的一些頁面數據。
將爬蟲程序請求的UA假裝爲任意一款瀏覽器的UA。
上述案例中,咱們是經過request模塊中的urlopen發起的請求,該請求對象爲urllib中內置的默認請求對象,咱們沒法對其進行UA進行更改操做。urllib還爲咱們提供了一種自定義請求對象的方式,咱們能夠經過自定義請求對象的方式,給該請求對象中的UA進行假裝(更改)操做。
import urllib.request url = 'https://www.baidu.com/' # UA假裝 # 1.自制定一個請求對象 headers = { # 自定製請求頭:存儲任意的請求頭信息 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36' } # 該請求對象的UA進行了成功的假裝 # Request()會返回一個自制定的請求對象,url指定url,headers表示自定製請求頭信息 request = urllib.request.Request(url=url,headers=headers) # 2.針對自制定的請求對象發起請求 response = urllib.request.urlopen(request) print(response.read())
將瀏覽器的UA數據獲取,封裝到一個字典中。該UA值能夠經過抓包工具或者瀏覽器自帶的開發者工具中獲取某請求,從中獲取UA的值。
在headers字典中能夠封裝任意的請求頭信息。
import urllib.request import urllib.parse # 1.指定url url = 'https://fanyi.baidu.com/sug' # post請求攜帶的參數進行處理 流程: # (1)將post請求參數封裝到字典 data = { 'kw':'西瓜' } # (2)使用parse模塊中的urlencode(返回值類型爲str)進行編碼處理 data = urllib.parse.urlencode(data) # (3)將步驟2的編碼結果轉換成byte類型 data = data.encode() # 2.發起post請求 # urlopen函數data參數:表示的就是通過處理以後的post請求攜帶的參數 response = urllib.request.urlopen(url=url,data=data) # 響應對象 response.read()
url對應的是針對詞條發起的ajax請求對應的url。
XHR選項卡顯示的是基於AJAX的POST請求。找到這些請求中攜帶參數是「西瓜」的那一個。
由此找到POST請求對應的url地址:
# 流程: # (1)將post請求參數封裝到字典 data = { 'kw':'西瓜' } # (2)使用parse模塊中的urlencode(返回值類型爲str)進行編碼處理 data = urllib.parse.urlencode(data) # (3)將步驟2的編碼結果轉換成byte類型 data = data.encode()
將上述數據,json格式化顯示以下:
通常不會使用基於urllib的代理和cookie操做,使用流程比較繁瑣,效率也比較低。通常仍是使用requests模塊和scrapy框架。
(1)什麼是代理?
代理就是第三方代替本體處理相關事務。例如:生活中的代理:代購,中介,微商......
(2)爬蟲中爲何須要使用代理?
一些網站會有相應的反爬蟲措施,例如不少網站會檢測某一段時間某個IP的訪問次數,若是訪問頻率太快以致於看起來不像正常訪客,它可能就會會禁止這個IP的訪問。因此咱們須要設置一些代理IP,每隔一段時間換一個代理IP,就算IP被禁止,依然能夠換個IP繼續爬取。
(3)代理的分類
正向代理:代理客戶端獲取數據。正向代理是爲了保護客戶端防止被追求責任。
反向代理:代理服務器提供數據。反向代理是爲了保護服務器或負責負載均衡。
import urllib.request import urllib.parse # 1.建立處理器對象,在其內部封裝代理ip和端口 handler=urllib.request.ProxyHandler(proxies={'http':'95.172.58.224:52608'}) # 2.建立opener對象,而後使用該對象發起一個請求 opener=urllib.request.build_opener(handler) url='http://www.baidu.com/s?ie=UTF-8&wd=ip' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } # 自制定請求對象 request = urllib.request.Request(url, headers=headers) # 3.使用opener對象發起請求,該請求對應的ip即爲咱們設置的代理ip response = opener.open(request) with open('./daili.html','wb') as fp: fp.write(response.read())
cookie概念:當用戶經過瀏覽器首次訪問一個域名時,訪問的web服務器會給客戶端發送數據,以保持web服務器與客戶端之間的狀態保持,這些數據就是cookie。
cookie做用:咱們在瀏覽器中,常常涉及到數據的交換,好比你登陸郵箱,登陸一個頁面。咱們常常會在此時設置30天內記住我,或者自動登陸選項。那麼它們是怎麼記錄信息的呢,答案就是今天的主角cookie了,Cookie是由HTTP服務器設置的,保存在瀏覽器中,但HTTP協議是一種無狀態協議,在數據交換完畢後,服務器端和客戶端的連接就會關閉,每次交換數據都須要創建新的連接。就像咱們去超市買東西,沒有積分卡的狀況下,咱們買完東西以後,超市沒有咱們的任何消費信息,但咱們辦了積分卡以後,超市就有了咱們的消費信息。cookie就像是積分卡,能夠保存積分,商品就是咱們的信息,超市的系統就像服務器後臺,http協議就是交易的過程。
cookiejar對象:
做用:自動保存請求中的cookie數據信息
注意:必須和handler和opener一塊兒使用
cookiejar使用流程:
建立一個cookiejar對象
import http.cookiejar cj = http.cookiejar.CookieJar()
經過cookiejar建立一個handler
handler = urllib.request.HTTPCookieProcessor(cj)
根據handler建立一個opener
opener = urllib.request.build_opener(handler)
使用opener.open方法去發送請求,且將響應中的cookie存儲到openner對象中,後續的請求若是使用openner發起,則請求中就會攜帶了cookie
思路:
1.咱們須要使用爬蟲程序對人人網的登陸時的請求進行一次抓取,獲取請求中的cookie數據
2.在使用我的信息頁的url進行請求時,該請求須要攜帶 1 中的cookie,只有攜帶了cookie後,服務器纔可識別此次請求的用戶信息,方可響應回指定的用戶信息頁數據
#使用cookiejar實現人人網的登錄 import urllib.request import urllib.parse import http.cookiejar cj = http.cookiejar.CookieJar() #請求中的cookie會自動存儲到cj對象中 #建立處理器對象(攜帶cookiejar對象的) handler=urllib.request.HTTPCookieProcessor(cj) #建立opener對象 (攜帶cookiejar對象) opener=urllib.request.build_opener(handler) #要讓cookiejar獲取請求中的cookie數據值 url='http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=201873958471' #自定義一個請求對象,讓該對象做爲opener的open函數中的參數 data={ "email":"www.zhangbowudi@qq.com", "icode":"", "origURL":"http://www.renren.com/home", "domain":"renren.com", "key_id":"1", "captcha_type":"web_login", "password":"40dc65b82edd06d064b54a0fc6d202d8a58c4cb3d2942062f0f7dd128511fb9b", "rkey":"41b44b0d062d3ca23119bc8b58983104", 'f':"https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DpPKf2680yRLbbZMVdntJpyPGwrSk2BtpKlEaAuKFTsW%26wd%3D%26eqid%3Deee20f380002988c000000025b7cbb80" } data=urllib.parse.urlencode(data).encode() request=urllib.request.Request(url,data=data) opener.open(request) #獲取當前用戶的二級子頁面 s_url='http://www.renren.com/289676607/profile' #該次請求中就攜帶了cookie resonse=opener.open(s_url) with open('./renren.html','wb') as fp: fp.write(resonse.read())