2020版python實現模擬登錄知乎(包含自動過驗證碼) (上)

爲什麼要寫這篇呢,因爲最近想在知乎上採集一點數據(真的只是一點點~~!),但爬取的時候沒有登錄沒有cookie值你是抓取不到的,這裏可能有人會問,那直接從瀏覽器貼一下cookie值不就好了嘛,NO!NO!NO!,對於像我這樣脫離了低級趣味的人,是不削這種做法的,什麼叫懶匠精神? 這隻有到達了一定的境界纔會明白的,點一點手指,爬盡萬千信息……

就是這種感覺……,閒話不多說,我們來整理下思路,額,飄了一下突然發現不知道從哪裏下手了……不管那麼多,先打開知乎網站看下:https://www.zhihu.com/

嗯,觀察了一下,發現有幾種模式登錄,既然我們要做模擬自動登錄,當然是用密碼登錄,接着操作下,發現在登錄的過程中可能會出現2種形式的驗證碼:

1.中文驗證碼,找出倒立的文字

2.英文驗證碼

登錄這個過程基本上就是輸入賬號,密碼,驗證碼,然後提交,一般都是表單數據,我們打開開發者模式,跟蹤一下登錄接口的表單數據看下是什麼樣子的:

這是什麼鬼,正常情況下應該是正常的表單參數格式,基本上登錄就是根據這裏的參數,模擬配置然後請求,請求成功後獲得狀態和cookie,然後保存cookie就可以爲所欲爲了,but……從上看這裏的formdata貌似是一串加密的文本,這叫我從何入手,不管了先百度下,嘿嘿,革命的道路上永遠不缺乏先驅的人民英雄,發現已經有志同道合的朋友已經對這個做了分析,我就他們基礎上來實現吧,(爲了尊重先驅的勞動成果我沒有白嫖,我是一步一步跟蹤的~~!),來,繼續……打開調試器跟蹤一下JS:

看了下,像這類的基本都是用類似webpack打包壓縮了的,爲了調試JS代碼,我們打開:

然後看到JS都是混淆加密一堆一堆,腦殼痛,經常搞前端和爬蟲的老玩家應該知道怎麼格式化一下JS吧,算了,還是說一下,點這裏,用紅框了2次,怕你們看不到……

將近8萬行代碼……恕我的垃圾電腦有點帶不動,根據上面我們可以看到登錄的請求地址:

我們先複製下oauth/sign_in在js中搜索一下:

發現了這個接口,感覺應該沒錯,就是通過這裏提交的請求,爲了驗證這個接口的正確性,我們在這裏打一下斷點,然後在登錄界面亂輸入一下賬號再點一下登錄:

不錯,我們看下e,驚喜的發現這就是我在登錄頁面提交的賬號密碼,其它參數基本上都是固定的,除了timestamp和signature這個,timestamp這個簡單看格式就是13位的時間戳,signature應該是個加密串,是怎麼得到的這個參數呢,我們在JS搜索一下:signature,在app.js裏面感覺沒有找到想要的,我們在,(參考了下先驅的方法)這裏搜一下,發現:

這個是hmac加密,如果做過加密算法的應該瞭解過,這裏哈希算法是 sha1,密鑰爲 d1b964811afb40118a12068ff74a12f4,加密數據有四個,爲 clientId、grantType、timestamp 和 source,好了,通過用上面的參數加密就能得到signature,用python實現hmac加密我們後面再講,這裏我們的目的是先模擬生成formdata數據,怎麼得到formdata呢,接下來進行復雜的操作找出formdata的加密方法……,你可以通過跟蹤調用函數慢慢的一步一步去找這個加密的方法,這裏繼續參考革命先驅的方法,先按下CTRL+SHIFT+F,不出以外會彈出一個,輸入: encrypt, 因爲一般加密的方法裏都會用這個命名

果然下面搜到了有3個JS有這個方法名,我們先到main.app裏查看下:

找到了這個方法,不知道是不是正確的,我們來斷點調試下看看:

嗯,就是這個,站到先驅的肩膀上果然事半功倍,這個方法就是加密那一串表單數據的,那怎麼轉成python可用的呢,如果你用python來實現的話,我覺得沒有那個有這個閒功夫來研究,而且它的算法有可能經常改變,簡單的方法就是把這段JS方法考下來,然後用python的execjs的庫來調用JS得到結果,但首先我們得將JS複製下來,在瀏覽器中調用看下是否可行,從這裏開始:

向上找到這段JS:

我們將, function(module, exports, __webpack_require__) {……}這段JS複製下來,然後拷貝到一個JS文件中,然後去掉這個外殼,留下方法裏的內容,我們去掉包含exports的參數,3個地方要刪除,然後在下面直接加上參數調用:

在b的方法裏的參數就是要加密的字符串,放入到html頁面加載看一下打印結果:

奧利給,成功拿到了formdata加密後的值,距離成功不遠了,那怎麼在python中獲取到這個值呢,通過下面方法:

#coding:utf-8
import execjs

with open('zh_encrypt.js', 'r', encoding='utf8') as f:
    js = execjs.compile(f.read())
    form_data='client_id=c3cef7c66a1843f8b3a9e6a1e3160e20&grant_type=password&timestamp=1589184275397&source=com.zhihu.web&signature=70f1cd2be0bd83f773ce3a96c413ffaa9be07a30&username=%2B861243324324&password=34343&captcha=&lang=en&utm_source=&ref_source=other_https%3A%2F%2Fwww.zhihu.com%2Fsignin%3Fnext%3D%252F'
    result=js.call('b', form_data)
    print(result)

來,這裏我就不再一一的跟蹤下去了,根據革命先驅的方法這裏會遇到一些問題,對於一般的革命同胞來說,下面的問題可能是致命的,還好,我們繼續踏着革命先驅的肩膀前行,我把下面遇到的問題羅列下:

首先不出意外會出現這個js第412行(相對於我的文件來說):

  改成: ,因爲沒有瀏覽器,是沒有window之類的對象的

接着在運行一下會出現:

atob這個方法在python裏是沒有的,這個方法的用途就是解密通過base64加密後的字符串,先搜到atob的所在位置,將:

替換成:

革命先驅踩過的坑我們就不踩了,這裏的意思是在瀏覽器中base64加密的是 binary 編碼,這裏解密也要用 binary 編碼,來接着運行下,打印一下:

完美,至此模擬登錄知乎的第一步算是完成了,我們得到了加密後的formdata,再次感謝永不停步的革命先驅……

認真的時光總是過得這麼快……現在媽媽叫我回家喫飯了,後面接着會講怎樣實現登錄以及怎樣自動過驗證碼,感謝大家的耐心閱讀,爲什麼我這麼禮貌?(點不點贊無所謂啦,雖然我的心不是這麼想的~~!)

額……關於源碼呢,白嫖兄弟們可以給我留言,可以加公衆號回覆:知乎 

關注公衆號,實現不一樣的自我

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章