百度做網(wǎng)站找誰智能建站系統(tǒng)
前言
做爬蟲肯定少不了JavaScript引擎的使用,比如在Python中現(xiàn)在一般用pyexecjs2
來執(zhí)行JavaScript代碼,另外還有一些其他執(zhí)行JavaScript的庫:
https://github.com/eight04/node_vm2
: rpc調(diào)用nodejs,需要安裝nodehttps://github.com/eight04/deno_vm
: rpc調(diào)用deno,需要安裝denohttps://github.com/wistn/pyChakraCore
: 調(diào)用ChakraCore.dll
aardio執(zhí)行js
如果本地安裝有nodejs,aardio范例里也有rpc調(diào)用node執(zhí)行JavaScript的例子。
但是rpc調(diào)用需要依賴本地的nodejs環(huán)境,給別人使用也不方便,需要讓人先安裝nodejs。而ChakraCore這個(gè)微軟開源的js引擎可以直接調(diào)用dll來實(shí)現(xiàn),不需要額外依賴。所以這篇文章我來封裝下aardio下的ChakraCore。
有了js引擎的話,又可以利用JavaScript優(yōu)秀的庫資源來豐富aardio的庫。比如加載crypt-js
給aardio增加一些加密算法(AES、DES等)。
下載地址
封裝好的代碼可以到github下載
下載地址:https://github.com/kanadeblisst00/aardio-extlibs
開始封裝
倉庫地址:https://github.com/chakra-core/ChakraCore
編譯dll
倉庫給出的編譯好的dll文件還是2020年的,但是代碼最近一直在更新,所以最好是自己編譯一個(gè),防止之前的有bug還沒修復(fù)到。
根據(jù)官方給的文檔,下載源碼后使用vs2017打開Build下的Chakra.Core.sln
,然后改一下編譯的架構(gòu)為x86。右鍵生成解決方案,一步就過了,沒有什么坑(最喜歡編譯這種項(xiàng)目了)。
生成的dll文件在Build\VcBuild\bin\x86_release
下,只需要ChakraCore.dll
這一個(gè)文件。
封裝思路
封裝這個(gè)庫用了不少時(shí)間,基本是參考上面pyChakraCore的代碼。就不說具體怎么做的(無非就是參考Python的代碼和看github和官方文檔嗎,碰到不會(huì)的在搜索一下),有興趣的可以自己看看庫代碼,下面說說怎么使用。
測(cè)試這個(gè)dll無法使用aardio的內(nèi)存加載,也就是說打包的時(shí)候只能帶上這個(gè)dll,不能直接打包進(jìn)exe。
案例
說幾個(gè)簡(jiǎn)單使用的案例,因?yàn)檫€沒有深度使用,后面想到什么在增加吧
例子1
import console;
import ChakraCore;io.open()var core = ChakraCore();
core.start();console.dump(core.run('(()=>{return Uint8Array.from([1,2,3,4]).buffer;})()'))
console.dump(core.run('(()=>{let a = {"a":1,"b":2};return a;})()'))
console.dump(core.callFunction('pretty', {"a":1,"v":"111"}))
console.dump(core.run('console.log("aaaaa",undefined,null,false,{a:1,b:2},function(){})'))console.pause(true);
例子2
先定義函數(shù)再調(diào)用
import console;
import ChakraCore;io.open()var core = ChakraCore();
core.start();core.run("function add(a,b){return a+b;}
")
var a = 1;
var b = 2;
console.log("a+b=", core.callFunction("add", a,b))console.pause(true);
例子3
注冊(cè)aardio函數(shù)為JavaScript函數(shù),這里以atob
和btoa
這兩個(gè)函數(shù)為例,ChakraCore沒有自帶這兩個(gè)函數(shù),而瀏覽器有,所以我們用aardio來實(shí)現(xiàn)。我在庫代碼里已經(jīng)內(nèi)置了console.log
和setTimeout
,有興趣的可以自己看怎么實(shí)現(xiàn)。
import console;
import ChakraCore;
import crypt.bin;
io.open()var core = ChakraCore();
core.start();var btoa = function(ptr_callee, isConstructCall, ptrj_arguments, argumentCount, callbackState){// ptr_callee不知道是什么// isConstructCall表示是不是構(gòu)造方法// ptrj_arguments是參數(shù)的數(shù)組// argumentCount是參數(shù)的個(gè)數(shù)// callbackState也不知道是什么var pointerSize = 4;var jStr = ..raw.convert(ptrj_arguments, {ptr p}, pointerSize).p;var aStr = ChakraCore.jValueToString(jStr);var result = crypt.bin.encodeBase64(aStr);var jResult = core.JsCreateString(result,#result,);return jResult;
};var atob = function(ptr_callee, isConstructCall, ptrj_arguments, argumentCount, callbackState){var pointerSize = 4;var jStr = ..raw.convert(ptrj_arguments, {ptr p}, pointerSize).p;var aStr = ChakraCore.jValueToString(jStr);var result = crypt.bin.decodeBase64(aStr);var jResult = core.JsCreateString(result,#result,);return jResult;
}core.registerMethod(btoa, "btoa");
core.registerMethod(atob, "atob");
var result = core.run('btoa("Hello, world")')
console.log("btoa: ", result)
console.log("atob: ", core.callFunction("atob", result))
console.pause(true);
而且比較有意思的是,這樣注冊(cè)的JavaScript函數(shù)打印出來的也是function () { [native code] }
,可惜和瀏覽器還是有區(qū)別,瀏覽器會(huì)加上函數(shù)名function btoa() { [native code] }
例子4
調(diào)用crypt-js實(shí)現(xiàn)下加密AES CBC加密算法
import console;
import ChakraCore;io.open()var core = ChakraCore();
core.start();core.run($"~\lib\ChakraCore\.res\crypto-js.js")var js = /*
let key = CryptoJS.enc.Utf8.parse("1234567890000000");
let iv = CryptoJS.enc.Utf8.parse("1234567890000000");let s = "Hello World";
let encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(s), key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7
});var eData = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
console.log("加密字符串: ", eData);let decrypted = CryptoJS.AES.decrypt(eData,key, { iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7
});
let dData= decrypted.toString(CryptoJS.enc.Utf8).toString();
console.log("解密字符串: ", dData);
*/core.run(js)
console.pause(true);