1. 程式人生 > >python爬蟲學習筆記-urllib的使用

python爬蟲學習筆記-urllib的使用

學習爬蟲,最基本的操作即為模擬瀏覽器向伺服器發出請求,python內建了一個名為urllib的內建HTTP請求庫,有了它,我們只需要關心請求的連結是什麼,需要傳遞什麼引數,以及設定請求頭等其他資訊即可。這樣,我們就不用深入底層的連線具體是怎樣傳輸和通訊(當然,這是站在巨人的肩膀上)。urllib庫包含4個模組:
request:urllib的請求模組,模擬傳送請求;
error:異常處理模組,用於在請求錯誤時捕獲異常;
parse:提供了URL的一些處理方法,包括拆分,解析,合併等;
robotparser:用於識別網站的robot.txt檔案,用於判斷網站是否可爬;
1.爬蟲的第一步即為向伺服器傳送請求,request模組提供了皆不能的構造HTTP請求的方法-urlopen()。下面以抓取百度首頁為例:

import urllib.request
res=urllib.request.urlopen('https://www.baidu.com')
print(res.read().decode('utf-8'))

執行結果如下:

<html>

<head>

	<script>

		location.replace(location.href.replace("https://","http://"));

	</script>

</head>

<body>

	<noscript><meta http-equiv
="refresh" content="0;url=http://www.baidu.com/">
</noscript> </body> </html>

我們看到得到的是html程式碼,但是我們爬取的目的是得到想要的資訊,首先看一下返回的到底是什麼,利用type()方法:

print(type(res))#返回結果:<class 'http.client.HTTPResponse'>

可以發現這是一個HTTPResponse型別的物件它包含read(),getheaders()等方法,接下來可以得到返回值的其他資訊:

print(
res.status) print(res.getheaders()) print(res.getheader('Server'))

返回結果:

200
[('Accept-Ranges', 'bytes'), ('Cache-Control', 'no-cache'), ('Content-Length', '227'), ('Content-Type', 'text/html'), ('Date', 'Sat, 17 Nov 2018 02:06:19 GMT'), ('Etag', '"5becd3d4-e3"'), ('Last-Modified', 'Thu, 15 Nov 2018 02:03:00 GMT'), ('P3p', 'CP=" OTI DSP COR IVA OUR IND COM "'), ('Pragma', 'no-cache'), ('Server', 'BWS/1.1'), ('Set-Cookie', 'BD_NOT_HTTPS=1; path=/; Max-Age=300'), ('Set-Cookie', 'BIDUPSID=9176DB820AEC79EC1B99BDD045E9C693; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com'), ('Set-Cookie', 'PSTM=1542420379; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com'), ('Strict-Transport-Security', 'max-age=0'), ('X-Ua-Compatible', 'IE=Edge,chrome=1'), ('Connection', 'close')]
BWS/1.1

這裡分別獲得資訊為響應的狀態碼(200代表響應成功),響應的頭資訊以及伺服器型別。

2.request方法除url引數外還可傳遞data,timeout,context,cafile,capath引數,下面一一說明:
data引數:使用瀏覽器檢視網頁檢查元素(f12),找到network下的headers資訊,發現有“Request Method: GET”,這是說明網頁的請求方法,這種方法我們只需要傳遞url引數就可以獲得原始碼,但有些網頁資訊的請求需要向伺服器傳送一個字典引數作為請求引數,此時的Request Method會變成Post,urllib中要傳遞這個引數需要使用bytes()方法將字典引數轉換為位元組流編碼格式,即bytes型別,例項如下:

import urllib.parse
import urllib.request
data=bytes(urllib.parse.urlencode({'word','hello'}),encoding='utf-8')
res=urllib.request.urlopen('http:httpbin.org/post',data=data)
print(res.read())

3.timeout引數:
用於設定超時時間,單位為s,指如果請求超出了設定的這個時間還沒有獲得響應,就丟擲異常,如果不指定,則預設全域性時間,例項如下:

import urllib.request
import urllib.error
import socket
try:
    res=urllib.request.urlopen('http:httpbin.org/get',timeout=0.01)
except urllib.error.URLError as e:	
    print('Time Out')

0.01s不可能得到響應,所以輸出結果TimeOut。
3.其他引數:
context:指定設定SSL;
cafile,capath分別指定CA證書和路徑。
4.構造Request物件請求:
urlopen()方法的引數之前是url,在這裡也可以將Request物件作為獨立的引數匯入,可以方便的配置Request引數.程式碼如下:

res=urllib.request.Request('https://www.baidu.com')
rep=urllib.request.urlopen(res)
print(rep.read().decode('utf-8'))

Request引數包括url,data,headers(此引數用來偽裝瀏覽器,為字典引數,chrome為User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36),host名稱等;
5.高階用法
Handler:前面的方法可以構造請求,但涉及到例如cookies處理,代理設定等高階操作就需要使用Handler,我們可以把它理解為某種處理器,有專門處理登陸,有的處理cookies,有設定代理的。
urllib.request模組裡的BaseHandler類是所有Handler類的父類,我們使用繼承BaseHandler父類的Handler子類來完成我們所需要的操作,舉例如下:

HTTPDefaultErrorHandler:用於處理HTTP響應錯誤,丟擲HTTPError異常;
HTTPRedirectHandler:用於處理重新定向;
HTTPCookieProcessor:用於處理cookies;
ProxyHandler:用於設定代理;
與之相關的還有一個稱作Opener的東西,OPener可以使用open(),作用和urlopen相同,我們可以使用Hnadler構建Opener;
例項如下:

from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler,build_opener
from urllib.error import URLError
usename='usename'
password='password'
url='http:localhost:5000/'
p=HTTPPasswordMgrWithDefaultRealm()
#新增使用者名稱,密碼
p.add_password(None,url,usename,password)#建立一個處理驗證的Handler
#構建opener
auth_handler=HTTPBasicAuthHandler(p)
opener=build_opener(auth_handler)

如果請求的頁面需要輸入使用者名稱和密碼應該如何處理呢?這裡利用HTTPPasswordMgrWithDefaultRealm的例項化物件的add——password()方法傳遞使用者名稱和密碼,這樣就建立了一個處理驗證的Handler,接下來再使用build_opener()方法構建Opener,使用Opener來發送請求,最後使用OPener的open()方法開啟連結就完成驗證;
代理:
新增代理,首先引入ProxyHandler,它的引數為字典型別,鍵名為協議型別,鍵值為代理連線,可新增多個代理,例項程式碼如下:

proxy_handlers=ProxyHandler({'https':'https://127.0.0.1:9743'})#可新增多個代理
opener1=build_opener(proxy_handlers)
try:
	result=opener.open('https://www.baidu.com')
	print(result.read().decode('utf-8'))
except URLError as e:
	print(e.reason)

利用build——opener方法構建一個Opener,最後使用open()方法傳送請求即可。
6.連結的解析
urlparse-URL的識別與分段,例項如下:

from urllib.parse import urlparse
result=urlparse('https://baidu.com/index.html;user?id=5#comment')
print(type(result), result)

輸出結果為:<class ‘urllib.parse.ParseResult’>
ParseResult(scheme=‘https’, netloc=‘baidu.com’, path=’/index.html’, params=‘user’, query=‘id=5’, fragment=‘comment’)#返回結果將url拆分成6部分
與之對立的方法為urlunparse,實現URL的構造它接受的引數是一個可迭代物件,但長度必須為6。

7.分析Robots協議
Robots協議叫做爬蟲協議,用來告訴爬蟲和搜尋引擎頁面是否可以抓取,它通常是一個叫做robots.txt的文字檔案,儲存再網站的根目錄下。
舉例如下:
User-agent:*
Disallow:/
Allow:/public/
這是一個robots.txt檔案的內容,它實現了只允許爬取public目錄的功能。

以上就是對urllib的簡單總結,當然,鼓勵學會了使用requests庫之後也沒有人會用這個了,不過了解python內建的庫使用還是有價值的。