爬蟲遭遇狀態碼521陷阱 破解js加密cookie

最近接了個小單,遇到一個很頭疼的問題,返回的狀態碼無限521,在網上查閱了各種資料後,終於解決了問題返回200。

首先咱們先貼上網址:點擊打開鏈接

首先我們按照傳統的方法:

import requests
headers={
        'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36'
    }
req=requests.get('https://www.seebug.org/vuldb/ssvid-92666',headers=headers).status_code
print(req)

/usr/bin/python3.5 /home/pipidi/Spider/lianjia/lianjia/spiders/__init__.py
521

Process finished with exit code 0

可以說是毫無疑問 返回的是521 

下面貼出兩種解決辦法:

(1):直接複製request header

我們可以打開谷歌F12 找到其中的network 可以找到本網站地址的一個html 文件 直接複製所有他的頭部

import requests
from copyheaders import headers_raw_to_dict
header=b'''Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding:gzip, deflate, br
Accept-Language:zh,en-US;q=0.9,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:__jsluid=9536c75cdfa3e7e8c38d59bcbf4fc98b; csrftoken=YzAMB2QogF2YmzpruqWI5vdsfeH9PSx5; Hm_lvt_6b15558d6e6f640af728f65c4a5bf687=1519809319,1519880921; __jsl_clearance=1519885472.708|0|IQ9%2FbeQ6cfNLaEZUk2QzXhNEtL8%3D; Hm_lpvt_6b15558d6e6f640af728f65c4a5bf687=1519885477
Host:www.seebug.org
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36'''
req=requests.get('https://www.seebug.org/vuldb/ssvid-92666',headers=headers_raw_to_dict(header)).status_code
print(req)


200

Process finished with exit code 0

就可以返回200,但是在實際爬取的過程中,會發現他還是會時不時返回521,並且cookie 是餅乾屑具有時效性,不可能一直保存,所以方法1也不能說是最優解,下面我們來介紹一下方法2


(2):使用exejs執行js代碼返回cookie

首先,我們先用帶User-Agent的request去訪問這個網站,還是令人沮喪,返回的是521

import requests
header={'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36'}
req=requests.get('https://www.seebug.org/vuldb/ssvid-92666',headers=header).status_code
print(req)

521

Process finished with exit code 0

然後我們輸出他的內容 使用requests.get().text方法

哇!? 看看看這是啥? 懂一點前端的同學估計都頓悟出來了 這!就是JS代碼

查閱了很多大佬的博客,我發現 這是一種js加密cookie的手法

先訪問第一次訪問 返回521 並且給瀏覽器設置cookies 在第二次刷新的時候,你的瀏覽器就可以用設置上的cookie自動訪問了

但是咱的爬蟲不一樣,無法加載js,就一直卡在第一次訪問了

對此 我們的做法是讓Python運行js代碼,獲取cookies 並且加到下次訪問的頭部

行!就這麼做!

我們首先獲取返回的源代碼

def get_521_content():
    headers={
        'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36'
    }
    req=requests.get('https://www.seebug.org/vuldb/ssvid-92666',headers=headers)
    cookies=req.cookies

    cookies='; '.join(['='.join(item) for item in cookies.items()])
    txt_521=req.text
    txt_521=''.join(re.findall('<script>(.*?)</script>',txt_521))
    return (txt_521,cookies)

我們需要返回的分別是兩個 第一個是網頁的源代碼 第二個是後臺設置的cookie

然後我們對拿來的js代碼進行修改並且運行

我使用的Python 執行js的模塊是execjs ,在這裏我也不過多贅述

主要的修改是將eval 替換成return 讓他有返回值給咱看到

def fixed_fun(function):
    func_return=function.replace('eval','return')
    content=execjs.compile(func_return)
    evaled_func=content.call('f')
var l=function(){while(window._phantom||window.__phantomas){};var cd,dc='__jsl_clearance=1519886795.502|0|';cd=[((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![]))-~~~[]-~-~{}-~~~[]-~-~{}+[]+[]),[4],(-~~~[]+[]+[])+(-~~~[]+[]+[]),(-~~~[]+[]+[]),(-~~~[]+[]+[])+[(-~[]|-~-~{})+(2<<-~[])],(-~~~[]+[]+[])+[4],(2+[[], ~~!{}][~~{}]),((-~-~{})*[(-~-~{}<<-~[])]+[]+[]),((+[])+[[], ~~!{}][~~{}]),(-~~~[]+[]+[])+((+[])+[[], ~~!{}][~~{}]),((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![]))+[[], ~~!{}][~~{}]),(-~~~[]+[]+[])+(-~![]+((-~![]<<-~![])<<-~[])+[]+[[]][~~[]]),[[-~-~{}]*((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))],(-~~~[]+[]+[])+[[-~-~{}]*((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))],(-~~~[]+[]+[])+(2+[[], ~~!{}][~~{}]),(-~~~[]+[]+[])+((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![]))+[[], ~~!{}][~~{}]),[(-~[]|-~-~{})+(2<<-~[])],(-~![]+((-~![]<<-~![])<<-~[])+[]+[[]][~~[]])];for(var i=0;i<cd.length;i++){cd[i]=[([-~[]-~[]-~[]-~[]][-~[]]+[]+[]).charAt(-~[-~~~[]-~(-~((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![]))))]),'HE',(2+[[], ~~!{}][~~{}])+[-~[]/~~[]+[]+[]][0].charAt(7)+(((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))/~~[]+[]).charAt(-~-~{})+[!{}+[[]][~~!{}]][0].charAt((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))+(-~~~[]+[]+[]),(2+[[], ~~!{}][~~{}]),'SG','D',[{}+[[]][~~!{}]][0].charAt(8),((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![]))+[[], ~~!{}][~~{}]),'T',(((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))/~~[]+[]).charAt(-~-~{})+[-~[]/~~[]+[]+[]][0].charAt(7)+[!{}+[[]][~~!{}]][0].charAt((-~[]+[(-~![]<<-~![])]>>(-~![]<<-~![])))+[-~[]/~~[]+[]+[]][0].charAt(7),'%',(-~![]+((-~![]<<-~![])<<-~[])+[]+[[]][~~[]])+((+[])+[[], ~~!{}][~~{}]),[-~[]/~~[]+[]+[]][0].charAt(7),'k%','x','FE','SEA',[!-[]+[]+[]][0].charAt(-~-~{})][cd[i]]};cd=cd.join('');dc+=cd;setTimeout('location.href=location.href.replace(/[\?|&]captcha-challenge/,\'\')',1500);document.cookie=(dc+';Expires=Thu, 01-Mar-18 07:46:35 GMT;Path=/;');};if((function(){try{return !!window.addEventListener;}catch(e){return false;}})()){document.addEventListener('DOMContentLoaded',l,false);}else{document.attachEvent('onreadystatechange',l);}

我們可以看到代碼解密出來有變成了新的一串js代碼

我們可以吧他放到html文件裏面運行

我這裏是直接放到exejs中運行的,對代碼也進行了各種修改,最重要的是將document.cookie=()函數替換成return這樣就可以直接用print輸出返回的內容了,對於其他的修改,大家只要那裏報錯刪那裏就行。

mode_func=evaled_func.replace('while(window._phantom||window.__phantomas){};','').\
        replace('document.cookie=','return').replace(';if((function(){try{return !!window.addEventListener;}','').\
        replace("catch(e){return false;}})()){document.addEventListener('DOMContentLoaded',l,false);}",'').\
        replace("else{document.attachEvent('onreadystatechange',l);}",'').replace(r"setTimeout('location.href=location.href.replace(/[\?|&]captcha-challenge/,\'\')',1500);",'')
    content = execjs.compile(mode_func)
    cookies=content.call('l')
    __jsl_clearance=cookies.split(';')[0]
    return __jsl_clearance

經過了一堆修改之後,

if __name__ == '__main__':
    func=get_521_content()
    content=func[0]
    cookie_id=func[1]
    print(cookie_id)
    cookie_js=fixed_fun(func[0])
    print(cookie_js)

__jsl_clearance=1519886795.502|0|fysySG50HEux2yfs1Te%2FEOSEAyk%3D

我們會驚奇的發現,Python執行了js代碼,並且返回了一段cookie,他就是我們想要的!之後我們需要做的事就比較輕鬆了,只需要把後臺設置的__jsluid 和js設置的cookie __jsl_clearance一起加入我們的瀏覽器頭就可以正常訪問了

headers={
             'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36',
             'Cookie': cookie_id+';'+cookie_js}  #一定要和第一次訪問的user-agent一模一樣
    code=requests.get('https://www.seebug.org/vuldb/ssvid-92666',
                      headers=headers).text
    print(code)

需要注意的是 User-Agent 一定要和第一次訪問設置的一模一樣,不然照樣返回521,這也困擾了我很久

print(req.status_code)
print(len(req.text))


/usr/bin/python3.5 /home/pipidi/Spider/pass_521.py
200
64382
可以放肆的爬取了,如果遇到521,就調用第一個訪問的函數,運行js換新的cookie就行!


源碼  GitHub點擊打開鏈接




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