LINUX DO 论坛安全自动阅读脚本

用于 LINUX DO (Discourse 架构) 社区的自动刷阅读量脚本,内置分段平滑滚动、随机停留时间等防封限速策略。

#type / snippet #status / evergreen #tech / dev / frontend #resource / javascript #platform / browser

[!info] related notes

LINUX DO 论坛安全自动阅读脚本

本篇笔记提供适用于 LINUX DO(基于 Discourse 社区架构)的网页自动阅读脚本。为了避免频繁请求触发服务器的防爬虫与速率限制(429 Too Many Requests),脚本内置了分段平滑滚动和随机化延迟等防封策略。 一个是刷主题 一个是刷帖子(一层楼(回复)就是一个帖子)

[!info] tip 发现linuxdo 升级的帖子指的是 一个回复,右侧有蓝点,消失了就算阅读了一个帖子,所以只需要在一个很多回复的帖子里下拉就行。


防封限速版 (Tampermonkey / Userscript)(跨主题)

推荐版本。大幅拉长了停留时间,并进行分段物理平滑滚动,使行为在后端审计日志中表现得更像人类。

建议直接将其添加为 Tampermonkey 等用户脚本管理插件中的新脚本:

// ==UserScript==
// @name         LINUX DO Safe Auto Reader
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  LINUX DO 论坛安全自动阅读脚本,防封限速平滑模拟版
// @author       Antigravity
// @match        https://linux.do/*
// @grant        none
// @run-at       document-end
// ==UserScript==

(function safeAutoRead() {
    // --- 配置参数 ---
    const MIN_STAY = 20000;         // 最小停留 20 秒(Discourse 判定有效阅读时间的保守阈值)
    const MAX_STAY = 45000;         // 最大停留 45 秒
    const SCROLL_PROBABILITY = 0.8; // 80% 的概率会发生物理滚动行为
    
    console.log("%c脚本已启动:安全阅读模式", "color: green; font-weight: bold;");

    async function start() {
        // 1. 获取未读帖子链接 (优先寻找带有 unread 或 new-topic 标识的帖子)
        let posts = Array.from(document.querySelectorAll('.topic-list-item.unread .title, .topic-list-item.new-topic .title'));
        
        // 如果没找到未读标识的,就找普通标题
        if (posts.length === 0) {
            posts = Array.from(document.querySelectorAll('.topic-list-item .title'));
        }

        if (posts.length === 0) {
            console.log("未找到帖子,向下滚动并等待加载...");
            window.scrollBy(0, 800);
            setTimeout(start, 3000);
            return;
        }

        // 随机选择一个目标
        const targetPost = posts[Math.floor(Math.random() * posts.length)];
        const postTitle = targetPost.innerText.trim();
        console.log(`%c准备进入:${postTitle}`, "color: blue;");
        
        targetPost.click();

        // 2. 进入帖子后的模拟行为
        setTimeout(() => {
            console.log("正在模拟阅读中...");
            
            // 模拟分段平滑滚动
            if (Math.random() < SCROLL_PROBABILITY) {
                let currentScroll = 0;
                const maxScrolls = Math.floor(Math.random() * 4) + 3; // 滚动 3-7 次
                
                const scrollTask = setInterval(() => {
                    const distance = Math.floor(Math.random() * 400) + 200; // 每次滚动 200-600 像素
                    window.scrollBy({ top: distance, behavior: 'smooth' });
                    currentScroll++;
                    if (currentScroll >= maxScrolls) clearInterval(scrollTask);
                }, Math.floor(Math.random() * 3000) + 2000); // 每 2-5 秒滚一次
            }

            // 3. 随机停留后返回
            const stayTime = Math.floor(Math.random() * (MAX_STAY - MIN_STAY)) + MIN_STAY;
            console.log(`计划停留时间:${(stayTime / 1000).toFixed(1)} 秒`);

            setTimeout(() => {
                console.log("阅读完成,返回列表...");
                if (window.location.pathname !== '/') {
                    window.history.back();
                }
                
                // 返回列表后,给页面一点加载时间再继续下一次
                setTimeout(start, Math.floor(Math.random() * 5000) + 3000);
            }, stayTime);

        }, 2500); // 等待页面加载的缓冲
    }

    // 仅在列表页(例如最新、未读等列表)触发
    if (window.location.pathname === '/' || window.location.pathname.startsWith('/c/') || window.location.pathname.startsWith('/latest')) {
        // 给页面初步渲染留出时间后再执行
        setTimeout(start, 3000);
    }
})();

单个帖子滚动

(function optimizedSmoothScroll() {
    const scrollStep = 2;        // 步长
    const scrollInterval = 40;   // 间隔
    const retryDelay = 2000;     // 检测到终点后,等待新内容加载的缓冲时间(毫秒)
    
    let isWaiting = false;

    const scrollTimer = setInterval(() => {
        if (isWaiting) return;

        window.scrollBy(0, scrollStep);

        // 判断是否触及当前页面底部
        if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 5) {
            isWaiting = true;
            const currentHeight = document.body.offsetHeight;

            console.log("检测到页面底部,等待新内容加载…");

            // 延迟一段时间后检查高度是否变化
            setTimeout(() => {
                if (document.body.offsetHeight > currentHeight) {
                    // 高度增加了,说明有新内容,继续滚动
                    isWaiting = false;
                    console.log("检测到新内容,继续滚动。");
                } else {
                    // 高度没变,说明真的到底了
                    clearInterval(scrollTimer);
                    console.log("确认已到达全站最底部,脚本停止。");
                }
            }, retryDelay);
        }
    }, scrollInterval);

    window.scrollTimer = scrollTimer;
    console.log("优化版脚本已启动:支持动态加载内容检测。");
})();

使用建议与避坑指南

  1. 缓慢运行:linuxdo 的帖子 429 问题应该是 在一定时间内阅读大量内容才会触发,所以在使用单个帖子滚动时要让速度足够慢,实测当前默认设置不会触发
创建于 2026/7/11 更新于 2026/7/19