article_image

Claim:本文写作时间较早,目前我已经改用 DEVONthink 读 RSS,但过滤思路完全来自本文。不如说,苟无 NetNewsWire 让我一展拳脚,我恐怕会惑于 DEVONthink 功能之琳琅而裹足不前。

如今读点东西就和减肥一样,不想花钱的人仍然可以轻松获得海量资讯,而有钱人却在付费屏蔽、过滤那些不想看到的内容。

RSS 阅读器多矣,支持过滤功能者却寥寥。大概是因为,过滤功能很容易“得罪人”。RSS 本身就有损网站的流量,阅读器内的浏览次数并不会被统计在内,换言之,你在 RSS 阅读器里越是如鱼得水,你订阅的那些网站损失的流量就越惨重;而过滤功能更是让这些被订阅的网站雪上加霜,不仅得不到流量,连广告、软文和合作文章也被统统拦下。这有点像原本就是免费派发的广告单子和宣传礼品,中途还被人拦截了一部分。

但对网站不利的操作,未必就是不正当的,RSS 也好,过滤也罢,完全是用户选择自由范围内的事情,我本人非常欢迎大家筛选我的文章,把不喜欢的滤掉不看,双方都自在。Inoreader 把付费过滤做成了一种商业模式,NewsBlur 的过滤功能 Intelligent Trainer 需要不断训练、像养宠物一样有趣1,开源工具 TinyTinyRSS 尽管繁琐、却仍然凭借过滤特性吸引了一批玩家……想必一说这些屈指可数的工具,文章开头提及的尴尬现状就出现了:要么花大钱订阅 Inoreader,要么和 NewsBlur 磨洋工,再要不就是折腾那些开源工具(仅仅搭建服务器的钱就直逼 Inoreader 订阅费)。

直到两年前,一款死寂多年的阅读器 NetNewsWire 突然苏醒2,我才发现一种新的过滤思路:本地自动化。不限关键词过滤数量,不限使用设备台数,可以对不同文件夹设置专门的关键词,并且从阅读器到过滤功能都免费的。

Alt text
过滤后的通知提示

如何过滤 RSS

如果只追求免费,Zapier 和 IFTTT 都有一定额度;如果还想要一些自主权,则可以考虑 Google Sheet 脚本——比如 这个——或者像 Dr. Drang 那样 自己搭建 在线过滤服务。而本文另辟蹊径,取道本地过滤。

本文脚本基于 NetNewsWire 的 AppleScript 编写,可以嵌入任何支持 AppleScript 的自动化工具,方便运行。下文以 Keyboard Maestro 为例,使用快捷键触发过滤操作。

下载动作后并不能马上使用,需要先设置自己的关键词和所针对的文件夹。打开脚本部分,可以看到第一行的关键词列表,我将其命名为 rssFilters,表示要过滤的元素。

Alt text
过滤脚本的代码

以过滤娱乐类信息为例,下面列出了 TikTokApple TVtvosarcade 四条关键词(实际使用中关键词远远不止这几条),每个关键词都需要英文双引号 "" 包裹起来,并且用英文逗号 , 隔开,以遵循 AppleScript 的语法,至于逗号后面要不要加空格则看个人喜好,有它不多,缺它不少。

set rssFilters to {"TikTok", "Apple TV", "tvos", "arcade"}

得益于英文双引号的包裹,过滤关键词可以使用中文,也可以掺有空格或英文单引号(常见于 Somebody's 这样的词语中)。当然中英混用的词语比如 任天堂 Switch 也可以屏蔽,不过考虑到很多网站在“中英文之间加不加空格”这一问题上莫衷一是,中英混用的关键词效果往往不好。和搜索一样,使用的关键词越少、越短,能屏蔽的文章就越多,而一旦使用较长的关键词乃至词组,屏蔽效果虽然更精确,但范围也更小。本文所称的过滤其实是把文章直接设置成已读,而不会删除原文,您可以随时检查过滤效果并调整关键词粗细。

接下来是指定关键词适用的文件夹。NetNewsWire 支持根据文件夹分类整理各个订阅源,同样也可以将过滤功能定位到具体某个文件夹,避免伤及无辜。根据侧边栏中从上到下的排序,文件夹的编号从 0 开始,逐项加一,比如我要过滤的科技类文件夹“T100”排在第四项,其对应的文件夹 id 就是 folder id 3

Alt text
第四个文件夹的 id 是“3”

设置好关键词和文件夹后,接下来过滤操作本身没有任何特别之处,只需要使用快捷键 ‌⌃Control-⌥Option-⌘Command-R 即可开始过滤,视文章数量所需时间有所差异,从几秒到几十秒不等(以300 篇新文章、50 个关键词为例,大概需要十几秒)。分文件夹当然也起到了加快过滤速度的作用,每类文章只需要检查其专用的关键词,不用把所有过滤条件遍历一遍。

Alt text
过滤 NetNewsWire 中的文章

示例动作只针对一个文件夹,相应地也只设置了一组关键词,你可以自行添加多组关键词——如果不熟悉 AppleScript 代码,也没关系,直接将整篇代码拷贝几份、或者干脆多做几个动作,反正最后目的是过滤文章,代码写得漂亮与否无伤大雅。

最后,受益于 NetNewsWire 的 iCloud 功能,你也可以将过滤后的文章同步到 iOS 端,在手机和平板上也减少垃圾信息的骚扰。

Alt text
NetNewsWire 支持 iCloud 同步

本地过滤思路重述

实际上,NetNewsWire 并不具备“过滤”功能,其官网也看不到任何关于过滤、屏蔽的介绍。之所以可以在 NetNewsWire 中过滤文章,是借用了它的 AppleScript 套件(Suite),先筛选出关键词匹配的文章,再将这些文章标记为“已读”(Read),这样在仅显示未读文章的默认视图下,就间接实现了过滤功能。

Alt text
在 NetNewsWire 中可以只查看未读内容

这种对于文章自身状态的操控,其实启发了一种独特的 RSS 阅读模式:订阅帐号和过滤操作分开,避免吊死在在线服务的歪脖子树上。我们可以用一个订报纸的比喻来理解各种 RSS 阅读器的差异:

  1. 多数 RSS 阅读器客户端3,只是一个“信箱”,基本没有批处理能力,完全依靠充当“报社”角色的云端服务器,由后者包揽了从编辑内容(比如 NewsBlur 的标签过滤功能)到投递“报纸”的整个流程,包括 Feedly、Inoreader 等服务的客户端其实也是个“信箱”,主要的功能是被动接收信息;
  2. 支持主动批处理的通常是在线 RSS 阅读插件,或者干脆是自建的服务器,这些插件和服务好比是“阅览室”,能够主动“进货”并做一些整理(获取 RSS Feed 并分类、过滤),但是往往不可“离柜阅读”、过于依赖网络;
  3. 而 NetNewsWire(以及我现在使用的 DEVONthink)更像一位私人助理,其能力并不限于收取“报纸”,还可以通过 AppleScript 自动化地处理一部分内容,并且经由 iCloud 同步到其他设备上。

某种程度上,我们是将 NetNewsWire 当成了 RSS 服务器——而这种挪用也有代价,盖 NetNewsWire 不是张着嘴等待云端服务器来投喂,所以每次都是当场过滤,少则几秒,多则花费半分钟。但相对的,读者获得了一位永远可靠的、站在身边的信息助理。

另外,NetNewsWire 也不排斥在线服务,它支持添加 Inoreader、NewsBlur、Feedly、FeedBin、The Old Reader、BazQux 和 FreshRss 等主流 RSS 服务,除了享受这些服务本身的特性,你也可以采用同一帐号,以打通 Apple 环境和 Windows、Android 等操作系统。如果你不愿意使用在线服务的过滤功能,完全可以把 Mac 当成“RSS 编辑部”,过滤完毕后再同步到其他设备上。

小结

NetNewsWire 开发历史 将近 20 年,其间几近易手;2019 年原开发者重出江湖后,新版 NetNewsWire 获得了 MacStoriesGizmodo 等网站的一致高度评价。

但是,这些媒体所在乎通常是界面是否优美、能不能调整字号、支持的 RSS 服务多寡等问题4,这些细枝末节只是跟在 Reeder 后面“陪跑”,只能说明 Reeder 卖那么贵物有所值,而 NetNewsWire 除了免费身无长物。

事实是,NetNewsWire 的格局远比这些测评人所看到的要高。NetNewsWire 一步一个脚印地适配各种原生特性,从暗色模式、Big Sur 风格图标到本文的主角 AppleScript,有意无意中提供了一个非常自由的阅读环境:你可以什么都不做,导入订阅源后直接阅读,感觉就像在使用一款苹果自己开发的阅读器(即所谓的“白开水”风格);也可以折腾 AppleScript 过滤脚本和云同步,实现更个性化的 RSS 订阅。

附:完整代码下载

set rssFilters to {"TikTok", "Apple TV", "tvos", "arcade"}
set counter to 0
set l to {}

tell application "NetNewsWire"
    set ws to (get webFeed of folder id 3 of accounts) as item
    repeat with w in ws
        set t to (get article of w) as item
        repeat with tt in t
            --try
            set the end of l to tt
            --end try
        end repeat
    end repeat
    
    repeat with ll in l
        set tl to title of ll
        if read of ll is false then
            repeat with pp in rssFilters
                if pp is in tl then
                    set read of ll to true
                    set counter to counter + 1
                    exit repeat
                end if
            end repeat
        end if
    end repeat
    
end tell

display notification "Filter " & counter & " articles" sound name "Purr"

🛍 我撰写的付费栏目《信息管理,文件为本位的方案》正在 UNTAG 售卖,对本文话题有进一步讨论,欢迎选购。

🔗 付费栏目链接


  1. 换个角度想想也挺浪费时间的。
  2. NetNewsWire 曾在 2011 年被 Black Pixel 收购,2019 年原作者买回其知识产权后,将其另一款 RSS 阅读器 Evergreen 改名为 NetNewsWire 并持续更新至今。
  3. 再强调一下,这里指“客户端”而非背后的服务。
  4. 当前版本的 NetNewsWire 所支持的 RSS 服务已经相当多,字号也已经可以调整,界面美观则纯属个人好恶。

author_avatar

Lawyer, macOS/iOS Automation Amateur