一起學爬蟲——urllib庫常用方法用法總結
1、讀取cookies
import http.cookiejar as cj,urllib.request as request cookie = cj.CookieJar() handler = request.HTTPCookieProcessor(cookie) opener = request.build_opener(handler) response = opener.open('http://www.bigdata17.com') for item in cookie: print(item.name + "=" + item.value)
2、將cookies儲存在檔案中
filename = 'baidu_cookies.txt' cookies = cj.MozillaCookieJar(filename) handler = request.HTTPCookieProcessor(cookies) opener = request.build_opener(handler) response = opener.open('http://www.baidu.com') cookies.save(ignore_discard=True,ignore_expires=True)
3、處理異常
URLError和HTTPError類,兩個類是父子關係,HTTPError會返回錯誤程式碼,兩個類都可以處理request模組產生的異常,這兩個都有一個reason屬性,用於記錄出現異常的原因
URLError處理異常:
from urllib import request,error try: response = request.urlopen('http://www.bigdata17.com/index.htm') except error.URLError as e: print(e.reason)
HTTPError處理異常:
這個類是專門處理http請求的異常,http請求會返回一個請求程式碼,因此HTTPError會有一個code屬性。另外HTTP請求會有包含請求頭資訊,所以HTTPError還包含一個headers屬性。HTTPError繼承自URLError類,因此也包含有reason屬性。
程式碼:
try: response = request.urlopen('http://www.bigdata17.com/index.htm') except error.HTTPError as e: print(e.reason) print(e.code) print(e.headers)
4、解析連結
urllib庫中的parse類提供了很多用於解析連結的方法。
urlparse()方法是專門用於解析連結的,我們先看這個方法的返回值:
from urllib.parse import urlparse result = urlparse('http://www.bigdata17.com') print(result)
上面的程式碼返回的結果:
ParseResult(scheme='http', netloc='www.bigdata17.com', path='', params='', query='', fragment='')
可見urlparse()方法返回的是ParseResult類,這個了有6個屬性,分別是scheme、netloc、path、params、query和fragment。其中scheme代表的是協議,有http,https,ftp等協議型別。netloc是網站域名,path是要訪問的網頁名稱。params是代表引數。query查詢引數,fragment是錨點。
urlparse()方法是如何將一個連結對映到上面的6個引數中呢?
繼續看下一段程式碼:
from urllib.parse import urlparse result = urlparse('http://www.bigdata17.com/22.html;user=bigdata17?id=10#content') print(result)
執行的結果如下:
ParseResult(scheme='http', netloc='www.bigdata17.com', path='/22.html', params='user=bigdata17', query='id=10', fragment='content')
可見從連結開始為://止,是scheme。從://開始到一個/位置,是netloc域名。從/開始到;分號為止是path,訪問頁面的路徑。;開始到?為止是params引數。從?問號開始到#井號結束時query查詢引數。最後是fragment錨點引數。
5、urlopen()方法
該方法返回的是HTTPResponse物件:
import urllib.request as request response = request.urlopen('http://www.bigdata17.com') print(response) <http.client.HTTPResponse object at 0x000002A9655BBF28>
HTTPResponse物件有read(),getheaders()等方法。
通過read()方法可以讀取網頁的資訊:
import urllib.request as request response = request.urlopen('http://www.bigdata17.com') print(response.read().decode('utf-8'))
使用該方法時要注意網站使用的編碼格式,配合decode()方法一起使用,否則會出現亂碼。像百度用的是utf-8,網易用的是gbk。
getHeaders()方法返回的是網頁的頭資訊:
import urllib.request as request response = request.urlopen('http://www.bigdata17.com') print(response.getheaders()) 結果: [('Server', 'nginx/1.12.2'), ('Date', 'Mon, 12 Nov 2018 15:45:22 GMT'), ('Content-Type', 'text/html'), ('Content-Length', '38274'), ('Last-Modified', 'Thu, 08 Nov 2018 00:35:52 GMT'), ('Connection', 'close'), ('ETag', '"5be384e8-9582"'), ('Accept-Ranges', 'bytes')]
繼續看urlopen()方法有哪些引數:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
其中url是必須傳遞的引數,其他的引數不是必須傳遞的。data用於將資料傳輸到我們要爬取的網站上,例如使用者名稱、密碼、驗證碼等。timeout是設定請求超時時間。
data引數的用法:
>>> import urllib.parse as parse >>> import urllib.request as request >>> data = bytes(parse.urlencode({'username': 'bigdata17'}), encoding='utf8') >>> print(data) b'username=bigdata17' >>> response = request.urlopen('http://httpbin.org/post', data=data) >>> print(response.read()) b'{\n"args": {}, \n"data": "", \n"files": {}, \n"form": {\n"username ": "bigdata17"\n}, \n"headers": {\n"Accept-Encoding": "identity", \n "Connection": "close", \n"Content-Length": "18", \n"Content-Type": "appl ication/x-www-form-urlencoded", \n"Host": "httpbin.org", \n"User-Agent": "Python-urllib/3.7"\n}, \n"json": null, \n"origin": "183.134.52.58", \n "url": "http://httpbin.org/post"\n}\n'
使用data傳輸資料時,必須將urlencode方法將data的資料轉換為bytes型別。
在使用urlopen方法時,如果不使用data引數,則使用的get方式傳送資料,如果使用了data引數,則是以post的方式傳送資料。post的方式必須保證要爬取的網站上有相應的方法(上面程式碼要爬取的網址是http://httpbin.org/post,post就是要處理我們通過data引數傳輸資料的方法),否則會報urllib.error.HTTPError: HTTP Error 404: NOT FOUND 的錯誤。
timeout引數的用法:
該引數是用於設定請求超時時間,免得出現網路故障或伺服器異常時我們的爬蟲程式長時間等:
import urllib.request as request response = request.urlopen('http://www.bigdata17.com', timeout=1) print(response.read())
如果將timeout設定為0.01,則會報如下的錯誤:
socket.timeout: timed out During handling of the above exception, another exception
設定請求頭資訊:
請求的頭資訊一般對帶有瀏覽器的資訊,很多網站根據請求頭資訊來判斷該請求是正常的瀏覽器發起的還是由爬蟲發起的。設定爬蟲頭資訊方法:
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': 'bigdata17' } data = bytes(parse.urlencode(dict), encoding='utf8') req = request.Request(url=url, data=data, headers=headers, method='POST') response = request.urlopen(req) print(response.read().decode('utf-8'))
設定代理:
如果一個ip過於頻繁的訪問某一個網站時,根據反爬蟲措施,會限制該IP的訪問。我們可以通過urllib提供的ProxyHandler方法來設定代理:
import urllib.request proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.bigdata17.com:3128/'}) proxy_auth_handler = urllib.request.ProxyBasicAuthHandler() proxy_auth_handler.add_password('realm', 'host', 'username', 'password') opener = urllib.request.build_opener(proxy_handler, proxy_auth_handler) # This time, rather than install the OpenerDirector, we use it directly: opener.open('https://accounts.douban.com/login?alias=&redir=https%3A%2F%2Fwww.douban.com%2F&source=index_nav&error=1001')