第二節--Urllib數據抓取

第二節–Urllib數據抓取

一.Urllib簡介

Urllib是python自帶的標準庫,無須安裝,直接引用便可。Urllib一般用於爬蟲開發,API(應用程序編程接口)數據獲取和測試。在python2和python3中,Urllib在不一樣版本中的語法有明顯的改變html

python2分爲UrllibUrllib2Urllib2能夠接收一個Request對象,並對此來設置一個URL的Headers,可是Urllib只接收一個URL,意味着不能假裝用戶代理字符串等。Urllib模塊能夠提供進行Urlencode的方法,該方法用於GET查詢字符串的生成,Urllib2不具備這樣的功能。這也是UrllibUrllib2常常在一塊兒使用的緣由python

在python3中,Urllib模塊是一堆能夠處理URL的組件集合,就是將UrllibUrllib2合併在一塊兒使用,而且命名爲Urllibweb

在python3中,Urllib是一個收集幾個模塊來使用URL的軟件包,大體具有如下功能:編程

  • urllib.request:用於打開和讀取URL
  • urllib.error:包含提出的例外urllib.request
  • urllib.parse:用於解析URL
  • urllib.robotparser:用於解析robots.txt文件

二.發送請求

urllib.request.urlopen的語法以下:瀏覽器

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

功能說明Urllib是用於訪問URL(請求連接)的惟一方法安全

[參數說明]服務器

  • url:須要訪問的網站的URL地址。url格式必須完整,如https://movie.douban.com/爲完整的url,若url爲movie.douban.com/,則程序運行時會提示沒法識別url的錯誤
  • data:默認值爲None,Urllib判斷參數data是否爲None從而區分請求方式。若參數data爲None,則表明請求方式爲Get;反之請求方式爲Post,發送Post請求。參數data以字典形式存儲數據,並將參數data由字典類型轉換成字節類型才能完成Post請求
  • timeout:超時設置,指定阻塞操做(請求時間)的超時(若是未指定,就使用全局默認超時設置)
  • cafile,capath,cadefault:使用參數指定一組HTTPS請求的可信CA證書。cafile應指向包含一組CA證書的單個文件;capath應指向證書文件的目錄;cadefault一般使用默認值便可
  • context:描述各類SSL選項的實例

當對網站發送請求時,網站會返回相應的響應內容。urlopen對象提供獲取網站響應內容的方法函數,分別介紹以下:cookie

  • read(),readline(),readlines(),fileno()和close():對HTTPResponse類型數據操做
  • info():返回HTTPMessage對象,表示遠程服務器返回的頭信息
  • getcode():返回HTTP狀態碼
  • geturl():返回請求的URL

下面的例子用於實現Urllib模塊對網站發送請求並將響應內容寫入文本文檔,代碼以下:svg

# 導入urllib
import urllib.request
# 打開url
response=urllib.request.urlopen("https://movie.douban.com/",None,2)
# 讀取返回的內容
html=response.read().decode("utf8")
# 寫入txt
f=open("html.txt","w",encoding="utf8")
f.write(html)
f.close()

首先導入urllib.request模塊,而後經過urlopen訪問一個URL,請求方式是GET,因此參數設置爲None;最後的參數用於設置超時時間,設置爲3秒,若是超過2秒,網站還沒返回響應數據,就會提示請求失敗的錯誤信息函數

當獲得服務器的響應後,經過response.read()獲取其響應內容。read()方法返回的是一個bytes類型的數據,須要經過decode()來轉換成str類型。最後將數據寫入文本文檔中,encoding用於設置文本文檔的編碼格式,數據編碼必須與文本文檔編碼一致,不然會出現亂碼

三.複雜的請求

urllib.request.Request的語法以下:

urllib.request.Request(url,data=None,headers={},method=None)

功能說明:聲明一個request對象,該對象可自定義header(請求頭)等請求信息

[參數解釋]:

  • url:完整的url格式,與urllib.request.urlopen的參數url一致
  • data:請求參數,與urllib.request.urlopen的參數data一致
  • headers:設置request請求頭信息
  • method:設定請求方式,主要是POST和GET方式

一個完整的HTTP請求必需要有請求頭信息。而urllib.request.Request的做用是設置HTTP的請求頭信息。使urllib.request.Request設置請求頭,代碼以下:

# 導入urllib
import urllib.request
url="https://movie.douban.com/"
# 自定義請求頭
headers={
    'User-Agent':'Mozilla/5.0(Windows NT 6.1;WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
    'Referer':'https://movie.douban.com/',
    'Connnection':'keep-alive'
}
# 設置request的請求頭
req=urllib.request.Request(url,headers=headers)
# 使用urlopen打開req
html=urllib.request.urlopen(req).read().decode('utf-8')
# 寫入文件
f=open('html.txt','w',encoding='utf8')
f.write(html)
f.close()

四.代理IP

代理IP的原理:以本機先訪問代理IP,再經過代理IP地址訪問互聯網,這樣網站(服務器)接收到的訪問IP就是代理IP地址

Urllib提供了urllib.request.ProxyHandler()方法可動態設置代理IP池,代理IP主要以字典格式寫入方法。完成代理IP設置後,將設置好的代理IP寫入urllib.request.bulid_opener()方法,生成對象opener,而後經過opener的open()方法向網站(服務器)發送請求

使用代理IP訪問網站,代碼以下:

import urllib.request
url='https://movie.douban.com/'
# 設置代理IP
proxy_handler=urllib.request.ProxyHandler(
    {
        'http':'218.56.132.157:8080',
        'https':'183.30.197.29:9797'
    }
)
# 必須使用bulid_opener()函數來建立帶有代理IP功能的opener對象
opener=urllib.request.build_opener(proxy_handler)
response=opener.open(url)
html=response.read().decode("utf-8")
f=open('html.txt','w',encoding='utf8')
f.write(html)
f.close()

注意,因爲使用代理IP,所以鏈接IP的時候有可能出現超時而致使報錯,遇到這種狀況只要更換其餘代理IP地址或者再次訪問便可。如下是常見的報錯信息:

  • ConnectionResetError:[WinError 10054]遠程主機強迫關閉了一個現有的鏈接
  • urllib.error.URLError:urlopen error Remote end closed connection without response(結束沒有響應的遠程鏈接)
  • urllib.error.URLError:urlopen error [WinError 10054]遠程主機強迫關閉了一個現有的鏈接
  • TimeoutError:[WinError 10060]因爲鏈接方在一段時間後沒有正確答覆或鏈接的主機沒有反應,所以鏈接嘗試失敗
  • urllib.error.URLError:urlopen error[WinError 10061]因爲目標計算機拒絕訪問,所以沒法鏈接

五.使用Cookies

Cookies主要用於獲取用戶登陸信息,好比經過提交數據實現用戶登陸以後,會產生帶有登陸狀態的Cookies,這時能夠將Cookies保存在本地文件中,下次程序運行的時候,能夠直接讀取Cookies文件來實現用戶登陸

Urllib提供HTTPCookieProcessor()Cookies操做。但Cookies的讀寫是由MozillaCookieJar()完成的。下面的例子實現Cookies寫入文件,代碼以下:

import urllib.request
from http import cookiejar
filename='cookie.txt'
# MozillaCookiesJar保存cookie
cookie=cookiejar.MozillaCookieJar(filename)
# HTTPCookieProcessor建立cookie處理器
handler=urllib.request.HTTPCookieProcessor(cookie)
# 建立自定義opener
opener=urllib.request.build_opener(handler)
# open方法打開網頁
response=opener.open('https://movie.douban.com')
# 保存cookie文件
cookie.save()

代碼中的cookiejar是自動處理HTTP Cookie的類,MozillaCookieJar()用於將Cookies內容寫入文件。程序運行時先建立MozillaCookieJar()對象,而後將對象直接傳入函數HTTPCookieProcessor(),生成opener對象;最後使用opener對象訪問URL,訪問過程所生成的Cookies就直接寫入已建立的文本文檔中

接着再看如何讀取Cookies,代碼以下:

import urllib.request
from http import cookiejar
filename='cookie.txt'
# 建立MozillaCookieJar對象
cookie=cookiejar.MozillaCookieJar()
# 讀取cookie內容到變量
cookie.load(filename)
# HTTPCookieProcessor建立cookie處理器
handler=urllib.request.HTTPCookieProcessor(cookie)
# 建立opener
opener=urllib.request.build_opener(handler)
# opener打開網頁
response=opener.open('https://movie.douban.com')
# 輸出結果
print(cookie)

讀取和寫入的方法很類似,主要區別在於:二者對MozillaCookieJar()對象的操做不一樣,致使實現功能也不一樣

注意,爲了方便測試,上述代碼中使用的cookie.save()cookie.load(filename)Cookies內容顯示在文本文檔中。在實際開發中,爲了提升安全性,能夠在保存和讀取Cookies時設置參數,使Cookies信息隱藏在文件中。方法以下

cookie.save(ignore_discard=True,ignore_expires=True)
cookie.load(filename,ignore_discard=True,ignore_expires=True)

六.證書驗證

當遇到一些特殊的網站時,在瀏覽器上會顯示鏈接不是私密鏈接而致使沒法瀏覽該網頁

補充

CA證書也叫SSL證書,是數字證書的一種,相似於駕駛證護照和營業執照的電子副本。由於配置在服務器上,也稱爲SSL服務器證書

SSL證書就是遵照SSL協議,由受信任的數字證書機構頒發CA,在驗證服務器身份後頒發,具備服務器身份驗證和數據傳輸加密功能

SSL證書在客戶端瀏覽器和Web服務器之間創建一條SSL安全通道(Secure Socket Layer,SSL),安全協議是由Netscape Communication公司設計開發的

遇到這類驗證證書的網站,最簡單而暴力的方法是直接關閉證書驗證,能夠在代碼中引入SSL模塊,設置關閉證書驗證便可。代碼以下:

import urllib.request
import ssl
# 關閉證書驗證
ssl._create_default_https_context=ssl._create_unverified_context
url='https://kyfw.12306.cn/otn/leftTicket/init'
response=urllib.request.urlopen(url)
# 輸出狀態碼
print(response.getcode())

七.數據處理

咱們知道urllib.request.urlopen()方法是不區分請求方式的,識別請求方式主要經過參數data是否爲None。若是向服務器發送Post請求,那麼參數data須要使用rullib.parse對參數內容進行處理

Urllib在請求訪問服務器的時候,若是發生數據傳遞,就須要對內容進行編碼處理,將包含str或bytes對象的兩個元素元組序列轉換爲百分比編碼的ASCII文本字符串。若是字符串要用做Post,那麼它應該被編碼爲字節,不然會致使TypeError錯誤

Urllib發送Post請求的方法以下:

import urllib.request
import urllib.parse
url='https://movie.douban.com'
data={
    'value':'true'
}
# 數據處理
data=urllib.parse.urlencode(data).encode('utf-8')
req=urllib.request.urlopen(url,data=data)

代碼中urllib.parse.urlencode(data)將數據轉換成字節的數據類型,而encode(utf-8)設置字節的編碼格式。urlencode()的做用只是對請求參數作數據格式轉換處理

除此以外,Urllib還提供quote()unquote()對URL編碼處理,使用方法以下

import urllib.parse
url='%2523%25E7%25BC%2596%25E7%25A8%258B%2523'
# 第一次編碼
first=urllib.parse.unquote(url)
print(first)
second=urllib.parse.unquote(first)
print(second)

八.本章小結

在python2和python3中,Urllib語法有明顯的改變。其經常使用的語法有如下幾種:

  • urllib.request.urlopen:urllib最基本的使用功能,用於訪問URL(請求連接)的惟一方法
  • urllib.request.Request:聲明request對象,該對象可自定義請求頭(header),請求方式等信息
  • urllib.request.ProxyHandler:動態設置代理IP池,可加載請求對象
  • urllib.request.HTTPCookieProcessor:設置Cookies對象,可加載請求對象
  • urllib.request.build_opener():建立請求對象,用於代理IP和Cookies對象加載
  • urllib.parse.urlencode(data).encode('utf-8'):請求數據格式轉換
  • urllib.parse.quote(url):URL編碼處理,主要對URL上的中文等特殊符號編碼處理
  • rullib.parse.unquote(url):URL解碼處理,將URL上的特殊符號還原
相關文章
相關標籤/搜索