python實現模擬登錄

此次想試一試模擬登錄,覺得應該會很順利,可是遇到了各類問題,因此記錄總結一下。
參考文章:請點擊這裏html

模擬登錄segmentfault

參考文章使用的node.js,感受沒有python用起來方便。node

工具

  • python2.7
  • Chrome瀏覽器
  • requests
  • PyV8
  • lxml

思路

首先進入segmentfault的登錄頁面
能夠隨便輸入錯誤密碼點擊登錄,使用Chrome查看請求發到了哪一個url
另外看post的參數,這裏有三個:remember, usernamepassword
而後能夠順便按照Requests Headers把請求頭設置好(照抄到代碼裏)。python

requests庫的 session對象可以幫咱們跨請求保持某些參數,也會在同一個 session實例發出的全部請求之間保持 cookies

使用:正則表達式

# 建立一個session對象 
    session = requests.session()
    # 用session對象發出get請求
    response = session.get('https://segmentfault.com/user/login')
    # 獲取cookie
    cookies = response.cookies

設置了請求頭,cookie也拿到了,看看post的url
clipboard.pngsegmentfault

發現這段url後面是帶了查詢字符串的,每次發請求都會變化。
只有明白它是如何生成的才能取得咱們要post的url,這裏我卡了很久,去尋找答案,才找到了參考文章,這裏面提供了思路獲取js中生成的token。api

  1. login.min.js中查詢字符串 "_=" (Chrome f12下使用快捷鍵Crtl+F能夠打開查詢窗口),由於注意到url是https://segmentfault.com/api/user/login?_=[querystring]

clipboard.png

發現要post的url是根url加上"?_="再加上a._.
能夠想到a是一個對象,_a這個對象的一個屬性。
能夠找到:瀏覽器

clipboard.png

因而發現了a._window.SF.tokencookie

取得token

分析:回到login文件發現tokenhtml中的script標籤中一個函數生成的,而html可使用requests.get取得,而後能夠經過pythonre模塊用正則表達式提取出所須要的函數,這時還須要python中的PyV8模塊來執行js函數。
執行:分析html的DOM節點,發現函數的位置,使用xpath取得那個script標籤session

response = requests.get('https://segmentfault.com/user/login')
    sel = html.fromstring(response.text)
    s = sel.xpath('/html/body/script[8]/text()')[0]
    st = str(s.encode('utf-8'))

寫一個get_token函數取得token(這裏要用到PyV8模塊實現pythonJavaScript的交互)
這個DOM目前是這樣的:python2.7

<script>
    (function (w) {
        w.SF = {
            staticUrl: "https://static.segmentfault.com/v-5aa63d11"
        };
        w.SF.token = (function () {
    var _PRmciaY = //'Uns'
'f44'+//'71w'
'b1e'+//'C'
'9a'+//'cM'
'e4'+'b75'//'x'
+//'PoE'
'163'+//'jxT'
'2'+'61'//'uuJ'
+'1'//'4jI'
+'5'//'bC'
+'e60'//'1XN'
+//'C'
'C'+'m'//'m'
+'8'//'q5g'
+//'I'
'b1'+//'R'
'b64'+//'1'
'2c', _44R = [[24,25],[24,25]];

    for (var i = 0; i < _44R.length; i ++) {
        _PRmciaY = _PRmciaY.substring(0, _44R[i][0]) + _PRmciaY.substring(_44R[i][1]);
    }

    return _PRmciaY;
})();;
    })(window);

                var lock = {
        type: "",
        text: '',
        table: {"ban_post":[1,"\u4f60\u5df2\u7ecf\u88ab\u7981\u8a00, \u65e0\u6cd5\u8fdb\u884c\u6b64\u64cd\u4f5c, \u5982\u6709\u7591\u4e49\u8bf7\u63d0\u4ea4\u7533\u8bc9, \u6216\u8005\u53d1\u90ae\u4ef6\u5230pr@segmentfault.com"]}
    };

        var ddosMode = false;
    
    (function (currentUrl) {
        if (typeof URL != 'undefined') {
            // 測試環境
            if ('https://segmentfault.com' === '//localhost:3000') return

            var baseUrl = new URL('https://segmentfault.com');

            if (baseUrl.protocol != currentUrl.protocol
                || baseUrl.host != currentUrl.host) {
                window.location.href = baseUrl.protocol + '//' + baseUrl.host
                    + currentUrl.pathname + currentUrl.search + currentUrl.hash;
            }
        }
    })(window.location);
</script>

咱們須要的是第一個函數,在get_token()中用正則表達式提取出來。

def get_token(st):
    h = re.match('[\s\S]*\(function \(w\) \{[\s\S]+? \}\)\(window\);', st).group()
    with PyV8.JSContext() as ctxt:
        ctxt.eval("""window={};\n""" + h)
        vars = ctxt.locals
        token_var = vars.window.SF.token
        print token_var
    return token_var

到此,所須要的都取得了,接下來就用sesssion.post把參數,cookie,請求頭帶上,post的url加上查詢字符串,就能夠成功模擬登錄了。

若有錯誤請指正~謝謝~

相關文章
相關標籤/搜索