python爬蟲-模擬微博登錄功能
微博模擬登錄
這是本次爬取的網(wǎng)址:https://weibo.com/
一、請求分析
找到登錄的位置,填寫用戶名密碼進行登錄操作
看看這次請求響應(yīng)的數(shù)據(jù)是什么
這是響應(yīng)得到的數(shù)據(jù),保存下來
exectime: 8 nonce: "HW9VSX" pcid: "gz-4ede4c6269a09f5b7a6490f790b4aa944eec" pubkey: "EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443" retcode: 0 rsakv: "1330428213" servertime: 1568257059
繼續(xù)完善登錄操作,輸入密碼,點擊登錄按鈕
經(jīng)過分析呢,發(fā)現(xiàn)變化的參數(shù)就是sp
,nonce
,servetime
。servetime
就是當前的時間戳,我們只需找到其他兩個參數(shù)的生成方法就好了。對了su
這個參數(shù)是通過base64加密生成的
二、找到sp
,nonce
的加密方式
這次就不通過search關(guān)鍵字去找加密位置了
找到調(diào)用函數(shù)的位置,打上斷點,再進行登錄操作
經(jīng)過js代碼流程調(diào)試分析,最終我們找到了加密的位置
簡單介紹下怎么調(diào)試js代碼
找到sp
,nonce
的位置,通過python代碼去實現(xiàn)它的加密方式
sp
它是通過rsa加密方式,加密生成的。rsa的具體用法可以通過百度找到。或者通過sha1加密生成。至于me.rsaPubkey
他怎么得到的,他就是我們還沒有點擊登錄前,就發(fā)了一個請求,那個請求的響應(yīng)數(shù)據(jù)就有它。如果你測試的次數(shù)多了的話,會發(fā)現(xiàn)這個值它是固定下來的。所以我們也可以直接去用,不用請求獲取。
nonce
:它呢也出現(xiàn)過在未點擊登錄前的那個請求響應(yīng)的數(shù)據(jù)中,但是呢,我們點了幾次登錄,都未發(fā)現(xiàn)這個請求了。nonce
的值每次還不一樣。所以它肯定是本地js文件的某個函數(shù)生成,不用請求服務(wù)器獲取。我們在這里找到了nonce的生成函數(shù)
import random import rsa import hashlib from binascii import b2a_hex def get_nonce(n): result = "" random_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" for i in range(n): index = random.randint(0, len(random_str) - 1) result += random_str[index] return result def get_sp_rsa(password, servertime, nonce): key = "EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443" pubkey = rsa.PublicKey(int(key, 16), int("10001", 16)) res = rsa.encrypt(bytes("" + "\t".join([servertime, nonce]) + "\n" + password,encoding="utf-8"), pubkey) return b2a_hex(res) def get_sp_sha1(password, servertime, nonce): res = hashlib.sha1(bytes("" + hashlib.sha1(bytes(hashlib.sha1(bytes(password, encoding="utf-8")).hexdigest(),encoding="utf-8")).hexdigest() + servertime + nonce,encoding="utf-8")).hexdigest() return res
三、響應(yīng)數(shù)據(jù)
請求參數(shù)分析的差不多了,這次輸入正確的用戶名,密碼。查看響應(yīng)的數(shù)據(jù)的是什么。
打開fiddler,然后退出當前賬號,重新進行登錄操作。fiddler上面就會出現(xiàn)很多請求。找到需要的請求,看看響應(yīng)內(nèi)容
這樣做,每個響應(yīng)都會set-cookie。所以照著上面的流程實現(xiàn),標識登錄的cookie肯定能得到。之后的話,只要帶上這個cookie去做其他操作就行了。
最后附上代碼
import requests, random, time, rsa, hashlib, base64, re, json from binascii import b2a_hex class WeiBo: def __init__(self): self.session = requests.Session() self.headers = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" } def login(self, account, password): api = "https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)" nonce = self._get_nonce() servertime = self._get_now_time() sp = self._get_sp_rsa(password, servertime, nonce) su = self._get_su(account) data = { "entry": "weibo", "gateway": "1", "from": "", "savestate": "7", "qrcode_flag": "false", "useticket": "1", "pagerefer": "https://login.sina.com.cn/crossdomain2.php?action=logout&r=https%3A%2F%2Fpassport.weibo.com%2Fwbsso%2Flogout%3Fr%3Dhttps%253A%252F%252Fweibo.com%26returntype%3D1", "vsnf": "1", "su": su, "service": "miniblog", "servertime": servertime, "nonce": nonce, "pwencode": "rsa2", "rsakv": "1330428213", "sp": sp, "sr": "1920*1080", "encoding": "UTF - 8", "prelt": "149", "url": "https://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack", "returntype": "META", } headers = self.headers.copy() headers.update({ "Host": "login.sina.com.cn", "Origin": "https://weibo.com", "Referer": "https://weibo.com/" }) response = self.session.post(api, headers=headers, data=data, allow_redirects=False) search_result = self._re_search("location.replace\(\"(.*?)\"", response.text) redirct_url = search_result and search_result.group(1) if not redirct_url: raise Exception("重定向url獲取失敗") response = self.session.get(redirct_url, headers=headers.update({ "Referer": "https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)" }), allow_redirects=False) search_result = self._re_search('"arrURL":(.*?)}', response.text) redirct_urls = search_result and search_result.group(1) if not redirct_urls: raise Exception("重定向url獲取失敗") redirct_url_list = json.loads(redirct_urls) userId = "" for url in redirct_url_list: response = self.session.get(url, headers=self.headers) if url.startswith("https://passport.weibo.com/wbsso/login"): userId = self._re_search('"uniqueid":"(.*?)"', response.text).group(1) if not userId: raise Exception("userId獲取失敗") user_details_url = "https://weibo.com/u/{}/home?wvr=5&lf=reg".format(userId) response = self.session.get(user_details_url, headers={ "Referer": "https://weibo.com/", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" }) if self._re_search(userId, response.text): print("登錄成功") print(self.session.cookies) else: print("登錄失敗") def _get_nonce(self): nonce = "" random_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" for i in range(5): index = random.randint(0, len(random_str) - 1) nonce += random_str[index] return nonce def _get_now_time(self): return str(int(time.time())) def _get_sp_rsa(self, password, servertime, nonce): key = "EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443" pubkey = rsa.PublicKey(int(key, 16), int("10001", 16)) res = rsa.encrypt(bytes("" + "\t".join([servertime, nonce]) + "\n" + password, encoding="utf-8"), pubkey) return b2a_hex(res) def _get_sp_sha1(self, password, servertime, nonce): res = hashlib.sha1(bytes("" + hashlib.sha1(bytes(hashlib.sha1(bytes(password, encoding="utf-8")).hexdigest(), encoding="utf-8")).hexdigest() + servertime + nonce, encoding="utf-8")).hexdigest() return res def _get_su(self, account): return str(base64.b64encode(bytes(account, encoding="utf-8")), encoding="utf-8") def _re_search(self, pattern, html): return re.search(pattern, html, re.S) def test(self): self.login("18716758777", "123456") if __name__ == '__main__': wb = WeiBo() wb.test()
總結(jié)
以上所述是小編給大家介紹的python爬蟲-模擬微博登錄功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
相關(guān)文章
Python實現(xiàn)多格式文本轉(zhuǎn)為word
在現(xiàn)代工作中,我們常常需要處理不同格式的文件,其中Word文檔是最為常見的一種,本文主要介紹了如何使用Python創(chuàng)建一個全能的文件處理工具,能夠?qū)⒍喾N格式的文件轉(zhuǎn)換為Word文檔,需要的可以參考下2023-11-11使用python如何將數(shù)據(jù)集劃分為訓(xùn)練集、驗證集和測試集
這篇文章主要介紹了使用python如何將數(shù)據(jù)集劃分為訓(xùn)練集、驗證集和測試集問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09python 根據(jù)正則表達式提取指定的內(nèi)容實例詳解
這篇文章主要介紹了python 根據(jù)正則表達式提取指定的內(nèi)容實例詳解的相關(guān)資料,需要的朋友可以參考下2016-12-12python中l(wèi)ambda函數(shù) list comprehension 和 zip函數(shù)使用指南
這篇文章主要介紹了python中l(wèi)ambda函數(shù) list comprehension 和 zip函數(shù)使用方法,非常的實用,有需要的朋友可以參考下2014-09-09Python利用re模塊實現(xiàn)簡易分詞(tokenization)
分詞(tokenization)任務(wù)是Python字符串處理中最為常見任務(wù)了。本文將利用re模塊實現(xiàn)簡易tokenizer,文中的示例代碼講解詳細,需要的可以參考一下2022-04-04