毛线助手

目录

简介

为了更方便 MaoXian Web Clipper 用户在对网页进行 “裁剪” 之前执行一些操作,我们把「MaoXian 助手」集成到扩展中。该项目用于收集和分享各个用户编写的 “Plan”。

注: MaoXian Web Clipper 已经支持记住选区功能,如果你只是懒的每次都点选,则记住选区功能会很适合你,推荐你前往扩展的设置页面开启试试。如果你想更好地控制你要裁剪的内容,或者遇到一些难搞的网页,那么请往下看 :)

项目地址

背景

由于 MaoXian Web Clipper 裁剪网页的时候,裁剪的是当前状态下的网页,并且不会保存任何脚本文件(即 javascript)。 这意味着在一些情况下,我们需要对网页进行一些操作后,才能获得一个较好的裁剪结果。比如: 一篇文章里的图片显示的都是缩略图,而你想保存的是原图;或者是你不想保存选区内的按钮、评论等无关内容;又或者是网页上的某些区域是可折叠的,需要在裁剪前把它们都展开。开发「MaoXian 助手」就是为了解决这些较常见的问题。

在集成「MaoXian 助手」之后,MaoXian Web Clipper 的裁剪流程也完整了起来。

准备 --> 选择 --> 裁剪 --> 存储

如上的四个步骤中,「MaoXian 助手」主要用于「准备」阶段,也涉及到「选择」阶段(不过不多)。它的工作方式有点像「广告屏蔽扩展」,需要针对不同的网站,编写不同的操作(在「MaoXian 助手里」我们称其为 Plan)。这也意味着它解决问题的多少取决于我们适配的网站的多少。

三种不同的 Plan

全局 Plan

「全局 Plan」 是由你自己编写的。它会应用到所有的网页上,如果某个操作具备普遍性,则可以加入到「全局 Plan」里。

自定义 Plan

「自定义 Plan」也是由你自己编写的,它会应用到某一类网页上。此种为最常见的,一般都会对某个网站的某类网页进行裁剪。比如对某个博客的文章进行裁剪,因为同类网页的结构一般都相同,需要对其的操作也相同,所以可以通过编写此种 Plan 对其进行统一处理。

公开的 Plan

为了减少用户重复编写「自定义 Plan」的工作。MaoXian 支持你将自己编写的 「自定义 Plan」分享出来,成为 「公开的 Plan」。这样所有用户都会受益。 此种 Plan,可以通过下方的订阅地址获取到。

订阅「公开的 Plan」

将下方的订阅地址复制到:MaoXian 扩展 > 设置页面 > 助手 页面的订阅框中。

订阅地址

# 默认网站列表(全球性)
https://mika-cn.github.io/maoxian-web-clipper/assistant/plans/default/index.json

# 华人网站列表
https://mika-cn.github.io/maoxian-web-clipper/assistant/plans/zh/index.json

参与进来

「MaoXian 助手」的功能强大于否取决于我们适配的网站的多少。这需要的不仅仅是开发者,更是每一个使用者的无私分享精神,于此,我们欢迎各位用户参与进来,只有这般,该助手才能发挥其真正的能力。

如果你不会编程,你可以在项目 issue 页面 提交适配请求(提供需要适配的网址),或者回馈某个网站适配不正确的信息,以便其他人进行跟进。

如果你会编程(只需要懂一点 CSS,了解 JSON 格式就行),那么恭喜你,你完全有能力编写 Plan,并分享给其他人,具体查看下一节。

如何编写 Plan

流程

  1. 请到 MaoXian Web Clipper 的设置页面,启用「MaoXian 助手」
  2. 使用任何编辑器编写 Plan, 再把其复制到 「MaoXian 助手」设置里的**自定义 Plan **里。
  3. 刷新目标网页,点击「裁剪」验证编写的动作有没有产生预期效果。

Plan 的结构解释

参数名 类型 是否必填 备注
name 字符串 必填 起标识作用,可随便填写,一般可以直接填写网站名
pattern 字符串、元组 必填 匹配的模式,只有网址和模式匹配,该 plan 才会被应用
excludePattern 字符串、元组 选填 用于充当 pattern 的黑名单
version 整型 必填 用于描述最后更新时间,格式为年月日,如:20190721
contributors 元组 选填 用于描述 plan 的作者和贡献者
disabled 波尔值 选填 用于表示 plan 的禁用状态
pick 选择器 选填 用于选择「要裁剪的节点」,可提供多个选择器,详情请看下文
hide 选择器 选填 用于选择「要剔除的节点」,可提供多个选择器,详情请看下文
hideSibling 选择器 选填 用于选择「要剔除的节点」,可提供多个选择器,详情请看下文
hideExcept 元组 选填 用于选择「要剔除的节点」,选择方式为反选,详情请看下文
show 选择器 选填 用于显示隐藏的「块状节点」,可提供多个选择器,详情请看下文
chAttr 元组 选填 用于修改节点的属性值,提供了多种修改属性的方式,详情请看下文
form 对象 选填 用于预设置表单的输入值,详情见下文
config 对象 选填 用于重写某些配置项,详情见下文
tags 元祖 选填 用于标注网站属性,使这些 plan 更好管理
comment 字符串 选填 备注

pattern 参数的使用

pattern 参数描述了该 Plan 会应用到哪一类网址上,如果网站有多个域名且很难用匹配符进行匹配,则可以提供多个 Pattern,例如:["https://a.com/article/*", "https://abcdefg.onion/article/*"]。 如果 pattern 所匹配的网址中有几个特殊项,则可以用 excludePattern 参数剔除。

目前支持的匹配符有数字匹配符 “$d” 和 星匹配符 “*” 和 “**“。

数字匹配符

数字匹配符专门用于匹配数字,常用于匹配网址路径中的数字部分。

比如: 使用 https://example.org/post/$d/$d/$d/$d 可以匹配到 https://example.org/post/2019/07/21/003 。其中前三个 $d 分别匹配到 年,月,日。最后一个 $d 匹配到文章 ID,注意网址中的这四个部分全是数字。

数字匹配符只能完整匹配,无法作为前缀或者后缀去使用。

比如: 使用 https://example.org/article-$d 是无法匹配到 https://example.org/article-001 的。

如果要匹配前缀和后缀,则需要使用星匹配符。

星匹配符

比如:匹配子域名,*.example.org 可匹配任何以 “example.org” 结尾的域名,例如: www.example.org,foo.bar.example.org。

比如:匹配网址协议,http* 即可以匹配到 http 也可以匹配到 https。

比如:使用 https://example.org/*/index.html,可以匹配到 https://example.org/blog/index.html 。但是无法匹配到 https://example.org/blog/jack/index.html ,因为 “*” 号不匹配目录分隔符 “/”。

双星匹配符

一般使用双星匹配符,来匹配零个或零个以上的目录。

假如我们要匹配的网址为 https://example.org/blog/javascript/2017/01/05/awesome-article.html ,里面 /blog 为固定不变的部分,/javascript 为文章分类(不知道有没有子分类),后面是年月日,最后是文章名。

可以用 https://example.org/blog/**/*/*/*/*/*.html这个 Pattern 来匹配。 中间用了四个 “*” 号来匹配分类和年月日,前面的 “**” 匹配可能存在的子分类。也可以用 https://example.org/blog/**/*/$d/$d/$d/*.html 来进行匹配。

上面这个例子也可以使用 https://example.org/blog/ (注意:最后面的 “/”) 作为 Pattern ,来直接匹配以该模式打头的网址,不同的 Pattern,严格程度不同,根据需求给出 Pattern 即可。

匹配网址的查询参数部分(较少使用)

一般匹配只是匹配网址的查询参数能满足 Pattern 的参数部分。网址的参数数量可以多,顺序也可以不一致。

例如:使用 https://a.org/page?id=* 这个 Pattern,可以匹配到 https://a.org/page?id=123 ,也可以匹配到 https://a.org/page?type=news&id=456 。当然了,你也可以进一步匹配参数值,如: https://a.org/page?type=news 这个 Pattern 。

严格匹配表示网址的查询参数必须和 Pattern 的参数部分严格一致,数量不能多,不能少,但顺序可以不一致。 严格匹配需要在 Pattern 的参数部分的最前方加上 “!”。

例如:使用 https://a.org/page?!foo=111&bar=222 这个 Pattern,只能匹配到 https://a.org/page?foo=111&bar=222 和 https://a.org/page?foo=222&bar=111 。但不能匹配到 https://a.org/page?foo=111 或 https://a.org/page?foo=111&bar=222&baz=333。

excludePattern 参数的使用

该参数用于作为 pattern 参数的黑名单,也可提供多个。用法参见 pattern 参数

disabled 参数的使用

disabled 参数用于表明该 plan 是否已禁用了。常用于「全局 plan」,或者是禁用某个「公开 plan」。比如你订阅的公开的 plan 列表里,有一个 plan 你不想使用。则可以把那个 plan 复制进 「自定义 plan」列表里,然后把它设为 "disabled": true ,就会把它禁用掉。

选择器

选择器的格式

选择器有两种:CSS 选择器 和 xPath 选择器。是一个字符串,格式为 $type||$q

变量 说明
$type 选择器的类型 C 代表 CSS, X 代表 xPath
$q 选择器 CSS 选择器 或 xPath 选择器

其中 $type|| 部分可省略,省略后的部分表示的是 CSS 选择器,大部分情况下我们都会用 CSS 选择器,除非一些很难用 CSS 选择器表示的,才会使用到 xPath 选择器。

下面我们来看一个例子(注: 本页面给出的例子都是 JSON 格式)

{
  "name": "example.org",
  "version": 20190831,
  "pattern": "https://www.example.org/article/*",
  "pick": "article",
  "hide": [
    "div.status-bar",
    "div.comment",
    "X||//span[text()='更多请关注']"
  ]
}

pick 参数的使用

pick 参数用于选中要裁剪的节点。找到第一个匹配的节点就停止查找,如果你填写了多个选择器,则会按照选择器的顺序依次查找,也是找到第一个即停止。注意: 「全局 Plan」会忽略该参数。

hide 参数的使用

hide 参数是用来剔除你不想裁剪的节点的,所有选择器找到的节点都会被隐藏掉(MaoXian 不会裁剪隐藏的节点)。

hideSibling 参数的使用

hideSibling 参数是用来剔除你不想裁剪的节点的,它比 hide 参数特殊的地方在于, 所有选择器找到的节点必须具有一个特征:找到的节点在父节点的子节点中有且只有一个。找到的节点的兄弟姊妹节点都会被隐藏掉。 (MaoXian 不会裁剪隐藏的节点)。

hideExcept 参数的使用

hideExcept 参数是使用「反选」的方式来选择要剔除的节点。它的值是一个 $action 的元组,$action 是一个 Object。$action 有两个必须指定的属性:insideexcept

假如有一个网页,它有如下结构:

<div class="post">
  <div class="xxxxx">广告内容</div>
  <div class="post-header"><h1>文章标题</h1></div>
  <div class="post-content">文章内容</div>
  <div class="xxxxx">更多推荐</div>
</div>

且其中的「广告内容」和「更多推荐」的 class 属性的值是随机生成的,其位置随机出现。这个时候可以通过 hideExcept 参数来反选它们,如:

{
  ...
  "hideExcept": [
    {"inside": ".post", "except": [".post-header", ".post-content"]}
  ]
}

该 Plan 会把 “.post” 选中到的节点内部的子节点进行隐藏,除了 “.post-header” 和 “.post-content” 指定的节点。(MaoXian 不会裁剪隐藏的节点)。

show 参数的使用

show 参数是用于显示「隐藏的块状节点」的,属性的值也是选择器(可填写多个),show 比较特殊,它只可用于块状节点(即display 的值为 block)。它会将节点的 display 样式设置成 block 来让这个节点显示出来. 它相对于后文会提到的 chAttr 参数比较简单,如果要操作的节点都为块状节点,则使用 show 会比较方便,否则,请考虑使用 chAttr 参数(具体查看 chAttr 的例4)

chAttr 参数的使用

chAttr 参数可以用来改变标签的某个属性的值。chAttr 是一个可选项,只有在需要的时候,才需要提供。 chAttr 的值为一个 $action 的元组,$action 是一个 Object。$action 的常用参数有三个 type, pickattr。不同的 type 会跟不同的的参数。下面我们用一些常见的例子来说明 chAttr 的用法。


例1.1: 假设有一个网页,显示的是低质量的图,这些图的 src 属性是一个有规律的地址,比如: https://www.example.org/images/awesome-pic-small.jpg ,而某些操作后,可能就变为 https://www.example.org/images/awesome-pic-big.jpg 。我们希望裁剪的是后者,而非前者,可以用下面这个 Plan 来实现:

{
  ...
  "chAttr": [
    {
      "type": "replace.last-match",
      "pick": "img",
      "attr": "src",
      "subStr": "small",
      "newStr": "big"
    }
  ]
}

上面 Plan 中的 chAttr 参数的值是一个数组,里面包含了一个 $action,它的各个属性解读如下:

还有一种和这个类似的 $action,它的 type 为 replace.all ,作用是替换所有找到的匹配,较少使用。 replace.all 也支持有多个替换项(即:subStrnewStr 都可以是数组)。替换规则为:如果 newStr 有和 subStr 对应的项,则使用对应的项,否则使用 newStr 的第一项。

例如: subStr 为 ["xm", "xxm"],newStr 为 ["xl", "xxl"] 两个值一一对应,则会使用对应项。即 xm 会由 xl 替换, xxm 会由 xxl 替换。

例如: subStr 为 ["xm", "xxm"],newStr 为 ["xxl"] ,其中 xxm 没有对应的替换值,则会使用第一项。即 xxm 也会由 xxl 替换。

专门用于修改 URL 的 $action

比如上方的例1.1,也可以用下方的 Plan 来实现:

{
  ...
  "chAttr": [
    {
      "type": "url.file.set-name-suffix",
      "pick": "img",
      "attr": "src",
      "sep": "-",
      "suffix": "big",
      "whiteList": ["small", "big"]
    }
  ]
}

这个 $action 会对 src 属性指定的 url 的文件名部分,设置后缀(在扩展名前面)。其中:

如果要移除文件名后缀,则使用下方 Plan :

{
  ...
  "chAttr": [
    {
      "type": "url.file.rm-name-suffix",
      "pick": "img",
      "attr": "src",
      "sep": "-",
      "whiteList": ["small", "md"]
    }
  ]
}

参数比前一个 Plan 少了 suffix。其中:

例1.2:有些网站会在文件的扩展名后面加上后缀来区分不同的文件质量。如:

<img src="assets/name.jpg!sm">

则可使用下方 Plan 进行设置:

{
  ...
  "chAttr": [
    {
      "type": "url.file.set-ext-suffix",
      "pick": "img",
      "attr": "src",
      "sep": "!",
      "suffix": "lg"
    }
  ]
}

若要移除,则使用:

{
  ...
  "chAttr": [
    {
      "type": "url.file.rm-ext-suffix",
      "pick": "img",
      "attr": "src",
      "sep": "!"
    }
  ]
}

注意: MaoXian 助手对于扩展名后缀的操作很粗暴。须确保 url 文件名中含有的分隔符确实为扩展名和后缀的分隔符,不然会出问题。

例1.3:有些网站还会把版本信息放在 url 的查询参数中,如:

<img src="http://a.org/name.jpg?size=sm&from=google">

遇到这种,可使用下方 Plan:

{
  ...
  "chAttr": [
    {
      "type": "url.search.edit",
      "pick": "img",
      "attr": "src",
      "change": {"size": "lg"},
      "delete": ["from"]
    }
  ]
}

其中:

上面这个 plan 应用后, src 属性的值为: “http://a.org/name.jpg?size=lg”


例2: 假设有一个网页,显示的是低质量的图,它的高质量图片地址,放在了 img 标签的另一个属性上。图片的 html 如下:

<img src="/image/pic-abc.jpg" hq-src="/image/pic-bdf.jpg" />

我们要裁剪的是 hq-src 指定的那张图片,使用下面这个 Plan 实现:

{
  ...
  "chAttr": [
    {
      "type": "assign.from.self-attr",
      "pick": "img",
      "attr": "src",
      "tAttr": "hq-src"
    }
  ]
}

例3.1: 假设有一个网页,显示的是低质量的图,并且这些图片本身是一个链接,可以通过点击图片查看原图, 图片的 html 如下:

<a href="/image/awesome-pic-bdf.jpg" >
  <img src="/image/pic-abc.jpg" />
</a>

我们要裁剪的是 a 标签 href 指定的那张图片,使用下面这个 Plan 实现:

{
  ...
  "chAttr": [
    {
      "type": "assign.from.parent-attr",
      "pick": "img",
      "attr": "src",
      "tAttr": "href"
    }
  ]
}

例3.2: 假如和 例3.1 类似,但是原图的链接不在父节点,而是在祖先节点,HTML 如下:

<a href="/image/awesome-pic-bdf.jpg" >
  <div class="wrapper">
    <img src="/image/pic-abc.jpg" />
  <div>
</a>

我们要裁剪的是 a 标签 href 指定的那张图片,使用下面这个 Plan 实现:

{
  ...
  "chAttr": [
    {
      "type": "assign.from.ancestor-attr",
      "pick": "img",
      "attr": "src",
      "tElem": ["a"],
      "tAttr": "href"
    }
  ]
}

注意 tElem 的值比较特殊,如下:

还有一种 和 assign.from.ancestor-attr 相似的类型为: assign.from.ancestor.child-attr , 此种类型也需要提供 tElem ,且需要提供两个选择器。拿到的目标节点为祖先节点的后代节点。


例4: 除了上面这几种 $action, chAttr 还对 class 属性的修改做了支持。请看下方 Plan:

{
  ...
  "chAttr": [
    {
      "type": "split2list.remove",
      "pick": ".section",
      "attr": "class",
      "value": "folded",
      "sep": " "
    }
  ]
}

还有一种 $action, 跟该例子类似,它的类型为 split2list.add,该类型表明要往属性里面添加一项。

一般可以使用这两种 $action ,对网页折叠部分进行控制,使其达到我们想要的状态。这种方式不像上文的 show 参数那样粗暴地对 display 进行操控。


例5: 这种可能不常见,即直接修改属性的值

{
  ...
  "chAttr": [
    {
      "type": "assign.from.value",
      "pick": ".formula",
      "attr": "type",
      "value": "image/svg",
    }
  ]
}

上面的例子会把 “type” 属性的值设置为 “image/svg”。

form 参数的使用

用于预设置表单的输入值,MaoXian 会在显示表单的时候,自动帮你输入这些预设的值。四项都为选填,详情如下:

名字 类型 说明 默认值
format 字符串 存储格式,只能为 htmlmd 取决于你的设置(见扩展设置页面)
title 选择器 用于选中包含标题的元素
category 字符串 对应表单的目录(多级目录用 / 隔开) 取决于你的设置(见扩展设置页面)
tagstr 字符串 对应表单的标签(多个标签用 ,空格 隔开)

主要应用场景:

例子:

请注意 title 的值是一个选择器,此例选中 main h1 对应的标题来作为『保存表单』的标题。

{
  ...
  "form": {
    "format": "md",
    "title": "main h1",
    "category": "news/read-later",
    "tagstr": "international,freedom-news"
  }
}

config 参数的使用

重写某些配置项,并且重写的这个动作只在这个 Plan 的作用范围内有效。

当前允许重写的配置项如下,所有可配置项均为选填。注: 其中的默认值指的是 MaoXian 扩展提供的默认值,该值只作为参考,实际上使用的是你自己配置页面上的值。

存储相关

可在扩展的 扩展 > 设置页面 > 存储设置 一节找到可使用的变量及其说明。

名字 说明 类型 默认值
clippingHandler 处理程序 String Browser
saveFormat 保存格式 String html
rootFolder 根目录 String mx-wc
defaultCategory 默认分类 String default
clippingFolderName 裁剪目录 String $YYYY-$MM-$DD-$TIME-INTSEC
mainFileFolder 主文件的存储目录 String $CLIPPING-PATH
mainFileName 主文件的文件名 String index.$FORMAT
saveInfoFile 是否保存元信息文件 Boolean true
infoFileFolder 元信息文件的存储目录 String $CLIPPING-PATH
infoFileName 元信息文件的文件名 String index.json
saveTitleFile 是否保存标题文件 Boolean true
titleFileFolder 标题文件的存储目录 String $CLIPPINT-PATH
titleFileName 标题文件的文件名 String a-title_$TITLE
frameFileFolder 内嵌的网页文件的存储目录 String $CLIPPING-PATH/frames
frameFileName 内嵌的网页文件的文件名 String $TIME-INTSEC-$MD5URL.frame.html
assetFolder 资源文件的存储目录 String $CLIPPING-PATH/assets
assetFileName 资源文件的文件名 String $TIME-INTSEC-$MD5URL$EXT

备注

Markdown 文档相关

请参考 扩展 > 设置 > Markdown 的说明文字进行配置。

名字 说明 类型 默认值 可选值
markdownTemplate Markdown 模板 String \n{{content}}\n  
markdownOptionHeadingStyle 标题格式 String atx setextatx
markdownOptionHr 水平分割线 String * * * * * *- - - 等等
markdownOptionBulletListMarker 子弹列表的行头符 String * *+-
markdownOptionCodeBlockStyle 代码块格式 String fenced indentedfenced
markdownOptionFence 代码块分隔符 String ``` ```~~~
markdownOptionEmDelimiter 强调(斜体)分隔符 String _ _*
markdownOptionStrongDelimiter 加重(粗体)分隔符 String ** **__
markdownOptionLinkStyle 链接格式 String inlined inlinedreferenced
markdownOptionFormulaBlockWrapper 块状公式的格式 String padSameLine sameLine, padSameLIne, multipleLinemathCodeBlock

备注

HTML 文档相关

请参考 扩展 > 设置 > HTML 的说明文字进行配置。

名字 说明 类型 默认值 可选值
htmlSaveClippingInformation 追加裁剪信息到内容尾部 Boolean false falsetrue
htmlCustomBodyBgCssEnabled 允许自定义 body 标签的 CSS 背景颜色 Boolean false falsetrue
htmlCustomBodyBgCssValue body 标签的 CSS 背景颜色 String #000000 查看 background-color (CSS)
htmlCompressCss 压缩样式(CSS) Boolean false falsetrue
htmlCaptureImage 图片 String saveAll saveAllsaveCurrent
htmlCaptureAudio 声音 String remove saveAllsaveCurrentremove
htmlCaptureVideo 影片 String remove saveAllsaveCurrentremove
htmlCaptureApplet Applets String remove saveAllremove
htmlCaptureEmbed Embeds String saveImage saveAllsaveImageremovefilter
htmlCaptureObject Objects String saveImage saveAllsaveImageremovefilter
htmlCaptureIcon 网站图标 String remove saveAllsaveFaviconremove
htmlCaptureCssRules 样式规则 String saveUserd saveAllsaveUserd
htmlCaptureWebFont Web 字体 String remove saveAllremovefilterList
htmlCaptureCssImage 样式图片 String remove saveAllremove
htmlEmbedFilter Embeds 过滤器 String <images> -
htmlObjectFilter Objects 过滤器 String <images> -
htmlWebFontFilterList Web 字体过滤器组 String woff2|woff|otf|ttf -

Web 请求相关

请参考 扩展 > 设置 > 高级设置 的说明文字进行配置。

名字 说明 类型 默认值 可选值
requestTimeout 超时(秒) Integer 300 5 ~ 86400
requestMaxTries 最大尝试次数 Integer 3 大于1的整数
requestReferrerPolicy Referrer 请求头 String originWhenCrossOrigin noReferreroriginoriginWhenCrossOriginunsafeUrl

tags 参数的使用

虽然 Plan 的 tags 属性是非必须的,但还是建议你为 Plan 打上标签,以便后期,我们能更好地管理他们。

贡献 Plan

所有的 Plan 都存储在 plans 的子目录下,不同的子目录代表不同频道,每个频道最终都将生成一个订阅地址。请将你写的 Plan 以数组的形式单独存为一个文件,如: plans/zh/zhihu.json。每个网站建一个文件。

最终所有的 Plan 会在 build.rb 这个脚本的渲染下,变成可订阅的形式。

你可以通过下方几种方式把 plan 分享出来:

最后

如果你对「毛线助手」有什么看法或建议,请告诉我们

首页