1、讀取cookies 2、將cookies保存在文件中 3、處理異常 URLError和HTTPError類,兩個類是父子關係,HTTPError會返回錯誤代碼,兩個類都可以處理request模塊產生的異常,這兩個都有一個reason屬性,用於記錄出現異常的原因 URLError處理異常: HTT ...
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')