上班都快一周了,一直想更新,奈何小伙還沒有從假期的快樂中緩過來,今天終于耐下心來更新一小篇。摳一下某品會的JS代碼,接著使用摳取的JS代碼加密密碼進行登錄。友情提示:為避免不必要的糾紛,本文中所有網址都進行了一定隱藏。
私信小編01即可獲取大量Python/ target=_blank class=infotextkey>Python學習資料
目標
標題已經闡明了本文的目的:
- 密碼加密解密;
- 利用第一步加密方法加密后進行登錄;
- 完整代碼中嘗試了多賬號號批量登錄(由于篇幅有限,移動到了 閱讀原文 中);
摳出代碼
找到目標網站,進入登錄頁面(對各位來說都很easy):
像以往一樣輸入錯誤的賬號密碼,看看提交的數據,點擊登錄后,提交賬號密碼 url 如下:
繼續看 FormData ,如下圖:
圖中的 loginName 為你輸入的用戶名, password 為密碼,可以看出被加密了,如果你熟悉了各類JS加密方式,心里應該能大概確定這就是 MD5 加密結果。暫時不用管其它的四個參數,接下來無非就是把加密JS代碼摳出來,可以通過調用棧進去,也可以全局搜索 password 來定位JS文件,具體使用哪種方法就看各位看官的喜好了,我這里是從調用棧進去的(既然我們是在登錄,那就點帶有 login 字樣的js文件進去好了):
進來后你可以搜一下 password 關鍵字,應該馬上就能定位到想要的位置,定位的時候別忘了掛上一個斷點,就像下圖一樣:
一看加密方法名就是熟悉的 MD5 ,接下來的操作應該更加熟悉了,激活斷點(輸入賬號密碼,點擊登錄,前提是你掛上了斷點)。
點擊后就進入了加密方法里:
function md5(string, key, raw) {
if (!key) {
if (!raw)
return hex_md5(string);
return raw_md5(string)
}
if (!raw)
return hex_hmac_md5(key, string);
return raw_hmac_md5(key, string)
}
可以看出md5方法一共有三個參數,第一個 striing 即為密碼, key 和 raw 是 undefined。接下笨一點的辦法就是一步一步運行,把跳轉的所有代碼都扣下來,如果是剛開始學習摳代碼,這個方法能增加很多調試”感覺”,慢慢摳得越來越順手。取巧一點的無非就是找到大括號:
一直往上找到,應該馬上就能找到正括號:
這樣里面的代碼其實就是本次要摳的代碼,但是要使用 python 調用,還要進行一點改動。本次要摳的加密代碼其實很簡單,畢竟只是 md5 。經過稍微改寫后,我們嘗試使用python里 execjs 庫執行:
成功運行出結果,摳取完畢。
登錄
FormData
通過上一節,我們已經可以得到加密后的密碼,既然要登錄,那就要回到 FormData 中,看看幾個參數的含義與取值,經過一番測試,總結如下,感興趣的也可以自己去試一下。
參數取值loginName用戶名password加密后的密碼remUser是否記住用戶名(0或者1)whereFrom可為空captchaId驗證碼(可為空)captchaTicket可為空
Cookies
現在的登錄都需要攜帶 cookies ,看一下本站登錄時候的Cookies:
看起來很多,但是經過測試并不需要全部攜帶,cookies應該是服務端產生的,所以還是老老實實帶上吧,沒有捷徑。經過粗略測試,攜帶以下幾個即可登錄:
cookies = {
' mars_pid': '你的',
' cps': '你的',
' mars_sid': '你的',
'times_XXXXX': '你的',
' VipRUID': '你的',
' VipRNAME': '',
' VipDegree': '你的',
' user_class': '你的',
' VipCI_te': '你的',
'mars_cid': '你的'
}
有興趣的可以繼續試試這里面還有沒有可以不用攜帶的。
Header
不管是登錄還是爬取某個網頁,請求頭是絕對繞不過的,現在一起看看本站的請求頭都有哪些:
好家伙,各種都有,不過大家不用擔心,經過測試在本文實際爬取過程中只用攜帶 user-agent,平時的爬取過程中,有些可能會檢查上一個網頁是在哪里,即要攜帶 referer ,還有 origin 和 host 也是可能會攜帶的。
正式登錄
本次登錄的幾個要點在前面應該算已經闡述清楚了,現在要做的無非就是把 FormData 里的數據 post 到 login_url 。
flowchat
st=>start: 開始
e=>end: 結束
op0=>operation: 輸入賬號密碼
op1=>operation: 執行js代碼加密密碼
op=>operation: 組裝formdata
op2=>operation: 把formdata post到登錄url
op3=>operation: 分析返回
st->op0->op1->op->op2->op3->e
好了,流程知道了開始寫代碼,友情提示: 由于可能引起一些不必要的紛爭,代碼中的url和cookies值都隱藏了,大家按照自己的添加即可 。創建了一個 VipLogin 類,下面是部分模塊的代碼。
執行js代碼
@property
def exec_js(self):
"""
你自己的js路徑
:return:
"""
with open('..//js//weipinhui.js', encoding='utf-8') as f:
weipinhui = f.read()
js = execjs.compile(weipinhui)
return js
加密密碼
def get_pwd(self,password):
key = ""
raw = ""
pwd = self.js.call('md5', password, key, raw)
logger.info("加密結果為:{}".format(pwd))
return pwd
用戶名加密
def encrypt_phone(self,phone):
return phone[:3]+"*"*5+phone[-3:]
提交數據
def login(self,user,passwd):
if not user.isdigit or len(user) != 11:
logger.error("目前僅支持手機號方式登錄:{}".format(user))
return False
session = requests.Session()
vip_name = self.encrypt_phone(user)
times_key = "times_"+user
data = {
"loginName": user,
"password": passwd,
"remUser": "0",
"whereFrom":"",
"captchaId":"" ,
"captchaTicket":"",
}
ck_dict = {
' mars_pid': '你的',
' cps': '你的',
' mars_sid': '你的',
times_key: '你的',
' VipRUID': '你的',
' VipRNAME': vip_name,
' VipDegree': '你的',
' user_class': '你的',
' VipCI_te': '你的',
'mars_cid': '你的'
}
requests.utils.add_dict_to_cookiejar(session.cookies,ck_dict)
resp = session.post(self.login_url,headers=self.headers,data=data,verify=False)
ret = json.loads(resp.text)
logger.info("賬號{}返回結果為:{}".format(self._encrypt_phone(user),ret))
if ret.get("result","") == "success":
return True
return False
登錄結果
登錄成功的標志為 'result': 'success ‘如下:
{
'result': 'success',
'errorCode': 0,
'data': {
'redirectUrl': 'https://www.xxx.com',
'captchaFlowData': None,
'extend': None,
'bindMobile': True,
'illegalState': False
},
'redirectUrl': 'https://www.xxx.com'
}