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