# 规则语法详解 (Rule Syntax) [[toc]] Legado 支持多种规则语法,可在源的不同字段中混合使用。本文档详细介绍每种语法的写法和使用场景。 ## 1. JSOUP 默认规则 (Default) 以 `@` 为分隔符的 CSS 选择器语法,是 Legado 最常用的规则类型。 ### 基本结构 每段规则可分为 3 部分,用 `.` 连接: ``` 类型.名称.位置 ``` | 部分 | 说明 | 示例 | |:---|:-----------------|:-------------------------------------| | 类型 | 选择器类型 | `class`、`id`、`tag`、`text`、`children` | | 名称 | 匹配值 | `odd`、`content`、`a` | | 位置 | 索引(从 0 开始,负数为倒数) | `0`、`-1` | **示例:** ``` class.odd.0@tag.a.0@text // 取 class="odd" 的第一个元素下第一个 标签的文本 tag.div.-1@text // 取最后一个
的文本 ``` ### 最后一段为获取内容 | 值 | 说明 | |:------------|:------------| | `text` | 文本内容 | | `textNodes` | 文本节点列表 | | `ownText` | 自身文本(不含子元素) | | `href` | 链接地址 | | `src` | 图片/资源地址 | | `html` | HTML 内容 | | `all` | 全部内容 | ### 排除符号 `!` 用 `!` 排除不需要的元素,多个排除用 `:` 分隔: ``` tag.div!0:2@text // 排除第 1 个和第 3 个 div ``` ### 列表倒置 `-` 在获取列表的最前面加 `-` 可使列表倒置,适用于网站目录列表本身是倒序的情况: ``` -tag.dd@tag.a@text // 倒序获取所有 dd 下的 a 标签文本 ``` ### 正则替换 `##` 在规则末尾添加 `##正则表达式##替换内容`: ``` tag.p@text##去除的文字##替换为的文字 tag.p@text##要去除的文字 // 替换内容为空时可省略第二个 ## ``` ### 数组写法 `[index]` 支持类似数组的索引选择: | 写法 | 说明 | |:-----------|:--------------| | `[0]` | 第一个元素 | | `[-1]` | 最后一个元素 | | `[0:3]` | 前 3 个元素 | | `[2:5]` | 第 3 到第 5 个元素 | | `[0:10:2]` | 每隔一个取一个 | | `[!0:2]` | 排除第 1 个和第 3 个 | | `[-1:0]` | 反转列表 | ### 连接符号 | 符号 | 说明 | 示例 | |:-------|:---------------|:------------------------------| | `\|\|` | 优先取第一个有值的结果 | `tag.a@text\|\|tag.span@text` | | `&&` | 合并所有取到的值 | `tag.a@text&&tag.span@text` | | `%%` | 交替取值(依次从各列表中取) | `tag.a@href%%tag.a@text` | ::: tip 使用限制 连接符号只能在同种规则间使用,不包括 js 和正则。 ::: ## 2. JSOUP CSS 选择器 (CSS Selector) 以 `@css:` 开头的标准 CSS 选择器语法。 ``` @css:选择器@获取内容 ``` **示例:** ``` @css:.book-list li@text // 获取 class="book-list" 下所有 li 的文本 @css:#content p@html // 获取 id="content" 下所有 p 的 HTML @css:[property=og:image]@content // 获取 meta 标签的 content 属性 ``` - 在线测试:[Try jsoup online](https://try.jsoup.org/) ## 3. JSONPath 路径表达式 以 `@json:` 或 `$.` 开头的 JSON 数据提取语法。 ``` @json:表达式 $.表达式 ``` **示例:** ``` $.data.books[*] // 获取所有书籍 $.data.books[0].title // 获取第一本书的标题 $..books[*] // 递归查找所有 books 数组 $.info.Datas // 获取 info 下的 Datas ``` - 在线测试:[Jayway JsonPath Evaluator](http://jsonpath.herokuapp.com/) ## 4. XPath 路径表达式 以 `@XPath:` 或 `//` 开头的 XML/HTML 路径表达式。 ``` @XPath:表达式 //表达式 ``` **示例:** ``` //div[@class="book-list"]/ul/li // 获取指定 class 下的列表项 //*[@property="og:novel:author"]/@content // 获取 meta 标签属性 //a[text()="阅读"]/@href // 获取特定文本链接的 href ``` 详细语法参见 [XPath 路径表达式](./xpath)。 ## 5. JavaScript 脚本 在 `` 或 `@js:` 中使用 JavaScript。 | 形式 | 使用位置 | 说明 | |:------------|:----------------|:-----------------------| | `@js:` | 只能放在其他规则的**最后** | 将前面规则的结果作为 `result` 变量 | | `` | 任意位置 | 可作为其他规则的分隔符 | **示例:** ``` @css:.book@text@js:result.replace("旧", "新") // 先取文本再用 JS 处理 tag.li//a // JS 作为分隔符 @js:java.base64Encode(key) // 纯 JS 表达式 ``` ### 在搜索/发现列表中使用 以 `+` 开头可使用 AllInOne 规则,在搜索列表、发现列表和目录中使用。 ## 6. 正则表达式 Legado 中有三种正则用法: ### 全部匹配 (AllInOne) - 只能在搜索列表、发现列表、详情页预加载和目录列表中使用 - 必须以 `:` 开头 ``` :<正则表达式> ``` **示例(目录页):** ``` -:
  • ([^<]*) // 提取链接和标题,- 前缀表示倒序 ``` ### 单一匹配 (OnlyOne) 形式:`##正则表达式##替换内容###` - 只能在搜索列表、发现列表、详情页预加载、目录列表**之外**使用 - 只获取**第一个**匹配结果并替换 **示例(详情页):** ``` ##:book_name"[^"]+"([^"]+)"##$1### // 提取书名 ``` ### 净化(循环替换) 形式:`##正则表达式##替换内容` - 跟在其他规则后面,对结果进行循环匹配替换 - 独立使用相当于 `all##正则表达式##替换内容` **示例(正文页):** ``` @css:.content@html#### // 移除所有 script 标签 ``` ## 7. `{{}}` 模板变量 ### 在搜索 URL 和发现 URL 中 `{{}}` 内只能使用 JavaScript: ``` /search?key={{key}}&page={{page}} /search?key={{java.base64Encode(key)}}&page={{(page-1)*20}} ``` ### 在其他规则中 `{{}}` 内可使用任意规则,默认为 JS。使用其他规则需要标志头: | 规则类型 | 标志头 | |:---------|:-----------------| | JS(默认) | 无需标志 | | Default | `@@` | | XPath | `@xpath:` 或 `//` | | JSONPath | `@json:` 或 `$.` | | CSS | `@css:` | ### `{}` 旧语法 保留的阅读 2.0 语法,只能使用 JSONPath,建议避免使用。 ## 8. 变量存取 ### `@put` 与 `@get` 只能在 JS 以外的规则中使用: ``` @put:{bid:"//*[@bid-data]/@bid-data"} // 存储变量 @get:bid // 读取变量 ``` ### `java.put` 与 `java.get` 只能在 JS 中使用(JS 中无法使用 `@get`): ```js java.put('key', 'value') // 存储 java.get('key') // 读取 ```