javascript
点击时候确定某个元素 js_某空气质量监测平台 JS反爬
目標(biāo):中國空氣質(zhì)量在線監(jiān)測分析平臺|城市分析 參考CSDN中文章,記錄一下學(xué)習(xí)過程
通過切換城市,頁面數(shù)據(jù)是通過 Ajax 加載的,數(shù)據(jù)接口:https://www.aqistudy.cn/apinew/aqistudyapi.php
請求的POST Data、返回的數(shù)據(jù)都被加密了
分析網(wǎng)站接口的加密邏輯
js加密的一般處理思路:
- 加密url或某個post data參數(shù)時,可以全局搜索對應(yīng)的參數(shù)名或者值,確定js函數(shù)
- 整個post data加密或無法搜索到參數(shù),可通過元素的事件監(jiān)聽,確定js函數(shù)
1. 這里搜索參數(shù)名 d 顯然不現(xiàn)實,當(dāng)我們點(diǎn)擊切換城市或者搜索按鈕之后,后臺便會發(fā)出 Ajax 請求,說明這個點(diǎn)擊動作是被監(jiān)聽的,所以我們可以找一下這個點(diǎn)擊事件對應(yīng)的處理代碼在哪里,這里可以借助于 Firefox 來實現(xiàn),它可以分析頁面某個元素的綁定事件以及定位到具體的代碼在哪一行
切換城市or點(diǎn)擊搜索
2.發(fā)現(xiàn)綁定的 click 事件調(diào)用了 getData() 函數(shù),顯然是獲取數(shù)據(jù)的js,搜索這個函數(shù)
在 city_detail.html 的第 463 行就找到了這個函數(shù)的聲明
3.發(fā)現(xiàn)它又調(diào)用了 getAQIData() 和 getWeatherData() ,這兩個方法的聲明就緊挨在下面,再進(jìn)一步分析發(fā)現(xiàn)這兩個方法都調(diào)用了 getServerData() 這個方法,并傳遞了參數(shù) method、param ,還有一個回調(diào)函數(shù)很明顯是對返回數(shù)據(jù)進(jìn)行處理的,這說明 Ajax 請求就是由這個 getServerData() 方法發(fā)起的,如圖所示:
4.繼續(xù)搜索這個函數(shù) getServerData()
city_detail.html 中的是上面兩個方法調(diào)用了 getServerData() ,這個文件里面并沒有g(shù)etServerData() 的聲明
貌似在 https://www.aqistudy.cn/js/jquery-1.8.0.min.js?v=1.2 中 右鍵 選擇在Sources中打開,繼續(xù)搜
果然找到了,發(fā)現(xiàn)這里經(jīng)過 JavaScript 混淆加密了,這個方法名后面怎么直接跟了一些奇怪的字符串,而且不符合一般的 JavaScript 寫法,而且這行代碼的開頭為eval(function(p,a,c,k,e,d)這種形式。
5.利用在線反混淆網(wǎng)站(http://www.bm8.com.cn/jsConfusion/)將 jquery-1.8.0.min.js 中這行 eval 開頭的混淆后的 JavaScript 代碼復(fù)制一下,然后粘貼到這個網(wǎng)站中進(jìn)行反混淆,就可以看到正常的 JavaScript 代碼了,搜索一下就可以找到 getServerData() 方法了,可以看到這個方法確實發(fā)出了一個 Ajax 請求,請求了Ajax 加載的數(shù)據(jù)接口:
在這里發(fā)現(xiàn)了一個getParam()方法:它接受了 method 和 object 參數(shù),然后返回得到的 param 結(jié)果就作為加密后的 POST Data,也就是d:后面的那一堆字符串
這里面還有一個decodeData()方法:對服務(wù)器傳回的數(shù)據(jù)進(jìn)行解密
6.還是在這一堆反混淆代碼中,緊挨著上面代碼找到了getParam()和decodeData()
其中 POST Data 的加密過程是 Base64 + AES 加密,Response Data 的解密是 AES + DES + Base64 解密
代碼
PyExecJS 是一個可以使用 Python 來模擬運(yùn)行 JavaScript 的庫
pip install PyExecJS還需安裝JS運(yùn)行環(huán)境(推薦安裝 Node.js )
Go~
不需要用 Python 重寫一遍 JavaScript,直接用 Python 來模擬運(yùn)行 JavaScript 就好
將剛才反混淆的 JavaScript 保存成一個文件,叫做 encryption.js,然后用 PyExecJS 模擬運(yùn)行相關(guān)的方法即可。
首先我們來實現(xiàn)加密過程,這里 getServerData() 方法其實已經(jīng)幫我們實現(xiàn)好了,并實現(xiàn)了 Ajax 請求,但這個方法里面有獲取 Storage 的方法,Node.js 不適用,所以這里不用它也別管他, 添加一個 getEncryptedData() 方法實現(xiàn)加密,在 encryption.js 最后面加入一段代碼,實現(xiàn)如下方法:
function getEncryptedData(method, city, type, startTime, endTime) {var param = {};param.city = city;param.type = type;param.startTime = startTime;param.endTime = endTime;return getParam(method, param); }用于傳遞數(shù)據(jù),調(diào)用參數(shù)加密函數(shù)
接下來用python模擬執(zhí)行這些方法即可:
import execjs import json import requests# Init environment # 通過 execjs(即 PyExecJS)的 get() 方法聲明一個運(yùn)行環(huán)境 node = execjs.get()# Params # 換成'GETCITYWEATHER'獲取溫度,風(fēng)向等數(shù)據(jù) method = 'GETDETAIL' city = '重慶' type = 'HOUR' start_time = '2019-09-06 00:00:00' end_time = '2019-09-06 12:00:00'# Compile javascript file = 'encryption.js' # 調(diào)用 compile() 方法來執(zhí)行剛才保存下來的加密庫 encryption.js,執(zhí)行一遍才能調(diào)用 with open(file, encoding=('utf-8')) as f:ctx = node.compile(f.read())# Get params # 調(diào)用一下 JavaScript 中的 getEncryptedData() 方法即可實現(xiàn)加密 # 通過 eval() 方法來模擬執(zhí)行,得到的結(jié)果賦值為 params,這個就是 POST Data 的加密數(shù)據(jù) js = 'getEncryptedData("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time) params = ctx.eval(js)# Get encrypted response text url = 'https://www.aqistudy.cn/apinew/aqistudyapi.php' response = requests.post(url, data={'d': params})# Decode data # 調(diào)用一下 JavaScript 中的 decodeData() 方法即可實現(xiàn)解密 js = 'decodeData("{0}")'.format(response.text) decrypted_data = ctx.eval(js)data = json.loads(decrypted_data) res = data.get('result').get('data').get('rows') for i in res:print(i)method = 'GETDETAIL' 可以獲得aqi(空氣質(zhì)量指數(shù)),pm2.5 等數(shù)據(jù)
換成'GETCITYWEATHER' 可以獲取溫度,風(fēng)向等數(shù)據(jù)
Github:https://github.com/Ingram7/AQI
總結(jié)
以上是生活随笔為你收集整理的点击时候确定某个元素 js_某空气质量监测平台 JS反爬的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql子分区多少层_MYSQL子分区
- 下一篇: jsonobject修改key的值_JS