使用urllib

urllib庫是Python內置的HTTP請求庫,包含4個模塊html

1)request:它是最基本的HTTP請求模板,能夠用來模擬發送請求瀏覽器

2)error:異常處理模塊,若是出現請求錯誤,咱們能夠捕獲這些異常,而後能夠進行重試或其餘操做來保證程序不會意外終止服務器

3)parse:一個工具模塊,提供許多URL處理方法,如拆分,解析合併等cookie

4)robotparser:主要用來識別網站的robots.txt文件,而後判斷哪些網站能夠爬,哪些網站不能夠爬網絡

一.發送請求

使用urllib的request模塊,能夠方便地實現請求的發送並獲得響應ide

1)urlopen()

urlopen()方法除了第一個參數能夠傳遞URL外,還能夠傳遞其餘內容,好比data,timeout等工具

A.data參數post

data參數是可選的。若是要添加該參數,而且若是它是字節流編碼格式的內容,即bytes類型,則須要經過bytes()方法轉化。若是傳遞了這個參數,則它的請求方式再也不是GET方式,而是POST方式fetch

B.timeout參數網站

timeout參數用於設置超時時間,單位爲秒,若是請求超出了設置時間,尚未獲得響應,就會拋出異常,若是不知道該參數,就會使用全局默認時間,它支持HTTP,HTTPS,FTP請求

C.其餘參數

context參數,它是必須是ssl.SSLContext類型用來指定SSL設置

此外,cafile和capath這兩個參數用來指定CA證書和他的路徑,這個在請求HTTPS連接時有用

 2)Request

urlopen()方法能夠實現最基本請求的發起,但其簡單的參數並不足以構建一個完整的請求,若是須要在請求中/加入Headers等信息,則須要利用強大的Request來構建

Request參數構造方法

1)第一個參數url用於請求URL,這是必傳參數,其餘都是可選參數
2)第二個參數data若是要傳,必須傳bytes(字節流)類型的,若是它是字典,能夠先用urllib。parse模塊裏的urlencode()編碼
3)第三個參數headers是一個字典,它就是請求頭,能夠在構造請求時經過headers參數直接構造,也能夠經過調用請求實例的add_header()方法調用
4)第四個參數origin_req_host指的是請求方的host名稱或者IP地址
5)第五個參數unverifiable表示這個請求是不是沒法驗證的,默認爲false,意思是用戶沒有足夠的權限來選擇接收這個請求的結果
6)第六個參數method是一個字符串,用來指示請求使用的方法,如GET,POST和PUT等
from urllib import request,parse
url="http://httpbin.org/post"
headers={
    'User-Agent':'Mozilla/4.0(compatible;MSIE 5.5;Windows NT)',
    'Host':'httpbin.org'
}
dict={
    'name':'Germey'
}
data=bytes(parse.urlencode(dict),encoding='utf-8')
req=request.Request(url=url,data=data,headers=headers,method='POST')
response=request.urlopen(req)
print(response.read().decode("utf-8"))

3)高級用法

對於一些高級操做,如Cookies處理,代理設置等,就要用到Handler,能夠把它理解爲各類處理器,有專門處理登陸驗證的,有處理Cookies的,有處理代理設置的

urllib.request模塊裏的BaseHandler類是全部其餘Handler的父類,它提供了最基本的方法

下面是各類Handler子類繼承這個BaseHandler類

1)HTTPDefaultErroeHandler: 用於處理HTTP響應錯誤,錯誤都會拋出HTTPError類型的異常
2)HTTPRedirectHandler: 用於處理重定向
3)HTTPCookieProcessor: 用於處理Cookies
4)ProxyHandler:用於設置代理,默認代理爲空
5)HTTPPasswordMgr:用於管理密碼,它維護了用戶名和密碼的表
6)HTTPBasicAuthHandler:用於管理認證,若是一個連接打開時須要認證,那麼能夠用它來解決認證問題

另一個比較重要的類是OpenerDirector,咱們能夠稱爲Opener,以前用過的urlopen()實際上就是urllib爲咱們提供的一個Opener

咱們須要實現更高級的功能,因此須要深刻一層進行配置,使用更底層的實例來完成操做,因此就用到Opener,Opener可使用open()方法,返回類型和urlopen()同樣

利用Hanler來構建Opener

用法:

A.驗證

有些網站須要輸入用戶名和密碼,驗證成功後才能查看頁面,要請求這樣的頁面,須要藉助HTTPBasicAuthHandler就能夠完成

from urllib.request import HTTPPasswordWithDefaultRealm,HTTPBasicAuthHandler,build_opener
from urllib.error import URLError
username='username'
password='password'
url='http://localhost:5000/'
p=HTTPPasswordWithDefaultRealm()
p.add_passsword(None,url,username,password)
auth_handler=HTTPBasicAuthHandler(p)
opener=built_opener(auth_handler)
try:
result=opener.open(url)
html=result.read().decode('utf-8')
print(html)
except URLError as e:
print(e.reason)

B.代理

在作爬蟲時,若是要添加代理,能夠這樣作

from urllib.error import URLError
from urllib.request import ProxyHandler,build_opener
proxy_handler =ProxyHandler({
'http':'http://127.0.0.1:9743',
'https':'https://127.0.0.1:9743'
})
opener=build_opener(proxy_handler)
try:
response=opener.open('https://www.baidu.com')
print(resposne.read().decode("urtf-8"))
except URLError as e:
print(e.reason)

使用ProxyHandler,其參數是一個字典,鍵名是協議類型(如HTTP或HTTTPS),鍵值是代理連接,能夠添加多個代理

C.Cookies

Cookies的處理就須要相關的Handler

from urllib.request import HTTPCookieProcessor,build_opener
import http.cookiejar
cookie=http.cookiejar.CookieJar()
handler=HTTPCookieProcessor(cookie)
opener=build_opener(handler)
response=opener.open("https://www.baidu.com")
for i in cookie:
    print(i.name+'='+i.value)

這樣能夠看到每條Cookie的名稱和值

將cookie以文本形式保存代碼以下

import http.cookiejar,urllib.request
filename='Cookies.text'
cookie=http.cookiejar.MozillaCookieJar(filename)
handler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handler)
response=opener.open("https://www.baidu.com")
cookie.save(ignore_discard=True,ignore_expires=True)

MozillaCookieJar才生成文件時會用到,時CookieJar的子類。能夠用來處理Cookies和文件相關的事件,好比讀取和保存Cookies,能夠將Cookies保存成Mozilla型瀏覽器的Cookies格式

LWPCookieJar也能夠讀取和保存Cookies,可是保存的格式和MozillaCookieJar的不同,它會保存成libwww-perl(LWP)格式的Cookies文件

從文件中讀取:

import http.cookiejar,urllib.request
cookie=http.cookiejar.MozillaCookieJar()
cookie.load('Cookies.txt',ignore_discard=True,ignore_expires=True)
handler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handler)
response=opener.open("https://www.baidu.com")
print(response.read().decode('utf-8'))

 

二.處理異常

urllib的error模塊定義了由request模塊產生的異常。若是出現了問題,request模塊便會拋出error中定義的異常

A.URLError

URLError類來自urllib庫的error模塊,它繼承自OSError類,是error異常模塊的基類,有request模塊生的異常均可以經過這個類來處理

from urllib import request,error
try:
    response=request.urlopen("https://www.dengwenxiong.com")
except error.URLError as e:
    print(e.reason)

B.HTTPError

它是URLError的子類,專門用來處理HTTP請求錯誤,好比認證請求失敗,它有三個屬性

1)code:返回HTTP狀態碼,好比404表示網頁不存在,500表示服務器內部錯誤
2)reason:同父類同樣,用於返回錯誤的緣由
3)headers:返回請求頭
from urllib import request,error
try:
    response=request.urlopen("https://cuiqingcai.com/index.htm")
except error.HTTPError as e:
    print(e.code,e.reason,e.headers)

 

三.解析連接

urllib庫還提供了parse模塊,它定義了處理URL的標準接口,例如實現URL各部分的抽取,合併以及連接轉換

1)urlparse

該方法能夠實現URL的識別和分段

from urllib.parse import urlparse
result=urlparse("https://www.dengwenxiong/index.html;user?id=5#comment")
print(result)
ParseResult(scheme='https', netloc='www.dengwenxiong', path='/index.html', params='user', query='id=5', fragment='comment')

其將url分爲6部分scheme表示協議,netloc表示域名,path表示訪問路徑,params表示參數,query表示查詢條件,fragment表示錨點,用於直接定位頁面內部的下拉位置

urlparse()有三個參數:urlstring,scheme和allow_fragments

uslstring是必填項,即待解析的URL

scheme:它是默認的協議,假如連接沒有協議,會將這個做爲默認的協議

allow_fragments:便是否忽略fragment,若是它被設置爲false,fragment部分被忽略,它會被解析成path,parameters或者query的一部分,而fragment部分爲空

2)urlunparse

它接受的參數是一個可迭代對象,可是它的長度必須是6,不然會拋出參數數量不足或者過多的問題

from urllib.parse import urlunparse
data=('https','www.baidu.com','index.html','user','a=6','comment')
print(urlunparse(data))

3)urlsplit()

這個方法和urlparse()方法很是類似,只不過它不在單獨解析params這一部分,只返回5個結果,params會合併到path中,能夠用屬性獲取值,也能夠用索引來獲取

4)urlunsplit()

與urlunparse()相似,也是將連接各個部分組合成完整連接的方法,傳入的參數也是一個可迭代對象,惟一的區別是長度必須爲5

5)urljoin()

生成連接除了上面兩個方法,還有就是urljoin()方法,能夠提供一個base_url(基礎連接)做爲第一個參數,將新的連接做爲第二個參數,該方法會分析base_url的scheme,netloc和path這三個內容並對新連接缺失的部分進行補充

base_url提供三項內容scheme,netloc和path,若是這3項在新的連接裏不存在,就予以補充,若是新的連接存在,就使用新的連接的部分,而base_url中的params,query和fragment是不起做用的

from urllib.parse import urljoin
print(urljoin('http://www.baidu.com','FAQ.html'))

6)urlencode()

它在構造get請求參數的時候很是有用

from urllib.parse import urlencode
params={
    'name':'dwx',
    'age':22
}
base_url='http://www.baidu.com?'
url=base_url+urlencode(params)
print(url)

 7)parse_qs()

有了序列化就要有反序列化,若是有一串GET請求參數,利用parse_qs()方法能將其轉回字典

from urllib.parse import parse_qs
query="name=dengwenxiong&age=22"
print(parse_qs(query))

8)parse_qsl()

它用於將參數轉化爲元組組成的列表

9)quote()

該方法能夠將內容轉化爲URL格式

from urllib.parse import quote
key="鄧文雄"
url="http://www.baidu.com/s?wd="+quote(key)
print(url)

10)unquote()

能夠對URL進行解碼

from urllib.parse import unquote
key="%E9%82%93%E6%96%87%E9%9B%84"
print(unquote(key))

 

三.分析Robots協議

利用urllib的robotparser模塊,咱們能夠實現網站Robots協議的分析

1)Robots協議

Robots協議也稱爲爬蟲協議,機器人協議,全名爲網絡爬蟲排除標準(Robots Exclusion Protocol),用來告訴爬蟲和搜索引擎哪些頁面能夠抓取,哪些頁面不可抓取。它一般是一個叫做robots.txt的文本文件,通常放在網站的根目錄下。

當搜索爬蟲訪問一個站點時,它會首先檢查這。個站點根目錄下是否存在robots.txt文件,若是存在,搜索爬蟲會根據其中定義的爬取範圍來爬取,若是沒有找到這個文件,搜索爬蟲便會訪問因此可直接訪問的頁面

下面是一個robot.txt的樣例

A.對全部搜索爬蟲只容許爬取public目錄

User-agent:*
Disallow:/
Allow:/public/

User-agent描述了搜索爬蟲的名稱,這裏設置爲*則表明該協議對任何爬取爬蟲有效

Disallow指定了不容許抓取的目錄,設置爲/則表明不容許抓取全部頁面

Allow通常和Disallow一塊兒使用,通常不會單獨使用,用來排除某些限制,這裏設置爲/public/則表示全部頁面不容許抓取,但能夠抓取public目錄

B.禁止全部爬蟲訪問任何目錄

User-agent:*
Disallow:/

C.容許全部爬蟲訪問任何目錄

User-agent:*
Disallow:

D.禁止全部爬蟲訪問網站某些目錄

User-agent:*
Disallow:/private/
Disallow:/tmp/

E.只容許某一個爬蟲訪問

User-agent:WebCrawler
Disallow:
User-agent:*
Disallow:/

2)爬蟲名稱

一些常見搜索爬蟲的名稱即其對應的網站

爬蟲名稱 名稱 網站
BaiduSpider 百度 www.baidu.com
Googlebor 谷歌 www.google.com
360Spider 360搜索 www.so.com
YodaoBor 有道 www.youdao.com
ia_archiver Alexa www.alexa.cn
Scooter altavista www.altavista.com

3)robotparser

能夠用robotparser模塊來解析robots.txt;該模塊提供了一個類RobotFileParser,它能夠根據某網站的robots.txt文件來判斷一個爬取爬蟲是否有權限來爬取這個網頁;這個類用起來很是簡單,只須要在構造方法裏傳入robots.txt的連接便可,其聲明以下:

urllib.robotparser.RobotFileParser(url=' ')

也能夠在聲明時不傳入,默認爲空,使用set_url()方法設置也行;

這個類經常使用的幾個方法:

1)set_url():用來設置robots.txt文件的連接。若是在建立RobotFileParser對象時傳入了連接,那麼就不須要再使用這個方法設置了
2)read():讀取robots.txt文件並進行分析,這個方法執行一個讀取和分析操做,若是不調用這個方法,接下來的判斷都會爲false,因此必定要調用這個方法,這個方法不返回任何內容,可是執行了讀取操做
3)parse():用來解析robots.txt文件,傳入的參數是robots.txt某些行的內容,它會按照robots.txt的語法規則來分析這些內容
4)can_fetch():該方法傳入兩個參數,第一個是User-agent,第二個是要抓取的URL。返回的內容是該搜索引擎是否能夠抓取這個URL,返回的結果是True或False
5)mtime():返回的是上次抓取和分析robots.txt的時間,這對於長時間分析和抓取的搜索爬蟲是頗有必要的,你可能須要按期檢查來抓取最新的robots.txt
6)modified():它對長時間分析和抓取的搜索爬蟲頗有幫助,將當前時間設置爲上次抓取和分析robots.txt的時間
from urllib.robotparser import RobotFileParser
rp=RobotFileParser()
rp.set_url('http://www.jianshu.com/robots.txt')
rp.read()#也可用parse()讀取和分析rp.parse(urlopen('http://www.jianshu.com/robots.txt').read().decode('utf-8').split('\n'))
print(rp.can_fetch('*','http://www.jianshu.com/'))
相關文章
相關標籤/搜索