天天看點

在Go中調用JS代碼(otto)

otto是一個Go語言實作的JavaScript 解釋器,它的項目位址為:https://github.com/robertkrimen/otto

假如我現在有一個encrypt.js的檔案,裡面的内容為:

var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

function encodeInp(input) {
    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;
    do {
        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);
        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;
        if (isNaN(chr2)) {
            enc3 = enc4 = 64
        } else if (isNaN(chr3)) {
            enc4 = 64
        }
        output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
        chr1 = chr2 = chr3 = "";
        enc1 = enc2 = enc3 = enc4 = ""
    } while (i < input.length);
    return output
}
           

這個檔案裡有一個函數是用來加密的(其實就是一個base64),然後當我們寫爬蟲或者其他的東西時我們需要将這段代碼運作一遍,并擷取其傳回的值。

那麼我們在Go中就可以這樣寫:

package main

import (
	"fmt"
	"github.com/robertkrimen/otto"
	"io/ioutil"
)

func main() {
	filePath := "你的JS檔案的路徑"
	//先讀入檔案内容
	bytes, err := ioutil.ReadFile(filePath)
	if err != nil {
		panic(err)
	}

	vm := otto.New()
	
	_, err = vm.Run(string(bytes))
	if err!=nil {
		panic(err)
	}
	
	data := "你需要傳給JS函數的參數"
	//encodeInp是JS函數的函數名
	value, err := vm.Call("encodeInp", nil, data) 
	if err != nil {
		panic(err)
	}
	fmt.Println(value.String())
}
           

然後假如你以後會經常性的使用這段代碼的話,你也可以給它進行一個小封裝。

func JsParser(filePath string, functionName string, args... interface{}) (result string) {
	//讀入檔案
	bytes, err := ioutil.ReadFile(filePath)
	if err!=nil {
		panic(err)
	}

	vm := otto.New()
	_, err = vm.Run(string(bytes))
	if err!=nil {
		panic(err)
	}
	value, err := vm.Call(functionName, nil, args...)
	if err != nil {
		panic(err)
	}

	return value.String()
}
           

其實otto還有很多有趣的功能,大家可以去otto的github項目裡去看。