最近我必須執行一項從一個須要登陸的網站上爬取一些網頁的操做。它沒有我想象中那麼簡單,所以我決定爲它寫一個輔助教程。html
在本教程中,咱們將從咱們的bitbucket帳戶中爬取一個項目列表。正則表達式
教程中的代碼能夠從個人 Github 中找到。瀏覽器
咱們將會按照如下步驟進行:session
提取登陸須要的詳細信息post
執行站點登陸學習
爬取所須要的數據測試
在本教程中,我使用瞭如下包(能夠在 requirements.txt 中找到):網站
requestsui
lxmlurl
步驟一:研究該網站
打開登陸頁面
進入如下頁面 「bitbucket.org/account/signin」。你會看到以下圖所示的頁面(執行註銷,以防你已經登陸)
若是你在學習Python的過程當中碰見了不少疑問和難題,能夠加-q-u-n 227 -435-450裏面有軟件視頻資料免費
仔細研究那些咱們須要提取的詳細信息,以供登陸之用
在這一部分,咱們會建立一個字典來保存執行登陸的詳細信息:
1. 右擊 「Username or email」 字段,選擇「查看元素」。咱們將使用 「name」 屬性爲 「username」 的輸入框的值。「username」將會是 key 值,咱們的用戶名/電子郵箱就是對應的 value 值(在其餘的網站上這些 key 值多是 「email」,「 user_name」,「 login」,等等)。
2. 右擊 「Password」 字段,選擇「查看元素」。在腳本中咱們須要使用 「name」 屬性爲 「password」 的輸入框的值。「password」 將是字典的 key 值,咱們輸入的密碼將是對應的 value 值(在其餘網站key值多是 「userpassword」,「loginpassword」,「pwd」,等等)。
3. 在源代碼頁面中,查找一個名爲 「csrfmiddlewaretoken」 的隱藏輸入標籤。「csrfmiddlewaretoken」 將是 key 值,而對應的 value 值將是這個隱藏的輸入值(在其餘網站上這個 value 值多是一個名爲 「csrftoken」,「 authenticationtoken」 的隱藏輸入值)。列如:「Vy00PE3Ra6aISwKBrPn72SFml00IcUV8」。
最後咱們將會獲得一個相似這樣的字典:
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 # 會返回給咱們最後一次請求的狀態
就是這樣。