跳转至

开源阅读源 JS 说明

预计阅读时长 : 6 分钟

Legado 使用 Kotlin 语言开发,并内置 Rhino JavaScript 引擎,因此可以使用 JavaScript 脚本大幅增加各个规则配置的功能。除了使用 JavaScript 语法,脚本中还可以调用 Kotlin 支持的 Java 方法。

除了 JavaScript 的原生语法,Legado 中自定义的 JS 方法详见 JavaScript 说明 ⧉

语法要求

  • JS 代码可以放在 <js></js> 中 和 @js:
  • @js: 只能放在其他规则的最后使用,或者在 {{}} 中内置使用
  • <js></js> 可以在任意位置使用,还能作为其他规则的分隔符,例:tag.li<js>...</js>//a

变量定义

结果变量

result 代表上一步规则执行的结果,是规则处理中的核心变量

显示赋值

result 不需要显式赋值, JS 脚本会直接把最后一个变量值的值传递给 result,但为了代码的可读性,强烈建议显式赋值

字符串变量

  • baseUrl : 当前 url
  • title : 当前标题,title
  • nextChapterUrl : 下一章节 url
  • src : 内容,源码

类变量

变量操作

put 与 get

java.put 与 java.get 可在 JavaScript 语法规则中,实现变量的传递。

java.get(key) // 获取变量值
java.put(key, value) // 设置变量,并返回变量值

在 JavaScript 以外的语法规则中,可以使用 @get 和 @put 来实现变量的传递,注意变量的赋值需要加引号:

@put:{bid:"//*[@bid-data]/@bid-data"}
java.get 的另外用法

根据传递的参数不同,java.get 还可以用作网络请求,具体用法如下:

java.get(url: String, headerMap: Map<String, String>): Connection.Response

{{}}

{{}} 可以看做字符串插值语法 ${} 的语法糖,用于在字符串中调用变量

  • 在搜索 URL 与发现 URL 中的 {{}} 里调用变量时,只能使用 JavaScript,不需要 @js: 开头
  • 在搜索 URL 与发现 URL 以外的 {{}} 里调用变量时,默认使用 JavaScript,不需要 @js: 开头。使用 JSONPath 需要以 @json:$. 开头,CSS 需要以 @css: 开头

通过以上的语法,可以和不同的提取规则配合使用,更加灵活的用在需要使用字符串组合的场景中:

章节信息
1
2
3
4
🕰  更新时间
{{@css:meta[property$=update_time]@content##T.*}}
📜  内容简介
{{@css:.intro_info@text}}##(^|[。!?……;]+[”」)】]?)##$1<br>

常用方法

JSON.stringify()方法

JSON.stringify() 是 JavaScript 最常用的方法之一,它的作用是将一个 JavaScript 对象转换成一个 JSON 字符串,这在需要将对象作为字符串传输(例如,通过 HTTP 请求)时非常有用。

转换后的字符串可以被服务器解析并用来处理请求,根据 user-agent、accept-language 等信息提供定制化的响应。

@css:a@href@js:result+','+JSON.stringify({"webView": true});

示例代码

搜索地址
burl = source.getKey(); //获取书源地址
url =
  burl +
  "/e/search/index.php," +
  JSON.stringify({
    method: "POST",
    charset: "GB2312",
    body: "keyboard=" + key + "&show=title&classid=0",
  }); //拼接搜索地址
result = String(java.connect(url).raw().request().url()).replace(
  "?",
  "<?,index.php?page={{page-1}}&>"
);
处理搜索重定向
(()=>{
  if(page==1){
    let url='https://www.yooread.net/e/search/index.php,'+JSON.stringify({
    "method":"POST",
    "body":"show=title&tempid=1&keyboard="+key
    });
    return source.put('surl',String(java.connect(url).raw().request().url()));
  } else {
    return source.get('surl')+'&page='+(page-1)
  }
})()
或者
(()=>{
  let base='https://www.yooread.net/e/search/';
  if(page==1){
    let url=base+'index.php';
    let body='show=title&tempid=1&keyboard='+key;
    return base+source.put('surl',java.post(url,body,{}).header("Location"));
  } else {
    return base+source.get('surl')+'&page='+(page-1);
  }
})()
图片链接修改 headers
1
2
3
4
let options = {
  headers: { "User-Agent": "xxxx", Referrer: baseUrl, Cookie: "aaa=vbbb;" },
};
'<img src="' + src + "," + JSON.stringify(options) + '">';
解析内容
let javaImport = new JavaImporter();
javaImport.importPackage(
  Packages.java.lang,
  Packages.javax.crypto.spec,
  Packages.javax.crypto,
  Packages.java.util
);
with (javaImport) {
  function decode(k, i, d) {
    $ = (str) => {
      return java.base64DecodeToByteArray(str);
    };
    var key = SecretKeySpec($(k), "AES");
    var iv = IvParameterSpec($(i));
    var chipher = Cipher.getInstance("AES/CTR/NOPadding");
    chipher.init(2, key, iv);
    return String(chipher.doFinal($(d)));
  }
}
a = String(result.match(/window.a='([^']+)'/)[1]);
b = String(result.match(/window.b='([^']+)'/)[1]);
c = String(result.match(/window.c='([^']+)'/)[1]);
cookies = "haha=" + encodeURIComponent(decode(a, b, c));