Python 爬蟲入門一:網絡請求的處理

Python 有非常多網絡請求相關的庫,這裏我只介紹一些我自己用過的庫,但不一定是最好的庫。
我會按照“任務”的方式來組織這篇文章。

0 前情提要

Python 爬蟲科普:爬蟲是什麼?該怎麼入門?

1 進行簡單請求

有一些網站沒有身份校驗的要求,通過最簡單的網絡請求就能拿到你要的結果,例如上篇文章裏的這個例子:

from urllib import request # 用於發起網絡請求的庫

response = request.urlopen("https://api.ipify.org") # 任務一:發起網絡請求
IP = response.read().decode('utf8') # 任務二:處理數據
print(IP) # 任務三:保存或展示數據

2 添加 GET 參數

如果還不瞭解 GET、POST 等請求方法的概念,還請先通過百度等方式瞭解一下。
GET 參數往往就在請求的鏈接中,通過瀏覽器的地址欄即可瞭解。

from urllib import parse # 用於處理參數
from urllib import request # 用於發起網絡請求的庫

searchURL = 'https://www.baidu.com/s?' # 請求地址
# GET 參數
para = {
	'ie': 'utf-8',
	'wd': 'Python 爬蟲'
}

# 對 GET 參數進行 URL 編碼
getPara = parse.urlencode(para)

# 發起請求
response = request.urlopen(searchURL + getPara)
print(response.read().decode('utf8'))

3 添加 POST 數據

通過 POST 方法提交數據,通常見於用戶註冊登錄、提交一些表單數據。在開始之前你需要確保:

POST 有多種方式( Content-Type ),可以參考這篇文章,其中最常見的還是 application/x-www-form-urlencodedmultipart/form-data 兩種。

3.1 application/x-www-form-urlencoded 的方式

POST 請求通常用於登錄動作,因此你可以找一個網站的登錄頁面進行練手,例如知乎。
挑選練手網站時請注意,如果你在網頁的表單裏看到一個 csrf_token 類似的隱藏字段,那麼請你先換一個其他的網站,這個 csrf_token 的處理目前是超綱的。

使用 POST 方法進行請求時,默認會按照 application/x-www-form-urlencoded 的方式進行參數的傳遞,調用也相對簡單。
爲了傳遞 POST 參數,就不能簡單地 urlopen 了,你需要使用 request 對象來描述你的請求。

from urllib import request

loginURL = '...某個登錄鏈接...'
email = '郵箱'
password = '密碼'


data = {
    'user': email, # 這裏的 data 字段,具體需要看你練手網站上表單各字段的 ID
    'pw':password
}

Request = request.Request(loginURL, \
                          method = 'POST', \
                          data = bytes(urllib.parse.urlencode(data), encoding = 'utf-8'))
# Request 對象包含了一個網絡請求所需的所有信息,除了鏈接地址,還有請求方法、請求參數、其他 header 
# method 參數說明請求的方式是 POST
# data 參數規定 POST 請求的數據,bytes() 函數將 string 使用規定編碼進行二進制編碼
                                 
response = request.urlopen(Request) # 完成請求
result = response.read().decode('utf-8') # 讀取結果
print(result)

關於 Request 對象的深入介紹,可以參考 官網說明

3.2 multipart/form-data 的方式

需要通過 POST 上傳文件的時候,網站就只能使用 multipart/form-data 了,實際上作爲爬蟲,POST 請求通常只會用在登錄、提交搜索之類的操作中,所以使用這個請求方式的機會並不多見。
這篇教程 有非常詳盡的說明,感興趣的同學可以來看一下。當然你也可以通過 requests

4 傳遞 cookie

瀏覽器裏的 cookie 大概就是對話的“環境”,這篇教程 對 cookie 進行了大致的介紹。
實際上“登錄”操作的結果,就是返回了一個憑證,當你發起網絡請求時,帶上這個憑證,就證明了你是登錄的用戶。而這個“憑證”就存放在 cookie 裏。
所以模擬登錄最重要的,實際上是獲取 cookie,並且在後續的請求中把相應的 cookie 帶上,從而模擬一個“對話環境”。

from urllib import request # 用於處理網絡請求
from http import cookiejar # 用於處理 cookie

cookies = cookiejar.CookieJar() # 設置一個 cookie 容器,可以對容器中的信息進行讀寫

opener = request.build_opener(request.HTTPCookieProcessor(cookies), request.HTTPHandler(), request.HTTPSHandler())
# build_opener() 的參數是一些“處理器”,返回一個類似“瀏覽器對象”,這些“處理器”爲返回的“瀏覽器對象”賦予能力
# HTTPCookieProcessor 是 cookie 的處理器,我們使用了 cookies 容器進行初始化,後續的所有 cookie 均可以通過這個變量進行讀寫
# HTTPHandler 是 http 請求的處理器
# HTTPSHandler 是 https 請求的處理器

userRequest = urllib.request.Request('請求地址', ...) # 根據具體請求的情況組建請求
response = opener.open(userRequest) # 使用之前生成的“瀏覽器對象”進行請求

print(cookie) # 此次請求生成的 cookie 已經放到了 cookie 裏

通過官網說明,你可以瞭解 cookiejar 的具體用法;
想了解 build_opener 相關的詳細介紹,也可以看官網說明

還有一種偷懶的情況,其實你可以利用瀏覽器裏已經存在的 cookie 信息,從而不用模擬登錄,就可以用一個“用戶身份”,進行網站的訪問。
也有一個 Python 庫,就是來獲取瀏覽器中 cookie 的,這個庫不是原生提供的,可以通過 pip 直接安裝。

pip install browsercookie # 如果你不瞭解 pip,可以去查一查 pypi 相關的教程

使用起來也比較簡單

import browsercookie

# 通過最簡單的方式獲取 Chrome 裏的 cookie
chrome_cookie = browsercookie.chrome()
# 另外還支持 firefox 和 Safari,可以通過 help(browsercookie) 查看
# chrome_cookie 是一個 cookiejar 對象

# 複雜一點的語法
Chrome = browsercookie.Chrome()
file_path = Chrome.find_cookie_files() # Chrome 的 cookie 存放路徑
chrome_cookie = Chrome.get_cookies() # 獲取 cookie

5 進階:設置“客戶端”

所謂“客戶端”,就是發起請求的那個“端”,例如我電腦上的 Chrome 就是 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36

這個“客戶端段”在發起請求時,是作爲一個 header 傳遞出去的,字段是 User-Agent 。不瞭解 header 的同學可以看下 這篇教程,在上一節中提到的 Content-Type 實際上也是 header 的一個。

Python 的 urllib 庫發起的請求,默認使用的 User-Agent 是 “python”,有一些爬蟲框架也會使用自己的 User-Agent ,例如 “scrapy”。有一些網站會根據 User-Agent 制定一些反爬蟲策略,爬蟲往往也會遵循網站的一些規定,比方你可以看看知乎對爬蟲的策略
因此,你可以修改這個 User-Agent 做一些無傷大雅的事情。同樣,網上也有關於設置“客戶端”的詳細教程,比如說這一篇

6 進階:設置代理

一些情況下,需要使用代理才能訪問網站,Python 也提供了便捷的工具,實際上就是爲我們的“瀏覽器對象”再賦予一個新的“處理器”。
拿 socks5 代理爲例進行說明:

import sockshandler # 引入 socks 處理器
import socks # socks 是一個更低層次的接口封裝
# 如果引入時出現問題,請現在命令行 pip install PySocks

opener = build_opener(sockshandler.SocksiPyHandler(socks.SOCKS5, "127.0.0.1", 1080), ...) # 根據需要添加其他 handler
# SocksiPyHandler 即 socks 代理的處理器
# socks.SOCKS5 說明代理類型是 socks5
# 127.0.0.1 是代理地址
# 1080 是代理端口

userRequest = ... # 組裝 Request
response = opener.open(userRequest) # 進行網絡請求

# ... 結果處理

如果感興趣,可以通過 官方說明sockshandler.SocksiPyHandler 進行更深入的瞭解。
關於 HTTP 和 HTTPS 代理,這篇教程 說得很好,大家可以看看

7 進階:攜帶證書

如果大家還有印象,最早的時候 12306 需要下載一個證書後才能正常訪問,而且必須使用 IE 瀏覽器。在一些公司內網安全防控要求也很高,需要在員工電腦上安裝證書纔可以進行某些網頁請求,其實和 12306 的做法是相似的。
使用 Python 進行這些頁面的訪問時,就需要把自己的證書帶上。

這裏又涉及到非常多的知識點,對於我一個非計算機出身的人來講,還是花了很長的時間來學習

  • 首先關於 HTTPS,你可以參考 這個說明,一篇可能並不夠
  • 關於公鑰、密鑰的知識,這一篇說明 還不錯
  • 瞭解以上概念後,你可能需要對數字證書有更清晰的認識,比方說 這篇這篇,從而把你的證書轉成 Python 可以識別的格式

Python 裏 urllib 還是通過“瀏覽器對象”和“處理器”來夾帶證書信息的。

from ssl import SSLContext # 處理 https 請求環境,例如證書
from urllib import request

# 設置證書環境
sslContext = SSLContext()
sslContext.load_cert_chain(certfile = '證書路徑/證書.pem')

opener = request.build_opener(request.HTTPCookieProcessor(context = sslContext), ...) # 添加所有必要的處理器
# 將證書環境賦予處理器

userRequest = ... # 組裝 Request
response = opener.open(userRequest) # 進行網絡請求

# ... 結果處理

8 總結

一篇文章其實只是一個切片,這篇文章裏的外鏈多到令人髮指,“看完”這篇文章所需要花費的時間是很長的。
其實也正說明了爬蟲爲什麼對非計算機專業的同學來講,爲啥比較不好入門,因爲需要的預備知識的確比較多。
但是隻要有耐心,這些知識還是能夠掌握的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章