自动化数字生活:收藏网页 - 基础

你如何来收纳你曾阅读的网页、文章,如何可以方便地「点击即收藏」,把它们归于一处?

这篇文章会以「收藏网页」这样一个情景,来介绍一些自动化工具,让我们的「数字生活」变得更加灵活一些。

书签托管

书签管理的方式有很多。用 IE 的时候,就有「收藏夹」的说法,网址加入收藏夹,随时都可以来翻阅。但我要是想换一台电脑,那就很麻烦,必须通过导出、导入的过程,所以就有了「同步」的需求。

Google Chrome 在浏览器中引入了「账户」,这样就可以用来同步书签和设置,后来 Mozilla Firefox 也做了这件事情。时至今日,我们依然可以在电脑上保存一个书签,然后在手机上的同名浏览器中打开这个网页。国内大大小小的浏览器也都有这样的功能。

在浏览器自己做出同步服务之前,一些网站也提供了体验不错的书签同步服务。曾经的 Delicious 红极一时,网站域名非常可爱,但被雅虎收购后已关停,最后又到了 Pinboard 手中。Xmarks 的命运与之相似,LastPass 给它续命了几年,目前也已停止服务。它们顺便还解决了不同浏览器之间同步的问题,我在 Chrome 中的书签,可以传递到 Firefox 中,我在 Windows 下使用 IE,也可以无缝切换到 Mac 上的 Safari。

成都的 Diigo 一直面向海外客户,年费 40 刀,不仅可以收藏书签、存档网页,还可以进行批注,非常酷。Pinboard 极简的网页设计吸引了非常多的用户,目前基础年费 11 刀,也可以花 20 刀来保存网页正文。但这两个网站的存档服务在爬取知乎、微信公众号的时候多多少少有点问题,若是不抓正文的话就没有关系。

一众「稍后阅读」服务则从另一个角度提供了解决方案。PocketInstapaper 都支持自动获取网页全文,并可以在手机上离线下载,从而实现「WiFi下载、离线阅读」的效果,为当年流量昂贵时刷手机提供了便利。读过的网页会一直保留,也成为许多人保存网页的工具,然而更多的人把网页丢进「稍后阅读」结果就「再也不读」了。

EvernoteOnenote有道云笔记为知笔记等笔记服务似乎可以算作独辟蹊径了。由于纷纷推出全平台的浏览器插件,剪辑网页正文并保存下来,这件事情反而成为了很多人使用笔记服务的最大用途。

API

要实现自动化,一套可供调用的 API 是必不可少的。Diigo、Pinboard、Pocket 和 Instapaper 都有比较完善的 API 可供调用,并且都只需要借助 HTTP 来实现,非常方便。

以我目前在用的 Pinboard 来讲,它的 API 就是一系列简单的 GET 方法,并没有那么多讲究。

All API methods are GET requests, even when good REST habits suggest they should use a different verb.

具体而言,当需要收藏一个书签时,我们可以直接调用如下的 API:

也就是说,书签的所有内容全部作为 URL 参数传递。同时,为了表明身份,我们需要加上一段验证,用 auth_token 作为参数名。这个验证的值可以在设置页面中找到,也就是下图中被我涂马赛克的那一整串。

这样,根据规则,我们可以构建下面的一个 http 请求:

https://api.pinboard.in/v1/posts/add?auth_token=sxxxxxxxxx7&url=https://blog.o2as.com/&description=SanKo Blog&replace=no&format=json

其中 sxxxxxxxxx7 换成你自己的 API token。把这一整串 URL 地址复制到浏览器中执行,应该能够得到如下的返回:

{"result_code":"done"}

这就表明添加成功。打开 Pinboard 网页版,就可以看到这个书签条目了。

我在这段 URL 中用到了下面这些参数:

参数名 参数值 含义
auth_token sxxxxxxxxx7 用户 token,用于验证身份
url https://blog.o2as.com/ 指定 书签地址
description SanKo Blog 指定 书签标题
replace no 当同个地址已经保存过时,返回一个错误,yes 的话会直接替换掉
format json 指定返回值的格式,默认是 xml,指定成 json 方便后面的解析

你也可以根据前面的 API 表格,来增加标签、未读等参数。这个 URL 在后面会一直用到,每一种自动化工具都通过访问这个格式的 URL 来完成新书签的收藏。

预处理程序

从前面的 URL 中可以看到,书签地址和书签标题是需要手动输入。对于浏览器情景来说,这没有问题,可以直接读取网页信息,但是对于客户端来讲,往往只能获得要保存的地址,而不能直接获取到网页标题。

即便对于浏览器,我们获取到了标题,但这个网页标题很可能是这样的:

(1 封私信 / 49 条消息)淘宝有哪些常年卖假货的皇冠店铺? - 知乎

显然,前面的 (1 封私信 / 49 条消息) 不应该在加入收藏时出现在标题中。

对于用户传入的网址,也可能是这样:

https://www.zhihu.com/question/307960107?utm_source=wechat_session

在实际有效的地址后面,跟了一串 utm_source=wechat_session 用来对链接进行标记。如果我们将这些信息一并保存到书签的地址中,当我们多年之后保存了同一个页面的时候,它的地址可能变成了:

https://www.zhihu.com/question/307960107

这时,我们发现,完全一致的两个页面,Pinboard 没有提示这个链接已保存过(因为对于 Pinboard 来说,只有链接一致,才算是同一个页面),而是将它们保存成了独立的两份。这跟我们的期望是有差异的。(啊,为什么我现在写文字越来越翻译腔

又比如澎湃新闻客户端分享出来的网址是一个针对手机优化的页面:

https://m.thepaper.cn/newsDetail_forward_2043041

而在电脑上,对应了一个同样的文章:

https://www.thepaper.cn/newsDetail_forward_2043041

这两个页面也应该保存成同一份。

相同的情况还包括 http 与 https,一般而言,我们希望对同一个网页的 http 版本与 https 版本合并成为同一个书签项。

所以保存书签之前,我在自己的 VPS 上跑了一段预处理程序,所有的书签保存请求全部往这个服务器上发,后台经过处理之后传到 Pinboard 方,之后处理 Pinboard 的返回信息并最终反馈给相应的自动化工具。

在这段服务器程序中,我只需要接收一个「书签地址」,之后进行这些处理。其中涉及到一些特定网站的处理,我以我常用的微博公众号、知乎、哔哩哔哩、澎湃新闻四个为例。

  • 处理传入的网址
    • 检查是否是正确的网址格式
    • 微信、知乎、B 站:http 改 https
    • 知乎、B 站:移除网址后面的所有 URL 参数
    • 澎湃:手机页面统一成电脑页面
  • 尝试访问网址,检查网站是否正常
  • 从网站中爬取标题
    • 标题中含有 \ 的替换成 \\(否则 Pinboard 不识别)
    • 知乎:标注「回答」、「专栏」和「提问」
    • 微信:在书签标题中同时显示文章标题和公众号名
    • B 站、澎湃:修饰标题后缀
  • 向 Pinboard 服务器发送请求
  • 接收并解析 Pinboard 的返回信息

对于标题的修改,我这里纯属个人偏好了。效果如下:

网站 原标题 处理后的标题
B 站 【动画/1080P】驯龙高手番外篇:龙的礼物 (2011)【中英字幕】_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili 【动画/1080P】驯龙高手番外篇:龙的礼物 (2011)【中英字幕】 - 哔哩哔哩
澎湃新闻 北京电影学院成立翟天临事件调查组:对学术不端行为零容忍_直击现场_澎湃新闻-The Paper 北京电影学院成立翟天临事件调查组:对学术不端行为零容忍 - 直击现场 - 澎湃新闻
微信 果壳 你吃的猪蹄是前蹄还是后蹄?最简单的区分方法竟然是…… - 果壳
知乎 (1 封私信 / 49 条消息)为什么地图上孟加拉国有「国」字? - 知乎 为什么地图上孟加拉国有「国」字? - 知乎回答

当然,为了让自动化工具可以接入,这个服务器程序本身也需要提供接口来供调用。接口可以跟 Pinboard 类似:

https://your.domain.com/bookmark/add?auth=sanko&url=blog.o2as.com

借助 Node.js 或 Python 等脚本语言,可以很方便地实现这些逻辑。