最全總結!聊聊 Python 呼叫 JS 的幾種方式
1. 前言
很多人學習python,不知道從何學起。
很多人學習python,掌握了基本語法過後,不知道在哪裡尋找案例上手。
很多已經做案例的人,卻不知道如何去學習更加高深的知識。
那麼針對這三類人,我給大家提供一個好的學習平臺,免費領取視訊教程,電子書籍,以及課程的原始碼!
QQ群:1097524789
日常 Web 端爬蟲過程中,經常會遇到引數被加密的場景,因此,我們需要分析網頁原始碼
通過調式,一層層剝離出關鍵的 JS 程式碼,使用 Python 去執行這段程式碼,得出引數加密前後的Python實現
本文將聊聊利用Python 呼叫 JS 的4種方式
2. 準備
以一段簡單的JS 指令碼為例,將程式碼寫入到檔案中
//norm.js
//計算兩個數的和
functionadd(num1,num2){
returnnum1+num2;
}
其中,定義了一個方法,計算兩個數的和
3. 方式一:PyExecJS
PyExecJS 是使用最多的一種方式,底層實現方式是:在本地 JS 環境下執行 JS 程式碼
支援的 JS 環境包含:Node.js、PyV8、PhantomJS、Nashorn 等
首先,我們需要安裝依賴包PyExecJS
//py_exec_js_demo.py
//安裝依賴
pip3installPyExecJS
然後,從 JS 檔案中讀取原始碼
defjs_from_file(file_name): """ 讀取js檔案 :return: """ withopen(file_name,'r',encoding='UTF-8')asfile: result=file.read() returnresult
最後,使用 execjs 類的compile()方法編譯載入上面的 JS 字串,返回一個上下文物件
importexecjs
fromjs_codeimport*
#編譯載入js字串
context1=execjs.compile(js_from_file('./norm.js'))
最後,呼叫上下文物件的call()方法執行 JS 方法
其中,引數包含:JS 程式碼被調的方法名、對應方法的傳入引數
#呼叫js程式碼中的add()方法,引數為2和3
#方法名:add
#引數:2和3
result1=context1.call("add",2,3)
print(result1)
需要注意的,由於PyExecJS執行在本地 JS 環境下,使用之前會啟動 JS 環境,最終導致執行速度會偏慢
更多功能可以參考:
https://github.com/doloopwhile/PyExecJS
4. 方式二:js2py
js2py作為一個純 Python 實現的 JS 直譯器,可以完全脫離 JS 環境,直接將 JS 程式碼轉換為 Python 程式碼
首先,安裝依賴庫
#安裝依賴庫
pip3installjs2py
然後使用 js2py 中的EvalJs()方法生成一個上下文物件
#使用獲取上下js2py生成一個上下文環境
context=js2py.EvalJs()
接著利用上下文物件執行 JS 指令碼,轉換為Python 程式碼
#執行整段JS程式碼
context.execute(js_content)
最後,利用上下文呼叫 JS 中的方法,並制定輸入引數即可
#使用上下文context呼叫具體的函式
#函式名:add
#引數:1,2
result=context.add(1,2)
print(result)
需要注意是,如果 JS 是很長的混淆程式碼,轉換為 Python 的過程可能會報錯
更多功能可以參考:
https://github.com/PiotrDabkowski/Js2Py
5. 方式三:Node.js
實際上是使用 Python 的os.popen執行 node 命令,執行 JS 指令碼
首先,確保本地已經安裝了 Node.js 環境
修改 JS 指令碼,新增一個匯出函式 init ,方便內部函式被呼叫
//計算兩個數的和
functionadd(num1,num2){
returnnum1+num2;
}
//新增一個匯出函式(node方式)
module.exports.init=function(arg1,arg2){
//呼叫函式,並返回
console.log(add(arg1,arg2));
};
然後,將呼叫 JS方法的命令組成一個字串
#組成呼叫js的命令
# node命令:node -e
cmd='node-e"require(\\"%s\\").init(%s,%s)"'%('./norm',3,5)
最後,通過 os.popen 執行命令即可
pipeline=os.popen(cmd)
#讀取結果
result=pipeline.read()
print('結果是:',result)
6. 方式四:PyV8
PyV8 是 Google將 Chrome V8引擎用 Python 封裝的依賴庫
它不依賴本地 JS 環境,執行速度很快
importPyV8
fromjs_codeimportjs_from_file
withPyV8.JSContext()asctx:
ctx.eval(js_from_file('./norm.js'))
#呼叫js函式,指定引數
ctx.locals.add(1,2)
但是經過反覆測試發現,MAC 和 PC 在 Python3 環境下,使用 PyV8 會報各種奇怪的問題,所以不推薦使用!
更多功能可以參考:
https://github.com/emmetio/pyv8-binaries
7. 最後
上面總結了 Python 呼叫 JS 的 4 種方式
實際爬蟲專案中,一般會先使用 node 命令進行一次測試,確保沒問題後,再使用前 3 種方式的任意一種進行 Python 改寫。