如何用 Python 爬取需要登錄的網站?

最近我必須執行一項從一個需要登錄的網站上爬取一些網頁的操作。它沒有我想象中那麼簡單,因此我決定為它寫一個輔助教程。

在本教程中,我們將從我們的bitbucket賬戶中爬取一個項目列表。

教程中的代碼可以從我的 Github 中找到。

我們將會按照以下步驟進行:

  1. 提取登錄需要的詳細信息
  2. 執行站點登錄
  3. 爬取所需要的數據

在本教程中,我使用了以下包(可以在 requirements.txt 中找到):

requests

lxml

步驟一:研究該網站

打開登錄頁面

進入以下頁面 “bitbucket.org/account/signin”。你會看到如下圖所示的頁面(執行註銷,以防你已經登錄)

如何用 Python 爬取需要登錄的網站?

仔細研究那些我們需要提取的詳細信息,以供登錄之用

在這一部分,我們會創建一個字典來保存執行登錄的詳細信息:

1. 右擊 “Username or email” 字段,選擇“查看元素”。我們將使用 “name” 屬性為 “username” 的輸入框的值。“username”將會是 key 值,我們的用戶名/電子郵箱就是對應的 value 值(在其他的網站上這些 key 值可能是 “email”,“ user_name”,“ login”,等等)。

如何用 Python 爬取需要登錄的網站?

如何用 Python 爬取需要登錄的網站?

2. 右擊 “Password” 字段,選擇“查看元素”。在腳本中我們需要使用 “name” 屬性為 “password” 的輸入框的值。“password” 將是字典的 key 值,我們輸入的密碼將是對應的 value 值(在其他網站key值可能是 “userpassword”,“loginpassword”,“pwd”,等等)。

如何用 Python 爬取需要登錄的網站?

如何用 Python 爬取需要登錄的網站?

3. 在源代碼頁面中,查找一個名為 “csrfmiddlewaretoken” 的隱藏輸入標籤。“csrfmiddlewaretoken” 將是 key 值,而對應的 value 值將是這個隱藏的輸入值(在其他網站上這個 value 值可能是一個名為 “csrftoken”,“ authenticationtoken” 的隱藏輸入值)。列如:“Vy00PE3Ra6aISwKBrPn72SFml00IcUV8”。

如何用 Python 爬取需要登錄的網站?

如何用 Python 爬取需要登錄的網站?

最後我們將會得到一個類似這樣的字典:

payload = {

"username": "",

"password": "",

"csrfmiddlewaretoken": ""

}

請記住,這是這個網站的一個具體案例。雖然這個登錄表單很簡單,但其他網站可能需要我們檢查瀏覽器的請求日誌,並找到登錄步驟中應該使用的相關的 key 值和 value 值。

步驟2:執行登錄網站

對於這個腳本,我們只需要導入如下內容:

import requests

from lxml import html

首先,我們要創建 session 對象。這個對象會允許我們保存所有的登錄會話請求。

session_requests = requests.session()

第二,我們要從該網頁上提取在登錄時所使用的 csrf 標記。在這個例子中,我們使用的是 lxml 和 xpath 來提取,我們也可以使用正則表達式或者其他的一些方法來提取這些數據。

login_url = "https://bitbucket.org/account/signin/?next=/"

result = session_requests.get(login_url)

tree = html.fromstring(result.text)

authenticity_token = list(set(tree.xpath("//input[@name='csrfmiddlewaretoken']/@value")))[0]

**更多關於xpath 和lxml的信息可以在這裡找到。

接下來,我們要執行登錄階段。在這一階段,我們發送一個 POST 請求給登錄的 url。我們使用前面步驟中創建的 payload 作為 data 。也可以為該請求使用一個標題並在該標題中給這個相同的 url 添加一個參照鍵。

result = session_requests.post(

login_url,

data = payload,

headers = dict(referer=login_url)

)

步驟三:爬取內容

現在,我們已經登錄成功了,我們將從 bitbucket dashboard 頁面上執行真正的爬取操作。

url = 'https://bitbucket.org/dashboard/overview'

result = session_requests.get(

url,

headers = dict(referer = url)

)

為了測試以上內容,我們從 bitbucket dashboard 頁面上爬取了項目列表。我們將再次使用 xpath 來查找目標元素,清除新行中的文本和空格並打印出結果。如果一切都運行 OK,輸出結果應該是你 bitbucket 賬戶中的 buckets / project 列表。

tree = html.fromstring(result.content)

bucket_elems = tree.findall(".//span[@class='repo-name']/")

bucket_names = [bucket.text_content.replace("n", "").strip() for bucket in bucket_elems]

print bucket_names

你也可以通過檢查從每個請求返回的狀態代碼來驗證這些請求結果。它不會總是能讓你知道登錄階段是否是成功的,但是可以用來作為一個驗證指標。

例如:

result.ok # 會告訴我們最後一次請求是否成功

result.status_code # 會返回給我們最後一次請求的狀態

就是這樣。


分享到:


相關文章: