update @2021.12.24: 

由于Todoist限制免费用户项目数量、IFTTT限制免费用户任务数,不适合后续对有价值视频的存档,因此作者用Cubox替代了Todoist的功能:监控脚本直接通过Cubox的API创建记录,可以不使用IFTTT和Todoist

 

现状

作为一个B站重度使用用户,曾经关注里躺着几百UP,每天睡前会无数次下拉首页刷新防止错过更新,视频列表刷不到尽头,动态里面更是天天99+。

实际上,B站的视频我只想按照UP的维度来获取更新,或者喜欢的只是UP的某一个系列,除此之外最多加上每周必看,然而几百的关注严重干扰了视频更新时间线,我又不可能靠首页推荐算法随机捕捉,加上平时洗漱的无聊时间又不想错过更新,于是,我需要一个简明扼要的方式,告诉我谁什么时间更新了什么

核心诉求和思路

UP的名字、投稿时间和投稿标题基本上可以确认我要不要看;

根据视频内容或者UP来源,分类到不同优先级的列表下;

可以快速记录看、看过和不看。

总体上看,我需要的是一个实时监控UP投稿并且分类成不同的列表的方案,简单拆分下。

监控部分,关心的是UP的投稿。可以直接轮询B站的API、可以用第三方RSS。这里选择RSSHub,优点是不用重复开发,也不用关心B站的API,缺点是被墙和有一定的延迟。

记录部分,我们把一个投稿看成TODO类应用的Inbox事件,这个问题就简单多了。这里直接用todoist的列表就可以解决分类和记录问题。为了更好的分类,这里引入IFTTT的Webhook

实现和一些细节

先上结果

未看视频列表

左边是项目,根据我的规则,这是按照UP来分类的,右边是投稿内容,如果不看,直接点小圆点就会消失,如果要现在看,点开项目,点击bilibili://video/[ID]这个URLSchema即可在iOS平台下面直接拉起bilibili并播放(我刷B站的主力是iPad)

点击并观看,自动跳转

下面一步一步说明它是怎么实现的

0. 基础组件

可以访问RSSHub(有墙)和IFTTT的WebhookURL的服务,可以是墙外的VPS,可以是云函数等服务

另外,写好从RSSHub拉取更新的代码,以及推送到IFTTT WebHookURL的代码(如果你想用我的也可以,下拉到最后贴了地址)

下面我们用一个🌰来说下我的完整的流程,其中,通过DB记录是可选的,你完全可以用本地文件(xml,json)的方式来实现

1. 核心流程

例如我想收到TESTV的投稿通知,首先我要知道他的UID,访问其B站主页https://space.bilibili.com/11336264,后面的这个11336264就是UID。

然后去https://todoist.com/app/#start上添加一个项目,记住它的名字,比如评测区

在IFTTT上创建(https://ifttt.com/create)一个将Webhook转发到Todoist的Applets,这里详细描述一下:

创建IFTTT触发事件

点击+This后,在搜索框中输入Webhooks,点击后会出现Receive a web request选项(也是唯一的选项),选它

找到Webhooks

之后会让你输入event_name,这个event_name会出现在你的WebhookURL中,建议与你想要做的分类相关,我们最后会用不同的WebhookURL推送到不同的Todoist项目。

比如我这里填:bili_tech_test

Event Name相当于分类标签

点击Create trigger后,就会回到/create的界面,我们继续点击+That

找到要做的动作:Todoist

这次我们找到Todoist,表示被做的事情,同样,它应该也只有一个选项,叫做Create Task

project就是我们在Todoist上的项目,选择它表示在这里创建任务

重点是TaskContent,这个是标题,ValueN这三个模板变量,是你发给WebhookURL的参数,可控(点Add ingredient来输入这种模板变量,或者用双大括号)

描述生成Todoist任务的参数

 

最后点击Create action,再点击Finish

完成IFTTT

那么,往哪里发送Webhook请求呢?点开https://ifttt.com/maker_webhooks,这里有与你Webhook有关的所有Applets,点击右上角的Documentation,你会得到一个与Key和Event有关的URL,这里Event就是上面第一步填的EventName,Key是与用户有关的字符串,可以看到,这里valueN都是可以指定的

Documentation查看自己的回调地址

3. 同步数据

我创建了一个DB(代码里有),用于表示我从哪个URL拉取内容,推送到哪个URL

Fetcher表结构
Fetcher的内容:每个关注UP

另外一张表,记录拉取到的投稿,这两步骤是分开的

Bilivideo表结构
Bilivideo的内容:投稿记录

 

在代码中,这个流程就是:

1. 从fetcher表中按上次运行时间时间获取RSSHub的地址

2. 拿到RSSHub中的更新内容,如果不存在,就放到bilivideo表中,新创建的记录标记为未推送

3. 遍历Bilivideo没有推送的投稿,向IFTTT的WebHookURL发送请求,返回成功后,在DB中更新状态表示已经推送过


 

3. 定时
 

将同步代码放到VPS上,crontab配个1min执行一次,就等着数据上门就好了,或者使用云函数方式也可替代这个步骤

*/1 *
 * 
* *
 /usr/bin/python3.6 /root/scf/bili2ifttt.py >> /root/scf/bili2iftt.log &

4. 细节和注意事项

理论上,你可以随意指定来源,例如非Webhook来源的URL,根据fetch_method做区分就可以了。

不同的分类需要创建不同的IFTTT Event Name,用不同的WebHookURL来区分。

同样,DB也不是最佳方案,它显得笨重了,如果仅仅是需要几个更新,完全可以用XML/JSON保存到本地文件的方式来完成,本质上,这里只是需要一个存储+去重方案,XML/JSON本身也是DB的一种形式,大家都一样。

bilibili://这种唤起方式叫做URLSchema,理论上其他设备有类似的方案,不过我没有安卓和Win设备,不太清楚。

你还有可能遇到一些问题,比如脚本执行太快,且数据获取的时候没有加锁,导致未推送的内容推送了多次,这个解决方案很多,各人按照情况来吧,只要你的脚本执行时间小于运行间隔时间就好。

IFTTT的所有步骤,可以在APP上操作,但是,建议在Web上创建,手机上用于修改Project和启用停用。

Todoist有每个项目300的上限,如果到了300,就会导致推送失败,IFTTT会把这个Applets关掉,这时候需要删掉一些任务,然后重新启用。

最后不知道大家有没有注意到,crontab的这个任务的执行目录中是有一个scf的,这是之前跑脚本是用的scf(腾讯云云函数),它替代了vps的这个步骤(crontab),要不是它每小时2块钱的扣费(请求量太大了)和一些奇奇怪怪的bug我还会继续用它QwQ

 

最后

工具是为需求服务的,不要本末倒置,这里用了RSSHub+IFTTT纯属个人选择较为熟悉的工具,并不代表这个方案最佳。
 

这个工作流已经正常运行大半年了,从我个人的体验上看,我可以每天下班回来打开iPad就看到谁更新了什么,根据自己的喜好点开看,看完就接着点下一个,也不需要关心是否错过投稿,它实现了一个按照分类查看未看投稿的功能

这期间,我把关注从400+降到了10-,动态也干净了很多,之前用来拖延、下拉首页的时间可以用来睡觉。

最后回顾来看,将关心的内容明确,最重要的是减少了算法推送的触达率,起码我个人认为这些算法推荐的基本上没什么营养,顶多也就是乐呵乐呵,与其这样,不如把关心的内容看完就走,把这些时间拿去刷刷网课(shui)看看书(jiao),它不香吗?

代码在这里: lc4t's GitHub