人生苦短,我用 Pythonhtml
前文傳送門:python
小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝github
小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門數據庫
小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門json
小白學 Python 爬蟲(5):前置準備(四)數據庫基礎瀏覽器
小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝cookie
小白學 Python 爬蟲(10):Session 和 Cookies
小白學 Python 爬蟲(11):urllib 基礎使用(一)
上一篇咱們聊了 urlopen 的基本使用姿式,但這幾個簡單的參數並不足以構建一個完整的請求。對於複雜的請求,例如須要添加請求頭就顯得無能爲力,這時咱們能夠選擇使用 Request 。
官方文檔:https://docs.python.org/zh-cn/3.7/library/urllib.request.html
首先來看一下 Request 的使用語法:
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)複製代碼
仍是先來看一個簡單的示例,使用 Request 爬取博客網站:
import urllib.request
request = urllib.request.Request('https://www.geekdigging.com/')
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))複製代碼
能夠看到,這裏仍是使用 urlopen() 來發起請求,只是參數再也不是以前的 URL 、 Data 、 timeout 等等信息,而是變成了 Request
類型的對象。
咱們來構建一個稍微複雜一點的請求。
import urllib.request, urllib.parse
import json
url = 'https://httpbin.org/post'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
'Content-Type': 'application/json;encoding=utf-8',
'Host': 'geekdigging.com'
}
data = {
'name': 'geekdigging',
'hello':'world'
}
data = bytes(json.dumps(data), encoding='utf8')
req = urllib.request.Request(url=url, data=data, headers=headers, method='POST')
resp = urllib.request.urlopen(req)
print(resp.read().decode('utf-8'))複製代碼
結果以下:
{
"args": {},
"data": "{\"name\": \"geekdigging\", \"hello\": \"world\"}",
"files": {},
"form": {},
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "41",
"Content-Type": "application/json;encoding=utf-8",
"Host": "geekdigging.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
},
"json": {
"hello": "world",
"name": "geekdigging"
},
"origin": "116.234.254.11, 116.234.254.11",
"url": "https://geekdigging.com/post"
}複製代碼
這裏咱們經過 4 個參數構建了一個 Request
對象。
經過 url 指定了訪問的連接,仍是前面一片文章中提到的測試連接。
在 headers 中指定了 User-Agent
、 Content-Type
和 Host
3 個參數。
在 data 中使用 json.dumps()
將一個 dict 轉換成 json 格式,並經過 bytes()
最終轉換爲字節流。
最後,指定了訪問方式爲 POST 。
從最終的結果中,能夠看到咱們前面的設定全都成功。
前面咱們使用 Request 完成了請求頭的添加,若是咱們想處理 Cookies 和使用代理訪問,就須要使用到更增強大的 Handler 了。 Handler 能夠簡單理解爲各類功能的處理器,使用它,幾乎能夠爲咱們作到全部有關 HTTP 請求的事情。
urllib.request 爲咱們提供了 BaseHandler 類,它是全部其餘 Handler 的父類,它提供了直接使用使用的方法以下:
接下來,就有各類 Handler 子類集成這個 BaseHandler 類:
等等, urllib 爲咱們提供的 BaseHandler 子類很是的多,小編這裏就不一一列舉,各位同窗能夠經過訪問官方文檔來查看。
官方文檔地址:https://docs.python.org/zh-cn/3.7/library/urllib.request.html#basehandler-objects
在介紹如何使用 Handler 以前,先介紹一個高級類: OpenerDirector 。
OpenerDirector 是用來處理URL的高級類,它分三個階段來打開URL:
在每一個階段中調用這些方法的順序是經過對處理程序實例進行排序來肯定的;每一個使用此類方法的程序都會調用 protocolrequest() 方法來預處理請求,而後調用 protocolopen() 來處理請求;最後調用 protocol_response() 方法來處理響應。
咱們能夠稱 OpenerDirector 爲 Opener 。咱們以前用過 urlopen() 這個方法,實際上它就是 urllib 爲咱們提供的一個 Opener 。
Opener的方法包括:
下面咱們來演示一下如何獲取網站的 Cookies :
import http.cookiejar, urllib.request
# 實例化cookiejar對象
cookie = http.cookiejar.CookieJar()
# 使用 HTTPCookieProcessor 構建一個 handler
handler = urllib.request.HTTPCookieProcessor(cookie)
# 構建Opener
opener = urllib.request.build_opener(handler)
# 發起請求
response = opener.open('https://www.baidu.com/')
print(cookie)
for item in cookie:
print(item.name + " = " + item.value)複製代碼
代碼中具體的含義小編就再也不解釋了,註釋已經寫得比較完善。最後獲得的打印結果以下:
<CookieJar[<Cookie BAIDUID=48EA1A60922D7A30F711A420D3C5BA22:FG=1 for .baidu.com/>, <Cookie BIDUPSID=48EA1A60922D7A30DA2E4CBE7B81D738 for .baidu.com/>, <Cookie PSTM=1575167484 for .baidu.com/>, <Cookie BD_NOT_HTTPS=1 for www.baidu.com/>]>
BAIDUID = 48EA1A60922D7A30F711A420D3C5BA22:FG=1
BIDUPSID = 48EA1A60922D7A30DA2E4CBE7B81D738
PSTM = 1575167484
BD_NOT_HTTPS = 1複製代碼
這裏產生一個問題, cookie 既然能夠打印,那麼咱們能不能將 cookie 的輸出保存到文件中呢?
答案固然是能夠的,由於咱們知道, cookie 自己就是保存在文件中的。
# cookies 保存 Mozilla 型文件示例
filename = 'cookies_mozilla.txt'
cookie = http.cookiejar.MozillaCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)
print('cookies_mozilla 保存成功')複製代碼
這裏咱們需修改以前的 CookieJar
爲 MozillaCookieJar
,它在生成文件時會用到,是 CookieJar 的子類,能夠用來處理 Cookies 和文件相關的事件,好比讀取和保存 Cookies ,能夠將 Cookies 保存成 Mozilla 型瀏覽器的 Cookies 格式。
在運行完成以後,咱們能夠在當前程序的目錄下看到生成了一個 cookies.txt
的文件,具體內容以下:
# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file! Do not edit.
.baidu.com TRUE / FALSE 1606703804 BAIDUID 0A7A76A3705A730B35A559B601425953:FG=1
.baidu.com TRUE / FALSE 3722651451 BIDUPSID 0A7A76A3705A730BE64A1F6D826869B5
.baidu.com TRUE / FALSE H_PS_PSSID 1461_21102_30211_30125_26350_30239
.baidu.com TRUE / FALSE 3722651451 PSTM 1575167805
.baidu.com TRUE / FALSE delPer 0
www.baidu.com FALSE / FALSE BDSVRTM 0
www.baidu.com FALSE / FALSE BD_HOME 0複製代碼
小編比較懶,就不截圖了,直接貼結果了。
固然咱們除了能夠將 cookies 保存成爲 Mozilla 型瀏覽器的格式,還能夠將 cookies 保存成爲 libwww-perl(LWP) 格式的 Cookies 文件。
要保存成LWP格式的Cookies文件,在聲明的時候須要修改成 LWPCookieJar:
# cookies 保存 LWP 型文件示例
filename = 'cookies_lwp.txt'
cookie = http.cookiejar.LWPCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)
print('cookies_lwp 保存成功')複製代碼
執行結果以下:
#LWP-Cookies-2.0
Set-Cookie3: BAIDUID="D634D45523004545C6E23691E7CE3894:FG=1"; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2020-11-30 02:45:24Z"; comment=bd; version=0
Set-Cookie3: BIDUPSID=D634D455230045458E6056651566B7E3; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2087-12-19 05:59:31Z"; version=0
Set-Cookie3: H_PS_PSSID=1427_21095_30210_18560_30125; path="/"; domain=".baidu.com"; path_spec; domain_dot; discard; version=0
Set-Cookie3: PSTM=1575168325; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2087-12-19 05:59:31Z"; version=0
Set-Cookie3: delPer=0; path="/"; domain=".baidu.com"; path_spec; domain_dot; discard; version=0
Set-Cookie3: BDSVRTM=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0
Set-Cookie3: BD_HOME=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0複製代碼
能夠看到,兩種類型產生的 cookie 文件格式差別仍是很是大的。
已經生成了 cookie 文件,下一步咱們就是要在請求的時候添加 cookie ,示例代碼以下:
# 請求是使用 Mozilla 型文件
cookie = http.cookiejar.MozillaCookieJar()
cookie.load('cookies_mozilla.txt', ignore_discard=True, ignore_expires=True)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
print(response.read().decode('utf-8'))複製代碼
這裏咱們使用 load() 方法來讀取本地的Cookies文件,獲取到了 Cookies 的內容。
前提是,咱們須要提早生成了 Mozilla 格式的 cookie 文件,而後讀取 Cookies 以後使用一樣的方法構建 Handler 和 Opener 便可。
請求正常的時候能夠相應擺渡首頁的源碼,結果小編也就不貼了,屬實有點長。
本篇的內容就到這裏了,但願各位同窗記得本身動手寫代碼哦~~~
本系列的全部代碼小編都會放在代碼管理倉庫 Github 和 Gitee 上,方便你們取用。
https://www.cnblogs.com/zhangxinqi/p/9170312.html
https://cuiqingcai.com/5500.html