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

qq1622479435發表於2018-08-23

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

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

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

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

  • 提取登入需要的詳細資訊

  • 執行站點登入

  • 爬取所需要的資料

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

requests

lxml

步驟一:研究該網站

開啟登入頁面

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

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

如果你在學習Python的過程中遇見了很多疑問和難題,可以加-q-u-n   227 -435-450裡面有軟體視訊資料免費

仔細研究那些我們需要提取的詳細資訊,以供登入之用

在這一部分,我們會建立一個字典來儲存執行登入的詳細資訊:

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”: “<USER NAME>”,

“password”: “<PASSWORD>”,

“csrfmiddlewaretoken”: “<CSRF_TOKEN>”

}

請記住,這是這個網站的一個具體案例。雖然這個登入表單很簡單,但其他網站可能需要我們檢查瀏覽器的請求日誌,並找到登入步驟中應該使用的相關的 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 inbucket_elems]

print bucket_names

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

例如:

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

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

就是這樣。


相關文章