一、Python執行JS代碼--PyExecJS、PyV8、Js2Py
1.1、PyExecJS
PyExecJS的優點是您不需要照顧JavaScript環境。特別是,它可以在Windows環境中運行,而無需安裝額外的庫。PyExecJS的缺點之一是性能。PyExecJS通過文本傳達JavaScript運行時,並且運行緩慢。另一個缺點是它不完全支持運行時特定的功能。對於某些用例,PyV8可能是更好的選擇。安裝之前先安裝JS環境,Node.js安裝好了,就可以安裝接下來的庫了。
安裝:
pip3 install -i https://pypi.douban.com/simple PyExecJS
import execjs execjs.get().name # 查看調用的環境 'Node.js (V8)' ctx = execjs.compile(""" function add(x, y) { return x + y; } """) print(ctx.call("add", 1, 2)) #3 with open("enc.js", "r", encoding="utf-8") as f: #執行js文件 js = execjs.compile(f.read()) url = js.call("posturl") print(url) #http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=2019115032868
enc.js:
function posturl() { var s = new Date; url = "http://www.renren.com/ajaxLogin/login?1=1" + "&uniqueTimestamp=" + s.getFullYear() + s.getMonth() + s.getDay() + s.getHours() + s.getSeconds() + s.getUTCMilliseconds(); return url }
1.2、PyV8
PyV8是Google V8引擎的Python包裝器,它充當Python和JavaScript之間的橋梁?對象,並支持使用python腳本托管Google的v8引擎。和 `PyExecJS` 相比,這個庫很輕量,不需要額外裝 JS 環境,因為 V8 本身就是環境,同時也因為不需要啟動外部環境,執行速度很快。Python3 安裝不要使用pip,因為官方只支持 Python2,需要在這里下載對應系統的二進制文件, 然后解壓后將 PyV8.py 與 _PyV8.so (如so不是這個名字需要改成這樣) 兩文件復制到 Python 的 site-packages 目錄下,如 /usr/local/lib/python3.6/site-packages
。
下載地址:
https://github.com/emmetio/pyv8-binaries
import PyV8 # 注意大小寫 with PyV8.JSContext() as ctx: ctx.eval(""" function add(x, y) { return x + y; } """) print(ctx.locals.add(1, 2)) #3
1.3、Js2Py
將JavaScript轉換為Python代碼。Js2Py幾乎可以翻譯和執行任何JavaScript代碼。Js2Py用純python編寫,沒有任何依賴關系。基本上是純Python中JavaScript核心的實現。這種方式可以擺脫調用 JS 環境的瓶頸,但遺憾的是如果用於很長的混淆 JS 代碼,轉譯過來的大概率會報錯… 所以只建議先嘗試一下,如果報錯及時更換上面的庫。
安裝:
pip3 install -i https://pypi.douban.com/simple js2py
import js2py add = js2py.eval_js(""" function add(x, y) { return x + y; } """) print(add) # 可以看到大括號里已被轉譯 #'function add(x, y) { [python code] }' print(add(1, 2)) #3
import js2py # 使用下邊這個方法可以輸出轉譯后的代碼 # 可以保存到文件里,下次不需要再次轉譯 print(js2py.translate_js('var x = 1')) #打印結果: """ from js2py.pyjs import * # setting scope var = Scope( JS_BUILTINS ) set_global_object(var) # Code follows: var.registers(['x']) var.put('x', Js(1.0)) """
實戰技巧:
接下來就是定位目標網頁需要調用的 JS 函數,每個網站的寫法都大不相同。只要通過 Debug ,查看數據從請求,每一步都經過哪些 JS 函數,輸出什么樣的數據,就可以順藤摸瓜找到一些可疑的函數,然后將這些方法逐一復制出來,層層去除多余代碼,通過上面的庫傳入參數執行,看是否和目標網頁處理后的數據一致,就可以找到目標函數。