利用Python模擬GitHub登陸

最近學習了Fiddler抓包工具的簡單使用,經過抓包,咱們能夠抓取到HTTP請求,並對其進行分析。如今我準備嘗試着結合Python來模擬GitHub登陸。html

Fiddler抓包分析

首先,咱們想要模擬一個網站的登陸,咱們必需要簡單瞭解其大體過程。
在這裏,我經過Fiddler來抓取GitHub登陸的請求,從網頁上登陸的URL爲:https://github.com/login ,抓包結果以下:git

左邊的是會話列表,右邊的是請求和響應的數據。通常狀況下,登陸都是用POST請求,由於我在左邊的會話列表中設置了顯示RequestMethod一列,所以可以很方便的找到POST請求。固然,Fiddler默認不顯示RequestMethod,若是沒有設置,還能夠經過命令「=post」來快速過濾POST請求。github

在GitHub登陸時,咱們經過抓包發現,GitHub登陸的URL雖然時https://github.com/login,但發生了302重定向,其真正提交POST表單數據的URL是 https://github.com/session ,當登陸成功時,則會跳轉到 https://github.com/ 首頁。web

打開WebForm,咱們能夠看到POST表單數據提交的值,能夠發現,只有authenticity_token、login、password三個字段是會變化的,其他的每次登陸都是固定的值。而login、password分別是咱們登陸的用戶和密碼,所以咱們只須要分析出 authenticity_token 從何而來,即可以實現模擬登陸了。正則表達式

至於如何肯定 authenticity_token 從哪一個頁面返回的,咱們直接在響應數據中搜索就好了,或者把數據複製出來再進行搜索。最後咱們會發現,authenticity_token 是在 https://github.com/login 這個請求中返回的,只不過用 hidden 隱藏起來了。瀏覽器

好了,到目前大體流程咱們已經梳理清楚了,接下來咱們便經過Python來實現模擬GitHub登陸。cookie

代碼實現

本人環境:PyCharm 2018.2.四、Python3.7.0session

1. 設置請求頭和Session

# 設置Session
        self.s = requests.session()
        # 設置請求頭
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:44.0) Gecko/20100101 Firefox/44.0"
        }
        # 在使用Fiddler時進行請求,經過該代碼忽略SSLError錯誤
        self.s.verify = False

在這裏,咱們設置了Session會話對象,Session至關於1個微型瀏覽器,可以自動幫咱們保持請求中的某些參數(如cookies),有了它,咱們通常不須要額外去處理cookies、header等。
假如咱們是在Fiddler打開的狀態下,經過代碼進行請求,那麼將會遇到SSLError的錯誤,而當加上 self.s.verify = False 這行代碼後,咱們即可以忽略該錯誤。工具

requests.exceptions.SSLError: HTTPSConnectionPool(host='github.com', port=443): Max retries exceeded with url: /login (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)')))

注意:
咱們經過上面的代碼忽略了SSLError的錯誤後,再次運行,這時仍然會出現2行警告,這2個警告並不影響咱們的登陸,能夠無論它。post

D:\Python\installation\lib\site-packages\urllib3\connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
D:\Python\installation\lib\site-packages\urllib3\connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)

若是咱們想去掉這2行警告,也能夠經過以下代碼來解決(針對Python3):

import urllib3
urllib3.disable_warnings()

2. 獲取authenticity_token

login_url = "https://github.com/login"
        r = self.s.get(login_url, headers = self.headers)
        authenticity_token = re.findall('<input type="hidden" name="authenticity_token" value="(.+?)" />', r.text)
        print("authenticity_token:{}".format(authenticity_token))
        return authenticity_token[1]

當咱們訪問 https://github.com/login 時,登陸界面會生成隱藏參數authenticity_token,而這恰是咱們在登陸提交表單時須要用到的參數。咱們可經過正則表達式 re.findall 來獲取authenticity_token。另外,咱們還會發現,HTML界面中存在2個authenticity_token,所以經過正則返回的是一個長度爲2的列表,通過分析,GitHub在登陸時用到的是列表中的第二個元素,即authenticity_token[1]。

3. 模擬登陸

def github_login(self, authenticity_token, username, password):
        session_url = "https://github.com/session"
        body = {
            "authenticity_token":authenticity_token,
            "commit":"Sign in",
            "login":username,
            "password":password,
            "utf8":"✓",
            "webauthn-support":"unknown"
        }
        r = self.s.post(session_url, headers = self.headers, data = body)
        title = re.findall('<title>(.+?)</title>',r.text)
        print("title:%s" %title[0])
        return title[0]

咱們在上面獲得authenticity_token後,即可以來實現登陸了。經過POST請求提交表單後,咱們須要判斷是否登陸成功。在這裏,我是經過頁面的標題來判斷GitHub是否登陸成功,固然,還有許多方法能夠用於判斷。

4. 經過 title 判斷是否登陸成功

def is_login_success(self, title):
        if "GitHub" == title:
            return True
        else:
            return False

GitHub登陸成功後,界面的標題會顯示"GitHub",而登陸失敗時,通常顯示的標題則是"Sign in to GitHub · GitHub"。

OK,以上就是經過Python模擬GitHub登陸的過程,難度不大,相信大多數人閱讀後都應該能夠進行實踐。

附源碼:

import requests
import re
import urllib3
urllib3.disable_warnings()

class Github_Login():

    def __init__(self):
        # 設置Session
        self.s = requests.session()
        # 設置請求頭
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:44.0) Gecko/20100101 Firefox/44.0"
        }
        # 在使用Fiddler時進行請求,經過該代碼忽略SSLError錯誤
        self.s.verify = False

    # 獲取 authenticity_token
    def get_authenticity_token(self):
        login_url = "https://github.com/login"
        r = self.s.get(login_url, headers = self.headers)
        authenticity_token = re.findall('<input type="hidden" name="authenticity_token" value="(.+?)" />', r.text)
        print("authenticity_token:{}".format(authenticity_token))
        return authenticity_token[1]

    # 模擬登陸,並返回 title
    def github_login(self, authenticity_token, username, password):
        session_url = "https://github.com/session"
        body = {
            "authenticity_token":authenticity_token,
            "commit":"Sign in",
            "login":username,
            "password":password,
            "utf8":"✓",
            "webauthn-support":"unknown"
        }
        r = self.s.post(session_url, headers = self.headers, data = body)
        title = re.findall('<title>(.+?)</title>',r.text)
        print("title:%s" %title[0])
        return title[0]

    # 經過 title 判斷是否登陸成功
    def is_login_success(self, title):
        if "GitHub" == title:
            return True
        else:
            return False

if __name__ == '__main__':
    github = Github_Login()
    authenticity_token = github.get_authenticity_token()
    title = github.github_login(authenticity_token, username = "用戶名", password = "密碼")
    login_result = github.is_login_success(title)
    print(login_result)

若有錯誤,歡迎指出!

相關文章
相關標籤/搜索