urllib模塊

1、urllib介紹

  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)持久化存儲框架

2、urllib使用示例

一、需求:爬取搜狗首頁的頁面數據(ssl證書報錯)

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("寫入數據成功")

注意:

(1)引入ssl解決urllib.urlopen報錯

  不添加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就能夠了。

(2)持久化存儲將爬取的html數據保存在sougou.html中

  

  瀏覽器打開顯示效果以下:

  

二、需求:爬取指定詞條所對應的頁面數據(涉及url編碼處理)

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)

注意:

(1)url編碼處理

  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

(2)打開renminbi.html文件顯示以下

  

三、反爬機制

  網站檢查請求的UA,若是發現UA是爬蟲程序,則拒絕提供網站數據。

  User-Agent參數,簡稱UA:當前請求所對應的請求載體的身份標識

  若是咱們經過瀏覽器發起的請求,則該請求的載體爲當前瀏覽器,則UA參數的值代表的是當前瀏覽器的身份標識表示的一串數據。若是咱們使用爬蟲程序發起的一個請求,則該請求的載體爲爬蟲程序,那麼該請求的UA爲爬蟲程序的身份標識表示的一串數據。有些網站會經過辨別請求的UA來判別該請求的載體是否爲爬蟲程序,若是爲爬蟲程序,則不會給該請求返回響應,那麼咱們的爬蟲程序則也沒法經過請求爬取到該網站中的數據值,這也是反爬蟲的一種初級技術手段。那麼爲了防止該問題的出現,則咱們能夠給爬蟲程序的UA進行假裝,假裝成某款瀏覽器的身份標識。

(1)Network(當前瀏覽器的抓包工具)

  該工具用於抓取當前瀏覽器發起的任意請求。

  查看某一個請求的user-agent請求頭信息所對應的鍵值數據(表明了當前請求載體的身份標識):

  

(2)Network抓包工具選項卡

  Headers選項卡包含了Response Headers(響應頭信息)、Request Headers(本次請求攜帶的請求頭信息)。  

  Response選項卡包含了服務器端響應給客戶端的一些頁面數據。

四、反反爬機制(ua身份假裝)

  將爬蟲程序請求的UA假裝爲任意一款瀏覽器的UA。

  上述案例中,咱們是經過request模塊中的urlopen發起的請求,該請求對象爲urllib中內置的默認請求對象,咱們沒法對其進行UA進行更改操做。urllib還爲咱們提供了一種自定義請求對象的方式,咱們能夠經過自定義請求對象的方式,給該請求對象中的UA進行假裝(更改)操做。  

(1)自定義請求對象實現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())

(2)封裝自定義的請求頭信息的字典

  將瀏覽器的UA數據獲取,封裝到一個字典中。該UA值能夠經過抓包工具或者瀏覽器自帶的開發者工具中獲取某請求,從中獲取UA的值。

  headers字典中能夠封裝任意的請求頭信息

3、urlib模塊發起的POST請求(帶參數)

一、需求:爬取百度翻譯的翻譯結果

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()

二、基於ajax的異步請求url獲取

  url對應的是針對詞條發起的ajax請求對應的url。

  XHR選項卡顯示的是基於AJAX的POST請求。找到這些請求中攜帶參數是「西瓜」的那一個。

  

  由此找到POST請求對應的url地址:

  

三、post請求攜帶的參數進行處理

# 流程:
# (1)將post請求參數封裝到字典
data = {
    'kw':'西瓜'
}

# (2)使用parse模塊中的urlencode(返回值類型爲str)進行編碼處理
data = urllib.parse.urlencode(data)

# (3)將步驟2的編碼結果轉換成byte類型
data = data.encode()

四、response.read()查看響應的數據

  

  將上述數據,json格式化顯示以下:

  

 4、urllib模塊的高級操做

  通常不會使用基於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操做

(1)cookie的相關概念及做用

  cookie概念:當用戶經過瀏覽器首次訪問一個域名時,訪問的web服務器會給客戶端發送數據,以保持web服務器與客戶端之間的狀態保持,這些數據就是cookie。

  cookie做用:咱們在瀏覽器中,常常涉及到數據的交換,好比你登陸郵箱,登陸一個頁面。咱們常常會在此時設置30天內記住我,或者自動登陸選項。那麼它們是怎麼記錄信息的呢,答案就是今天的主角cookie了,Cookie是由HTTP服務器設置的,保存在瀏覽器中,但HTTP協議是一種無狀態協議,在數據交換完畢後,服務器端和客戶端的連接就會關閉,每次交換數據都須要創建新的連接。就像咱們去超市買東西,沒有積分卡的狀況下,咱們買完東西以後,超市沒有咱們的任何消費信息,但咱們辦了積分卡以後,超市就有了咱們的消費信息。cookie就像是積分卡,能夠保存積分,商品就是咱們的信息,超市的系統就像服務器後臺,http協議就是交易的過程。 

(2)cookiejar對象及使用流程

  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

(3)使用cookiejar實現爬取人人網我的主頁頁面數據

  思路:

    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())
相關文章
相關標籤/搜索