改造豆瓣小组,帖子按照日期分组显示
最近在活跃更新远程工作者的微信公众号,这些招聘信息,除了分享到公众号,也会同步到豆瓣小组等渠道,之前豆瓣都是每月发一条内容,现在是每个招聘信息发布一条内容,帖子的数量就急剧增加了。
为了管理方便,我想要按照日期分组来决定当天是否还要发布更多信息(通常一天发布五条),不过豆瓣的帖子显示并没有分组的功能,每次都要数呀数,犯懒的狗哥我只能是自己动手改造豆瓣小组了。
之前做过一个辅助小组新成员审核的油猴脚本,这次依然是使用油猴脚本,先给大家看一下改造效果,豆瓣小组是按最后回复时间倒序显示帖子的,那么分组就比较容易了。
脚本流程梳理
脚本的逻辑很简单,主要分为三步:
- 获取小组帖子列表,逐条解析出“最后回复”时间的文本
- 解析文本为日期对象,然后提取出日期的部分,例如 2025-05-24
- 在日期变化时,给该条帖子增加边框高亮,以在视觉上达到分组效果
匹配网址获取列表
我需要匹配小组首页以及更多讨论列表,虽然首页还有“最热讨论”和“精华讨论”,按照上面的方法分组,会有一些副作用,不过我们自用的话,可以不用考虑。
总结了一下小组的列表页面的网址,做了下面四个匹配项,分别应对有无 Query Parameters 的情况(比如分页参数等)。
// @match https://www.douban.com/group/*/
// @match https://www.douban.com/group/*/?*
// @match https://www.douban.com/group/*/discussion
// @match https://www.douban.com/group/*/discussion?*
小组首页和更多讨论也得帖子列表表格结构类似,只是表格的容器不同,所以在获取时,稍微做一下兼容。
const discussionItems = document.querySelectorAll('#group-topics table.olt tbody tr, #content .article table.olt tbody tr');
这样就可以拿到各种情况下的帖子列表了。
解析日期并分组
获取表格行列表后,遍历并取得最后回复时间,然后解析日期,在日期变更时改变行样式即可达到视觉分组效果。
// 用于存储当前遍历到的日期,用于日期变更判定
let currentDate;
discussionItems.forEach((item) => {
const lastReplyTimeElement = item.querySelector('.time');
const lastReplyTime = new Date(lastReplyTimeElement.textContent.trim());})
const dateString = lastReplyTime.toISOString().split('T')[0];
// 日期变更后改变样式
if (dateString !== currentDate) {
item.style.borderTop = "1px solid #6ba3ff";
currentDate = dateString;
}
})
完整脚本
// ==UserScript==
// @name 豆瓣小组 - 日期分组显示
// @namespace https://anl.gg/
// @version 1.0
// @description Group discussion list by last reply date.
// @icon https://www.google.com/s2/favicons?sz=64&domain=douban.com
// @author greatghoul
// @match https://www.douban.com/group/*/
// @match https://www.douban.com/group/*/?*
// @match https://www.douban.com/group/*/discussion
// @match https://www.douban.com/group/*/discussion?*
// @grant none
// ==/UserScript==
(function() {
'use strict';
const discussionItems = document.querySelectorAll('#group-topics table.olt tbody tr, #content .article table.olt tbody tr');
if (discussionItems.length === 0) {
return;
}
let currentDate;
discussionItems.forEach((item) => {
const pinned = item.querySelector('span.pl');
if (pinned) {
return;
}
const lastReplyTimeElement = item.querySelector('.time');
if (!lastReplyTimeElement) {
return;
}
const lastReplyTime = new Date(lastReplyTimeElement.textContent.trim());
const dateString = lastReplyTime.toISOString().split('T')[0];
if (dateString !== currentDate) {
item.style.borderTop = "1px solid #6ba3ff";
currentDate = dateString;
}
});
})();
油猴扩展和脚本安装,可以参考 https://www.bilibili.com/video/BV1xmLvzwEJi/
文章同步发表于微信公众号老狗拾光,欢迎关注。