Appearance
JS 执行上下文参考
规则里的 <js>...</js>、@js:...、payAction、loginCheckJs、coverDecodeJs、imageDecode 等脚本,都在同一个 JSEngine(JavaScriptCore)里执行,可以访问下面这些全局对象。 执行环境固定在专属串行队列上(见异步、取消与线程语义), 不要假设脚本在主线程或和 UI 同步。
隐式变量
| 变量 | 含义 |
|---|---|
result | 上一步规则的输出,是 JS 片段最常用的输入;对图片/字体解密类脚本,result 是原始字节。 |
src | 多数场景下和 result 同值;图片解密脚本里额外表示图片 URL。 |
baseUrl / url / sourceUrl | 当前请求的基址,一般就是书源 bookSourceUrl。 |
bookSourceUrl | 书源主 URL,等价 source.getKey()。 |
variables | 当前规则上下文里通过 @put:/java.put 存过的变量快照(对象)。 |
cookieHeader / cookieString | 当前书源的 Cookie 头字符串。 |
bookName / bookAuthor / bookIntro / bookKind / bookCoverUrl / bookLastChapter | 详情页解析上下文里可直接读到的书籍字段,省得再 book.name 绕一层。 |
chapterUrl / chapterTitle | 正文解析上下文里的当前章节信息。 |
headers | 当前请求头(对象)。 |
previousResult | 组合规则链(&&)里上一段的输出,语义上和 result 基本重叠,二者都可用。 |
book / chapter:可读写的宿主对象
book 在书籍详情/目录/正文解析上下文里可用,字段可读也可写——脚本改了 book.xxx 之后,解析结果会写回书架里的这本书:
text
book.name / author / intro / kind / coverUrl / lastChapter / lastChapterName
book.bookUrl / tocUrl / origin / originName / type
book.durChapterIndex / durChapterTitle / totalChapterNum / canUpdate
book.customIntro / variable
book.getVariable(key) / book.putVariable(key, value) / book.putCustomVariable(value)
book.getUseReplaceRule() / book.setUseReplaceRule(true|false)
book.getImageStyle() / book.setImageStyle(style)
book.getReverseToc() / book.setReverseToc(true|false)chapter 只在正文/目录相关上下文可用:
text
chapter.url / title / name / index / chapterCount / variable
chapter.getVariable(key) / chapter.putVariable(key, value)典型用法:把从正文页额外抓到的“真实作者”写回书籍信息——
js
book.author = result.match(/作者[::]\s*(.+)/)?.[1] ?? book.author;
resultsource:书源自身信息与变量
text
source.getKey() / source.key 书源主 URL(同 bookSourceUrl)
source.getTag() / source.name 书源显示名
source.put(key, value) / source.get(key) 书源级持久变量(跨请求保留,不同于规则内 @put:)
source.getLoginInfoMap() / source.putLoginInfo(json) / source.removeLoginInfo()
source.getLoginHeaderMap() / source.putLoginHeader(json) / source.removeLoginHeader()
source.getHeaderMap() / source.getCookies()
source.bookSourceGroup / source.bookSourceType / source.exploreUrl / source.searchUrl
source.refreshExplore() 通知宿主刷新发现页缓存source.put/source.get 存的是书源级变量(同一书源所有书共享,重启 App 后依然在), 和规则里的 @put:{varName}(只在当前一次求值上下文有效)是两个不同的存储层,写解析脚本 时容易混淆,选错一个会导致变量“看起来没生效”。
cookie:Cookie 读写
text
cookie.getCookie(url)
cookie.setCookie(url, cookieString) 等价 setWebCookie / replaceCookie
cookie.removeCookie(url)
cookie.getKey(url, name) 取某个 Cookie 字段值,如 cookie.getKey(url, 'PHPSESSID')java:通用工具方法
以下按用途分组,均为 java.xxx(...) 调用。命名和参数顺序尽量对齐社区通用书源生态的 习惯写法,方便直接迁移现成脚本;具体行为以这里和源码为准。
变量
text
java.get(key) / java.getString(key) 读规则级变量(同 @get:)
java.put(key, value) 写规则级变量(同 @put:)网络请求
text
java.ajax(url) GET 请求,返回响应体字符串
java.ajax(url, headersJson) 带自定义请求头
java.ajaxAll([url1, url2, ...]) 并发多个 GET,返回结果数组
java.get_url(url, headers) 等价 java.ajax,命名上和"读变量"的
java.get(key) 区分开,避免同名歧义
java.post(url, body, headersJson) POST 请求
java.get_response(url) / java.post_response(...) 返回带状态码/响应头的完整响应对象
java.getStrResponse(url) 返回字符串形式的完整响应
java.head(url) / java.connect(url) HEAD / 探测连接
java.initUrl(url, options) 按 URL 请求选项语法(见规则语法里的
"URL 请求选项")发起请求DOM / 二次解析
text
java.getElements(html, cssSelector) 在一段 HTML 里再跑一次 CSS 选择器,返回元素集合
java.getElement(html, cssSelector) 同上,只取第一个
java.selectElementsJSON(html, cssSelector) 返回 JSON 字符串形式的元素集合,便于跨语言传递编码 / 加解密(这一组方法族最大,命名沿用社区惯例的 xxxDecodeToString / xxxEncodeToString / xxxDecodeToByteArray 模式):
text
java.base64Encode(str) / java.base64Decode(str)
java.base64DecodeToByteArray(str)
java.md5Encode(str) / java.md5Encode16(str) / java.sha256Encode(str)
java.digestHex(str, algorithm) / java.digestBase64Str(str, algorithm)
java.HMacHex(data, key, algorithm) / java.HMacBase64(data, key, algorithm)
java.hexEncodeToString(bytes) / java.hexDecodeToString(hex) / java.hexDecodeToByteArray(hex)
java.strToBytes(str) / java.bytesToStr(bytes)
java.aesBase64DecodeToString(data, key, transformation, iv)
java.aesBase64EncodeToString(data, key, transformation, iv)
java.desDecodeToString(data, key, transformation, iv)
java.desEncodeToString(data, key, transformation, iv)
java.tripleDESDecodeStr(data, key, transformation, iv)
java.createSymmetricCrypto(algorithm, key, iv) 返回可复用的加解密器对象,处理同一密钥的
多段数据时比每次都传参更高效用于封面/图片二次解密的典型写法(配合 coverDecodeJs/imageDecode 字段,result 是 原始字节):
js
java.aesBase64DecodeToString(result, "0123456789abcdef", "AES/ECB/PKCS7Padding", "")杂项工具
text
java.timeFormat(ms) / java.timeFormatUTC(ms) 时间戳格式化
java.t2s(str) / java.s2t(str) 简体转繁体 / 繁体转简体
java.htmlFormat(html) 清理 HTML,保留图片标签
java.toNumChapter(str) 从"第三章"这类中文数字标题里提取数字
java.getVerificationCode(imageUrl) 触发验证码识别/人工输入流程
java.randomUUID() / java.deviceID() / java.androidId() 生成/读取设备标识
java.getUserAgent() / java.getWebViewUA()
java.log(msg) / java.toast(msg) / java.longToast(msg) 调试输出 / 弹出提示字体反爬
text
java.queryTTF(fontBytes) 解析自定义 TTF 字体的字形映射表
java.queryBase64TTF(base64Font) 同上,输入是 Base64 编码的字体
java.replaceFont(html, fontMap) 按字形映射把混淆字符替换回真实文字WebView / 交互式浏览器桥接(用于 Cloudflare 一类需要真实渲染或人工介入的场景,详见 Cloudflare 与反爬绕过实战、浏览器探测实战)
text
java.webView(url, js) 用 WKWebView 加载页面并执行 js,返回结果
java.startBrowser(url, title) 打开可交互浏览器页面(同步等待关闭)
java.startBrowserAwait(url, title) 异步版本,配合 async 规则使用
java.showBrowser(url) / java.showReadingBrowser(url)
java.startBrowserDp(url) 以“沉浸式”样式打开(去除多余外壳 UI)兼容别名:源码里还有大量以 _raw/_charset/_flags 结尾的变体(如 base64Decode_charset、getElements_raw、downloadFile_raw),用于精确匹配不同书源习惯 传参方式的写法;正常写新书源规则时用不到,遇到别处抄来的规则里出现这些方法名,说明它们是 故意保留的兼容入口,直接照抄调用方式即可,不需要额外转换。java.getAppVariant 固定返回 false——按标准 iOS 客户端能力对待,避免脚本里 !java.getAppVariant 这类判空写法产生歧义。
cache:跨请求缓存
text
cache.get(key) / cache.getFromMemory(key) / cache.getFile(key) 读缓存,未命中返回 undefined
cache.put(key, value, seconds) / cache.putMemory(...) / cache.putFile(...)
写缓存,seconds 是 TTL(秒),不传或传 0 表示不设过期
cache.remove(key) / cache.delete(key) / cache.deleteMemory(key) 删除单个 key
cache.clear() 清空当前书源的缓存命名空间getFromMemory/getFile、putMemory/putFile 目前是同一套底层存储的别名(不区分内存 和文件两级缓存),保留多个名字只是为了兼容不同书源习惯的调用方式。缓存按 bookSourceUrl 分命名空间,不同书源之间不会互相污染;非字符串的 value 会被 JSON.stringify 后存储, 读回来的也是字符串,需要自己 JSON.parse。
CryptoJS:浏览器脚本兼容层
从网站前端 JS 里直接搬来的解密脚本经常依赖 CryptoJS(一个很流行的浏览器端加密库)。 Readori 内置了一个精简 polyfill,覆盖最常用的子集:CryptoJS.AES、CryptoJS.MD5、 CryptoJS.SHA256、CryptoJS.enc.Base64 等。遇到书源脚本里出现 CryptoJS.AES.decrypt(...) 这类写法,通常不需要改写,直接照抄即可;如果用到了更冷门的算法/编码模式,才需要改用 java.* 里对应的方法自己实现。
