跳转到主内容
全部文档

写自己的站点规则

转网页、收藏网页时,页面里通用的文献信息(论文页的 citation_*、新闻页的结构化数据等)会先被读出来。常去的某个网站读得不全——作者没认出来、日期不对、书被当成了网页、正文混进了侧栏——可以给它写一份站点规则,写明这一站的页面是哪种文献、东西在哪。

站点规则是一份纯文本 TOML,存进 ~/.42md/siterules/,文件名就是规则的编号,比如 my-blog.toml。42md <网址> 和网页收藏都照它读。

一份最小的规则

toml
schema = "42md.siterule/2"id = "my-blog"                          # 与文件名相同label = "我的博客"match = { hosts = ["blog.example.org"], path = '^/posts/\d+$' }
[[detect]]type = "blogPost"                       # 这一站的文章页是博客文章
[item.blogPost]title  = [{ css = "h1.post-title" }]author = [{ css = ".byline a" }]issued = [{ meta = "article:published_time" }]
[[sections]]key = "body"from = [{ css = ".post-body" }]
  • schema:照抄第一行。
  • match.hosts:哪些网站用这份规则。写 blog.example.org 时,它和它的子域都算,名字只是相像的别家网站不算。加 path 可以只让文章页用。
  • [[detect]]:这一站的页面是哪种文献。type 用 book(图书)、bookSection(图书章节)、journalArticle(期刊论文)、thesis(学位论文)、newspaperArticle(报纸文章)、blogPost(博客文章)、webpage(网页)。
  • [item.<类型>]:这种文献的条目信息,一个字段一行。能写哪些字段,跑 42md siterule schema 看;写了别的类型才有的字段,规则读不进来,并说明是哪一项。
  • [[sections]]:长一些的内容按节取。body 是正文;不写就照常自动找正文。
  • 至少要取到一个必填字段(各种文献都是标题):一个都取不到,这份规则在这一页上不算数,照通用的读法收。

一个网站有几种页面

书店的书目页、书评页长得不一样,可以写几条 [[detect]],从上往下看,第一条对得上的为准;每条用 when 写怎么认:

toml
[[detect]]type = "book"when = { all = [  { css_exists = "#info" },  { any = [    { jsonld_type = "Book" },    { meta_equals = { name = "og:type", value = "book" } },  ] },] }
[[detect]]type = "webpage"
  • css_exists:页面上有这个元素;meta_equals:某个 <meta> 等于这个值;jsonld_type:页面结构化数据里有这种类型。
  • all 是都要成立,any 是有一个成立就行,可以套几层。取不到的一律算不成立。
  • 最后一条不写 when,就是「别的页面都按网页收」。每种写过的类型各写一张 [item.<类型>]。

每个字段怎么取

一个字段可以列好几种取法,从前往后试,用第一个取到值的。每种取法写下面一种:

写法取什么例子
meta页面头部 <meta> 的内容,按 name 或 property 找,不分大小写{ meta = "citation_title" }
css选择器选中的元素的文字{ css = "h1.title" }
css + attr选中元素的某个属性{ css = "a.journal", attr = "title" }
jsonld页面结构化数据(JSON-LD)里的值,用点隔开的路径{ jsonld = "author.name" }
info中文书目页常见的「标签: 值」,按标签找{ info = ["出版年", "出版时间"] }
after_heading + css某个小标题之后第一个对得上选择器的元素(到下一个小标题为止){ after_heading = "作者简介", css = ".intro" }

info 的值里有链接时,每个链接算一个值,几位作者自然就分开了;没有链接时取到换行为止的文字。

info 默认在整页里找第一个对得上的标签。书目信息都在某一块里的(比如 #info),加上 within,只在那一块里找,页面别处碰巧写着同样的标签也不会取错:

toml
publisher = [{ info = "出版社", within = "#info" }]

另外几项可以加在取法后面:

  • re:对取到的文字再用正则抽一次。有括号分组时取第一组,没有就取整个匹配:{ css = ".info", re = 'ISBN[::]\s*([0-9Xx-]{10,17})' }。正则建议用单引号写,反斜杠不用再转义。
  • all = true:收全部匹配,不只第一个。作者、关键词这类有好几个值的字段用它。
  • literal = true:只用在作者、编者、译者这类人名字段上。取到的是机构名时写它,整个名字保留,不会被拆成「名、姓」(只把多余的空格整理掉,汉字之间的空格会去掉):{ meta = "agency", literal = true },「Office of the Federal Register」就照原样记作者,不会变成「Register, Office of the Federal」。

选择器、正则最长 200 字节(汉字一个算 3 字节);JSON-LD 路径最多 8 段。

一格里写了好几个人

有的网站把几位作者写在同一格里,比如「张三,李四;王五」。人名字段(author、editor、translator 这类)和 keyword 可以加 split,按其中任一字符切开:

toml
author = [{ css = ".authors", split = ",,;;、", drop = ["著", "等"] }]
/3