最近入手學習Python3的網絡爬蟲開發方向,入手的教材是崔慶才的《python3網絡爬蟲開發實戰》,作為溫故所學的內容同時也是分享自己操作時的一些經驗與困惑,所以開了這個日記,也算是監督自己去學習。在這一系列的日記中我也會隨時加上一些書中沒有的內容作為對所學知識的一個補充。
(1)使用urllib庫
在python3中,把python2的urllib和urllib2兩個庫合並了,同時作為了其內置的HTTP請求庫,不需要額外安裝,這個庫包括四個模塊
request:最基本的HTTP請求模塊,可用來模擬發送請求。傳入URL以及額外的參數就可以實現想瀏覽器那樣訪問網站
error:異常處理模塊,請求錯誤時,我們可以捕獲這些異常,在進行重試以保證程序不意外終止
parse:一個工具模塊,提供URL處理方法,比如拆分,解析,合並
robotparser:主要用來識別網站的robots.txt文件,然后判斷哪些網站可以爬,用得少。
我們主要了解前三個模塊
首先是安裝,直接用命令安裝 pip install urllib3(這里如果不打3的話在cmd中會報錯)(ps:吐槽的是別少打一個l)
接下來我們用request發送請求,可以使用以下一些函數
1. urlopen():可請求抓取網頁內容
如下請求python官網的內容
1 import urllib.request
2 response = urllib.request.urlopen('https://www.python.org')
3 print(response.read().decode('utf-8'))
使用type()函數可以發現他的類型
print(type(response))
<class 'http.client.HTTPResponse'>
是一個HTTPResponse類型的對象,因此可對其進行一些方法使用,如read()可返回網頁內容,status可得到返回結果的狀態碼,如200代表請求成功,404代表網頁未找到
值得一提的是如果read 函數后未接decode('utf-8')那么現實的會是 b''因為網頁是二進制,需要將其轉為utf-8格式才行
>>> print(response.read())
b''
利用response下的方法來找到狀態碼和響應的頭信息,最后是獲取了其中Server值,nginx表示服務器是用Nginx搭建的
>>> print(response.status)
200
>>> print(response.getheaders())
[('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'SAMEORIGIN'), ('x-xss-protection', '1; mode=block'), ('X-Clacks-Overhead', 'GNU Terry Pratchett'), ('Via', '1.1 varnish'), ('Content-Length', '48812'), ('Accept-Ranges', 'bytes'), ('Date', 'Thu, 16 Aug 2018 02:31:55 GMT'), ('Via', '1.1 varnish'), ('Age', '595'), ('Connection', 'close'), ('X-Served-By', 'cache-iad2126-IAD, cache-hnd18734-HND'), ('X-Cache', 'HIT, HIT'), ('X-Cache-Hits', '59, 109'), ('X-Timer', 'S1534386716.758723,VS0,VE0'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]
>>> print(response.getheader('Server'))
nginx
還可以給urlopen傳遞一些參數,我們可以看看該函數的API(應用程序調用接口)
urllib.request.urlopen(url , data=None , [timeout,]* , cafile=None , capath=None , cadefault=False , context=None)
下面對這幾個參數進行調用:
這里要注意一個事,使用與urllib相關的庫時候,文件的命名千萬別用一些敏感詞,比如http.py,否則在導入包的時候,會一直報錯說module 'urllib' has no attribute 'request'
后面將名字改了后就沒有出現相關的報錯了 ,當然出現這種報錯還有一種原因,那就是導入的時候直接導入的是import urllib。但是在python3中,他不會把子模塊一塊導入,所以我們需要具體的導入比如import.urllib.request ,當然還有最后一種錯誤,那就是你拼錯了單詞,這就是一段辛酸淚了,好了,接下來我們開始進行各個參數的調試。
- data參數
該參數是可選的,如果要添加該參數,如果他是字節流編碼格式,即為bytes類型的話,則需要使用bytes()方法轉化另外如果傳遞了這個參數,他的請求方式就不再是GET, 而是POST。
import urllib.request
import urllib.parse
data = bytes(urllib.parse.urlencode({'word':'hello'}),encoding = 'utf8')
response = urllib.request.urlopen('http://httpbin.org/post',data = data)
print(response.read())
結果為
b'{ "args": {},
"data": "",
"files": {},
"form": {
"word": "hello"
},
"headers": {
"Accept-Encoding": "identity",
"Connection": "close",
"Content-Length": "10",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Python-urllib/3.6"
},
"json": null,
"origin": "182.110.15.26",
"url": "http://httpbin.org/post"
}
傳遞的參數出現在了form字段中,表明是模擬了表單的提交方式,以POST傳遞了數據
- timeout 參數
timeout參數用於設置超時時間,單位為秒,意思為如果超過了設置的這個時間,還沒有得到響應,就會拋出異常。如果不指定該參數,就會使用全局默認時間,
它支持HTTP,HTTPS,FTP請求。
import urllib.request
response = urllib.request.urlopen('http://httpbin.org/post',timeout=1)
print(response.read())
設置超時時間為1秒,結果一秒后,服務器無響應,於是拋出了URLError異常。該模塊屬於urllib.error模塊,錯誤原因為超時。
因此我們可以設置超時時間為來控制網絡長時間未反應,,也就是跳過他的抓取。可以使用try expcept語句實現。
其中,isinstance()函數的API為isinatance(object,classinfo),object為實例對象,classinfo為直接或間接類名,值得一提的是他與type的區別,type不會認為子類是父類的一種類型,但isintance會認為子類是父類的一種類型。
socket.timeout為超時類型。
- 其他參數:
還有其他一些參數如context參數,他必須是ssl.SSLConetext,用來指定SSL設置(SSL:(Secure Socket Layer,安全套接層協議),SSL協議位於TCP/IP協議與各種應用層協議之間,為數據通訊提供安全支持。SSL通過互相認證、使用數字簽名確保完整性、使用加密確保機密性,以實現客戶端和服務器之間安全通訊。該協議由兩層組成:SSL記錄協議和SSL握手協議。)
此外還有cafile參數指定CA證書,capath參數指定他的路徑,這個在請求HTTPS鏈接時會有效