Skip to content

规则开发

lanyuanxiaoyao edited this page Jan 18, 2021 · 5 revisions

概述

在说明规则编写之前必须要说明的是,这套规则体系并不是专门为本项目设计的,其使用了作者另一个尚未(即将)开源的工具 Squirrel(使用 kotlin-multiplatform 开发,具备跨 JVM、JS、Android 等平台的天然特性的一个页面解析工具),所以下文中部分设计如果放在本项目专用的场景下似乎有些繁琐,但是从跨平台跨项目的角度考虑会更容易理解。

规则试图使用如下的结构来表达一个待解析的目标页面(下简称: Site):

  1. 具备一个列表的页面
  2. 具备一段文本的页面
  3. 同时满足两点的页面

于是, 取一个并集, 一个Site的基本抽象就是

{
  "text": {},
  "list": {}
}

当然, Site里面还有比如上一页, 下一页等琐碎的信息, 暂且不表.

不管是text还是list, 统一称为Content, 最美妙的地方在于, 如果把list里的每一项看做text的话, 那么两类Content唯一的区别就是其选取的范围了.

于是, 完全相同的Content结构便可以同时胜任列表和文本两种页面的定义, 这就是这套规则体系的运作方式.

当然, 上面这些废话看不懂也无所谓, 看具体的字段解释和例子也可以明白.

规则结构说明

一个完整的站点规则看起来长这样:

{
  "code": "43e259b9-abd3-465f-bd22-7bdc8ad907a2",
  "name": "Nyaa",
  "category": "ACG",
  "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAABAlBMVEURbeMIN2////8hd+Xn9P4ofeYBefoAcfXX6/0op/84jOz4/P898v8dov845P8vg+cwq/8Chf9C//0AavJvxP7d7Pyw1vo3hegSmf/w+P4zu/87ovQ/+f856v8MkP9q4v4Zivgysv/O7P40zv7J5fy42vsqoPqgyvkYc+s4xP/C4PsqmvgPePIujfE43P821f8+qv2K3/yAyfzQ5fskf+4Fi/+76v2b3f1auv1ouf1Ls/2OzfuDwPqsz/l8vfmTvvVsrfWDtPE1lvFio+4/iOcq1/8kw/+Y8f5K3f563/1a1/xmy/xF7Pue1ft11PlRq/lcsPhL0PZDmfIysPAAS95YlOoND8hKAAACLElEQVQ4y4WR53LiQBCE5d2VWSSExKEEAiQTRTqTjpzBOdt37/8qNyMZkP3HDaXaqv6qe3ZWOPtBwhmlwheJolpyu8ERHADUr7b07tQ/3GeBUvHj8c0BQIz6UtXRLrLZO7eUzCd+gQCwThVqU1HicS173XWTyUQiFwJQiggV1bZtIwAR3fvfkAAEAtg2aJ2nUn8K9oGoly6RyOUQiMVi5yAECgW7ua1W4xdZIDAiAoREmwq0qmhTLVu/DEsASB8JzxJA1bg+hgwseTwCYYmEPnUmejjGlXuTTyDwGeGBj3KmMGdcf3i7k2+SAQDEYNBSDwvbdhRF0XV9SGQ3mcdr+mKr1Tpta6d3FE3vsWKm694mEaB+Om0dbKrOXzV73JuZfDS8v0KA+qq/P/pUNDv2mC01bcaH17dFBARLjD7nslA1ydTWy0/Z5wwLKk79FJ7lpfDCCHuqsN6IMBYknHy8qZfSCarICZE5JkQA6NqmUg30ZRm/owgQDiJ5nlckB8kPEYDin7altjcjR7HvCZIFv3loZiCpHAFUjJBUSdibZcIZAwI6ohUWpKgipTs26TcqZpnhVUJgZ272sENftUTaXi7IvMF5owKA3AsAy4BjbeDDs76vzQVjGcYZ57JcXjsBsAoHXlVWa0IMzgzCZG6UJx1JQoAKjASqNGoZAAwDF5Dh5qtKmwoAf/+RULUN+ISbeO7XWM0UhKaDwOIT2BiBhZRR6xsVTsWmBcAP+g8dajvM1EuD+QAAAABJRU5ErkJggg==",
  "target": "SEARCH",
  "home": "https://nyaa.si",
  "author": "lanyuanxiaoyao",
  "description": "A BitTorrent community focused on Eastern Asian media including anime, manga, music, and more",
  "parser": "CSS",
  "rules": {
    "https://nyaa\\.si/\\?q=.+&p=\\d+": {
      "list": {
        "expression": ".container table.torrent-list tbody > tr",
        "title": {
          "expression": "td[colspan] > a[title]:not(.comments)",
          "attribute": "title"
        },
        "dateTime": {
          "expression": "td:nth-child(5)"
        },
        "link": {
          "expression": "td[colspan] > a[title]:not(.comments)",
          "attribute": "href",
          "prefix": "{home}"
        },
        "extra": {
          "size": {
            "expression": "td:nth-child(4)"
          },
          "view": {
            "expression": "td:nth-child(8)"
          }
        }
      },
      "next": {
        "expression": "ul.pagination > li.next > a",
        "attribute": "href",
        "prefix": "{home}"
      }
    },
    "https://nyaa\\.si/view/\\d+": {
      "text": {
        "expression": ".container > .panel:contains(Magnet)",
        "title": {
          "expression": "h3.panel-title"
        },
        "author": {
          "expression": "a[title=User]"
        },
        "dateTime": {
          "expression": "div[data-timestamp]"
        },
        "extra": {
          "size": {
            "expression": "div.col-md-1:contains(File size) + div"
          }
        }
      },
      "list": {
        "expression": ".container > .panel:contains(Magnet)",
        "title": {
          "expression": "h3.panel-title"
        },
        "content": {
          "expression": ".panel-footer a:contains(Magnet)",
          "attribute": "href"
        }
      }
    }
  },
  "search": "{home}/?q={query}&p=1",
  "properties": {
    "SEARCH_LITE_SUPPORT": "true",
    "SEARCH_LITE_TITLE_TEMPLATE": "#title{${i.title}}#size{${i.size}}#view{${i.view}}#datetime{${i.datetime}}",
    "SEARCH_LITE_DESC_TEMPLATE": "#description{${i.link}}#link{${i.link}}",
    "SEARCH_LITE_IMAGE_TEMPLATE": "",
    "SEARCH_LITE_KEYS": "Nyaa",
    "TEST_SEARCH_KEY": "girl"
  }
}

部分字段本项目没有支持, 将会用删除线标注, 这些字段不写即可

Site

字段 名称 类型 默认值 必填
code ID String
enable 是否可用 Boolean false
version 版本号 Int 0
name 名称 String
category 分类 String ""
icon 图标 String ""
target 规则目标 Target
home 站点主页 String
author 规则作者 String
description 描述 String ""
banner 横幅 String ""
parser 解析器类型 Parser.Type
downloader 下载器类型 Downloader.Type "HTTP"
charset 网页编码 String "UTF-8"
headers 访问时 headers Map<String, String> {}
tags 站点 tag, 或分类 Map<String, String> {}
rules 解析规则 Map<String, Rule>
platform 规则适用平台 List []
options 其他选项 List []
search 搜索入口 String ""
properties 附加参数 Map<String, String> {}

code

站点规则唯一识别码, 建议使用 UUID, 在导入规则以及 API 调用的时候使用该code来识别站点规则.

UUID
通用唯一识别码(英语:Universally Unique Identifier,缩写:UUID)是用于计算机体系中以识别信息数目的一个128位标识符,还有相关的术语:全局唯一标识符(GUID)。

enable

由于没有相应的下载器或其他情况可能会导致站点不可用, 此时规则会改字段会被置为false, 规则不需要写, 这个字段由程序自动管理.

version

站点规则版本, 用于识别规则是否升级.

*name

站点名称, 这个没啥好说的, 必填就对了.

category

站点分类, 分类用于对不同类型的规则进行区分, 供前端识别使用, 比如漫画类, 资讯类, 搜索类等, 这种类型上的区别往往会导致前端需要使用不同的布局来展示, 因此使用这个字段供识别使用.

icon

站点图标, 可以填链接也可以填 base64 格式的图片, base64 格式为data:image/png;base64,....

base64 图片可以让规则第一时间显示图标, 比较美观, 但是如果图标较大, 会导致规则文件体积大增, 建议压缩后再转换为 base64 格式.

target

*home

站点主页, 用于在各种需要跳转到原站点的时候用到.

*author

规则作者

description

站点描述, 对站点的一些说明.

banner

parser

downloader

charset

headers

tags

rules

platform

options

search

properties