校長,我要上車——python模擬登錄熊貓TV

python的爬蟲例子真是多到有毒啊。這篇文章是在意識到這個問題之前寫的,不管如何還是先發上來把。

各大直播平台的彈幕爬蟲的例子已經很多了,但模擬登陸和彈幕發送似乎並沒有,我在這裡補充一個用python模擬登陸pandaTV的教程。

pandaTV的前端似乎是一股清流,給二次開發提供了很多便利,之前鼓搗彈幕爬蟲的時候就發現熊貓的彈幕比較其他的好抓,程序結構也清晰,模擬登錄同樣如此。

首先進行抓包分析。用chrome打開pandaTV,同時按F12打開chrome dev tool,選擇Network欄,勾選Preserve log,如圖所示。勾選Preserve log 是為了不讓抓包被刷新掉,因為登錄過程中有一次刷新,很容易就把關鍵的包刷掉了。

執行一次登錄命令,分析獲取的數據包。

一般來分析這些ajax包應該選中XHR來篩選,但我在XHR中試了多次,都沒找到和登錄相關的項目,後來是在other中找到的,不知道是不是網址是u.開頭的原因。在Other欄中,我發現了一個「u.panda.tv/ajax_login?」打頭的數據包,這濃眉大眼的,就是你了。為什麼我如此確定,因為只有這個包中包含了用戶名和密碼,一定是登錄用的。具體如下。

兩個塗黑的地方就是登錄名和密碼。

是不是直接將這調request提交過去就可以了呢,並不是,因為密碼是加密的,大家自己試試就知道了,如果原文提交過去會返回密碼錯誤。整個模擬登錄中,除了請求ajax,另一個難點就是構建AES加密後的密碼了。

我的查找方法是用sublime在下載的網頁文件中用關鍵詞全局搜索,畢竟不是搞前端的,只能笨辦法找了。不過最後還是找到了,關鍵代碼如下,可以看出密碼是AES加密方式。

function r(e, t) {n var n = $.Deferred(),n i = _.enc.Utf8.parse(e),n a = _.enc.Utf8.parse("995d1b5ebbac3761"),n r = _.AES.encrypt(t, i, {n iv: a,n mode: _.mode.CBC,n padding: _.pad.ZeroPaddingn }).toString();n return n.resolve(r),n nn }n

ase加密需要如下幾步:

  1. 獲取asekey,通過抓包和分析js可以知道通過請求這個網址獲得——"u.panda.tv/ajax_aeskey"
  2. AES需要的iv參數在js文件里可以找到——995d1b5ebbac3761
  3. AES的模式為MODE_CBC
  4. 字元串均需utf-8解碼為比特流

分析完後編輯代碼如下:

def aes_pwd(asekey, pwd):n if len(pwd) < 16:n pwd = pwd.encode(utf-8) + bx00 * (16 - len(pwd))n asekey = asekey or ""n iv = "995d1b5ebbac3761".encode("utf-8")n aes = AES.new(asekey, AES.MODE_CBC, iv)n aespwd = aes.encrypt(pwd)n aespwd64 = base64.b64encode(aespwd)n asepwdurl = quote(aespwd64)n return asepwdurln

AES加密後用base64將比特流轉為string,並且做url安全處理,就可以編輯為http請求了。

不過在實際的調試中,這一步經常出錯,用py算出來的密碼和抓包抓出來的密碼加密結果不一樣,上車失敗!搞了很久也不知道是什麼原因

這一部分代碼如下:

url = ("https://u.panda.tv/ajax_login?"n "_jp=jQuery1124011207815503733687_"n "{tick}&regionId=86&account={user}&password={pwd}"n "&rsms=&vc=&sign=&__plat=pc_web&"n "__guid=96554777.1564197678686254300.1489313051827.2598"n "&psrc=&refer=http%3A%2F%2Fwww.panda.tv%2F10015&"n "pdftsrc=%7B%7D&_={tick}")n url = url.format(n user=self.user, pwd=aespwdurl,n tick=int(time.time() * 1000))nn response = self.ses.get(url)n text = response.text.split(()[-1].split())[0]n textjson = json.loads(text)n

對於url這種長字元串而言,pythonic的寫法是用小括弧分行,大家可以看看這篇文章《Pythonic way to create a long multi-line string》。

總結以下流程就是:

  1. 請求"u.panda.tv/ajax_aeskey"獲得aeskey。
  2. AES加密用戶密碼。
  3. 編輯包含用戶名和密碼的url請求"u.panda.tv/ajax_login?"這個網址。

下面說說我對python爬蟲的看法吧,我其實也是從爬蟲入門的,但現在timeline上各種爬蟲教程也是看的想吐,絕大部分都是靜態的爬取,偶爾出現幾個需要請求ajax的。而真正的分散式,非同步的,或者一些工程化的分享幾乎沒有,不知道是不是因為有scrapy了,有BS了,大大降低了這一個圈子的下限(如果有這個圈子的話)。對這個問題我也沒太多看法,僅僅吐槽一下。

我的知乎專欄文章:zhuanlan.zhihu.com/p/26


推薦閱讀:

從零開始寫Python爬蟲 --- 3.1 Selenium模擬瀏覽器
Trip: 給Requests加上協程,一百份網路請求一份時間
如何在瀏覽器中高效抓包分析數據?
Scrapy爬圖片(一)
未來的旅遊的熱點是什麼?旅遊點評數據分析

TAG:Python | 爬虫 | 网络直播 |