使用Python的POST請求如何使Web抓取更容易?
譯文【51CTO.com快譯】當使用Python抓取一個網站時,通常使用urllib或Requests庫向服務器發(fā)送GET請求以接收其信息。
然而,在接收所需數(shù)據(jù)之前,需要你向網站發(fā)送一些信息,這可能是因為必須執(zhí)行登錄或以某種方式與頁面交互。
為了執(zhí)行這樣的交互,Selenium是一個常用的工具。然而,它也有一些缺點,因為它有點慢,有時也很不穩(wěn)定。另一種方法是發(fā)送一個POST請求包含網站需要使用請求庫的信息。
實際上,與Requests相比,Selenium變得非常慢,是因為它實際上要完成打開瀏覽器瀏覽收集數(shù)據(jù)的網站的整個工作。而對于某些其他情況,POST請求可能是更好的選擇,這使它成為Web抓取的重要工具之一。
在本文中,將簡要介紹POST方法,以及如何使用它改進Web抓取程序。
Web 抓取
盡管POST請求通常用于與API交互,但它們也有助于在網站中填寫HTML表單或自動執(zhí)行其他操作。
在Web抓取過程中,能夠執(zhí)行這些任務是一項重要的能力,因為在獲取數(shù)據(jù)之前必須與Web頁面進行交互是很常見的流程。
識別HTML表單
在開始向網站發(fā)送信息之前,首先需要了解它將如何接收這些信息。假設你的想法是登錄你的賬戶。
如果是這種情況,您需要做的就是在POST請求中發(fā)送用戶名和密碼。
但是,如何識別并查看HTML表單的外觀呢?這時我們可以考慮使用我們的老朋友:GET請求。使用GET并使用BeautifulSoup解析HTML,很容易看到頁面上的所有HTML表單以及它們的外觀。
代碼如下所示:
import requests
from bs4 import BeautifulSoup
page = requests.get('http://website.com').text
soup = BeautifulSoup(page, 'html.parser')
forms = soup.find_all('form')
for form in forms:
print(form)
這就是我們簡單的登錄表單,它將成為上面代碼的輸出:
<form action="login.html" method="post">
User Name: <input name="username" type="text"/><br/>
Password: <input name="password" type="text"/><br/>
<input id="submit" type="submit" value="Submit"/>
</form>
在這樣的表單中,“動作”是網站中你應該發(fā)送請求的地方,而“用戶名”和“密碼”是你想要填寫的字段。您還可以注意到,這些值的類型被指定為文本。
提交你的第一個 POST
現(xiàn)在是發(fā)送第一個POST請求?;菊埱髮瑑蓚€參數(shù):接收請求的URL和發(fā)送的數(shù)據(jù)。
數(shù)據(jù)通常是一個字典,其中鍵是要填充的字段名,值是要填充的字段內容。數(shù)據(jù)也可以通過不同的方式傳遞,但這是一種更復雜的方法,超出了本文的范圍。
代碼也非常簡單,只需兩行就可以實現(xiàn):
payload = {'username': 'user', 'password': '1234'}
r = requests.post('http://website.com/login.html', data=payload)
print(r.status_code)
第三行代碼只是為了查看請求的狀態(tài)代碼。如果看到的狀態(tài)代碼是200,則意味著一切正常。
現(xiàn)在,我們可以通過將剛才創(chuàng)建的POST請求實現(xiàn)到函數(shù)中。下面是它的工作原理:
1. post_request函數(shù)將接收兩個參數(shù):URL和發(fā)送請求的有效負載。
2. 在函數(shù)內部,我們將使用一個 try 和 except 子句讓代碼準備好處理可能的錯誤。
3. 如果代碼沒有崩潰并且我們收到了來自服務器的響應,我們將檢查這個響應是否是我們期望的響應。如果是,函數(shù)將返回它。
4. 如果我們得到不同的狀態(tài)碼,將不返回任何內容,狀態(tài)將被打印出來。
5. 如果代碼引發(fā)異常,我們希望看到發(fā)生了什么,因此該函數(shù)將打印該異常。
示例代碼如下:
def post_request(url, payload):
try:
r = requests.post(url, data=payload)
if r.status_code == 200:
return r
else:
print(r.status_code)
except Exception as e:
print(e)
然而,根據(jù)網站的不同,為了實際執(zhí)行登錄,還需要處理其他問題。好消息是,Requests庫提供了處理cookie、HTTP身份驗證等更多內容的資源。這里的目標只是使用一種常見的表單類型作為一個簡單的例子,讓未使用過POST請求的人能夠理解。
最后
特別是如果你向特定網站發(fā)送大量請求,你可能希望在代碼中插入一些隨機暫停,以免在整個代碼中使用更多的try和except子句使服務器過載。而不僅僅是在 post_request函數(shù)中以確保它已準備好處理可能在此過程中發(fā)現(xiàn)的其他異常。
當然,利用代理提供商來確保代碼在還需要提交請求和收集數(shù)據(jù)的情況下繼續(xù)運行,以及確保連接受到保護,也是一個很好的實踐。
本文的目的只是介紹POST請求以及它們如何在Web上收集數(shù)據(jù)。我們基本上學習了如何自動填寫表單,甚至如何登錄一個網站。
【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】