python基础之调用JS函数
调用方式一:execjs
安装execjs: pip install PyExecJS
1. 以字符串方式调用
call_js.py
import execjs js_function = """ function s(j,r){var a=[];var p=[];var o="";var v=j.length;for(var q=0;q<256;q++){a[q]=j.substr((q%v),1).charCodeAt(0);p[q]=q}for(var u=q=0;q<256;q++){u=(u+p[q]+a[q])%256;var t=p[q];p[q]=p[u];p[u]=t}for(var i=u=q=0;q<r.length;q++){i=(i+1)%256;u=(u+p[i])%256;var t=p[i];p[i]=p[u];p[u]=t;k=p[((p[i]+p[u])%256)];o+=String.fromCharCode(r.charCodeAt(q)^k)}return o}; """ encode_value = execjs.compile(js_function).call("s", r, l) print(encode_value)
2. 以文本方式调用
js_function.js
function s(j, r) { var a = []; var p = []; var o = ""; var v = j.length; for (var q = 0; q < 256; q++) { a[q] = j.substr((q % v), 1).charCodeAt(0); p[q] = q } for (var u = q = 0; q < 256; q++) { u = (u + p[q] + a[q]) % 256; var t = p[q]; p[q] = p[u]; p[u] = t } for (var i = u = q = 0; q < r.length; q++) { i = (i + 1) % 256; u = (u + p[i]) % 256; var t = p[i]; p[i] = p[u]; p[u] = t; k = p[((p[i] + p[u]) % 256)]; o += String.fromCharCode(r.charCodeAt(q) ^ k) } return o }
call_js.py
import execjs def _get_runntime(): phantom = execjs.get() with open('js_function.js', 'r') as f: source = f.read() return phantom.compile(source) encode_value = _get_runntime().call('s', r, l) print(encode_value)
调用方式2:js2py
安装js2py: pip install js2py
call_js.py
import js2py js_function = """ function s(j,r){var a=[];var p=[];var o="";var v=j.length;for(var q=0;q<256;q++){a[q]=j.substr((q%v),1).charCodeAt(0);p[q]=q}for(var u=q=0;q<256;q++){u=(u+p[q]+a[q])%256;var t=p[q];p[q]=p[u];p[u]=t}for(var i=u=q=0;q<r.length;q++){i=(i+1)%256;u=(u+p[i])%256;var t=p[i];p[i]=p[u];p[u]=t;k=p[((p[i]+p[u])%256)];o+=String.fromCharCode(r.charCodeAt(q)^k)}return o}; """ encode_value = js2py.eval_js(js_function)(r, l) print(encode_value)
对这两个方式目前还存在一点疑惑没解决
call_js.py
#!/usr/bin/env python # _*_ coding: UTF-8 _*_ """================================================= @Project -> File : call_js.py @IDE : PyCharm @Author : zihan @Date : 2022/1/3 9:53 @Desc : =================================================""" import execjs import js2py js_function = """ function s(j,r){var a=[];var p=[];var o="";var v=j.length;for(var q=0;q<256;q++){a[q]=j.substr((q%v),1).charCodeAt(0);p[q]=q}for(var u=q=0;q<256;q++){u=(u+p[q]+a[q])%256;var t=p[q];p[q]=p[u];p[u]=t}for(var i=u=q=0;q<r.length;q++){i=(i+1)%256;u=(u+p[i])%256;var t=p[i];p[i]=p[u];p[u]=t;k=p[((p[i]+p[u])%256)];o+=String.fromCharCode(r.charCodeAt(q)^k)}return o}; """ def _get_runntime(): phantom = execjs.get() with open('js_function.js', 'r') as f: source = f.read() return phantom.compile(source) def get_s(r, l): encode_value = _get_runntime().call('s', r, l) print(encode_value) encode_value = execjs.compile(js_function).call("s", r, l) print(encode_value) encode_value = js2py.eval_js(js_function)(r, l) print(encode_value) #want: encode_value = 'ú\x1FBoÁ\n\x1Fn¢\x0Fa\x1EQ\x01\x92òVx¯o¤h9Õ%G¶\x89ÄQâ*7EÁö.\x7FÒÓ' return _get_runntime().call('base64Encode', encode_value) def main(): # sign3 f = 'e8c7d729eea7b54551aa594f942decbe' # sign1 l = '84dcadc608ddd0d635e81b35821a0a3a7b7e31b4' sign = get_s(f, l) # want: +h9Cb8EKH26iD2EeUQGS8lZ4r2+kaDnVJUe2icRR4io3RcH2Ln/S0w== print(sign) if __name__ == '__main__': main()
运行结果
煤Bo脕 n垄aQ聮貌Vx炉o陇h9脮%G露聣脛Q芒*7E脕枚.脪脫 煤Bo脕 n垄aQ聮貌Vx炉o陇h9脮%G露聣脛Q芒*7E脕枚.脪脫 úBoÁ n¢aQòVx¯o¤h9Õ%G¶ÄQâ*7EÁö.ÒÓ +h9Cb8EKH26iD2EeUQGS8lZ4r2+kaDnVJUe2icRR4io3RcH2Ln/S0w==
可以看到使用js2py和execjs运行同一个函数的结果并不相同,当前状态是js2py得到的结果是想要的,不过目前并不清楚其中的区别,可能得继续研究。
进一步研究发现,原来之前电脑安装了Node.js,导致execjs的默认JS环境变成了Node.js (V8),默认Windows下的JS环境是JScript。所以只需要在get时指定execjs的环境为Windows默认环境就行了。
call_js.py
#!/usr/bin/env python # _*_ coding: UTF-8 _*_ """================================================= @Project -> File : call_js.py @IDE : PyCharm @Author : zihan @Date : 2022/1/3 9:53 @Desc : =================================================""" import execjs import js2py js_function = """ function s(j,r){var a=[];var p=[];var o="";var v=j.length;for(var q=0;q<256;q++){a[q]=j.substr((q%v),1).charCodeAt(0);p[q]=q}for(var u=q=0;q<256;q++){u=(u+p[q]+a[q])%256;var t=p[q];p[q]=p[u];p[u]=t}for(var i=u=q=0;q<r.length;q++){i=(i+1)%256;u=(u+p[i])%256;var t=p[i];p[i]=p[u];p[u]=t;k=p[((p[i]+p[u])%256)];o+=String.fromCharCode(r.charCodeAt(q)^k)}return o}; """ def _get_runntime(): phantom = execjs.get() print(phantom.name) phantom = execjs.get(execjs.runtime_names.JScript) print(phantom.name) with open('js_function.js', 'r') as f: source = f.read() return phantom.compile(source) def get_s(r, l): encode_value = _get_runntime().call('s', r, l) print(encode_value) encode_value = execjs.get(execjs.runtime_names.JScript).compile(js_function).call("s", r, l) print(encode_value) # encode_value = js2py.eval_js(js_function)(r, l) # print(encode_value) #want: encode_value = 'ú\x1FBoÁ\n\x1Fn¢\x0Fa\x1EQ\x01\x92òVx¯o¤h9Õ%G¶\x89ÄQâ*7EÁö.\x7FÒÓ' return _get_runntime().call('base64Encode', encode_value) def main(): # sign3 f = 'e8c7d729eea7b54551aa594f942decbe' # sign1 l = '84dcadc608ddd0d635e81b35821a0a3a7b7e31b4' sign = get_s(f, l) # want: +h9Cb8EKH26iD2EeUQGS8lZ4r2+kaDnVJUe2icRR4io3RcH2Ln/S0w== print(sign) if __name__ == '__main__': main()
主要变化代码是 execjs.get(execjs.runtime_names.JScript) 。至此,这个问题结束。