大家好。AI 确实太强了,闲着没事就折腾了一下。 感觉最近大家年底了都忙着上班搬砖,但是论坛里的瓜又特别多,一不留神就错过了。 为了方便自己快速“补课”,我让 AI 帮我搓了个脚本,自动把每天最火的帖子抓下来(目前就是一第一页),这样再忙也能一眼看今天的瓜。可以把时间改短一点,最近在瞎折腾 Python,想着能不能把自己手里的闲置小鸡利用起来。
突发奇想写了个脚本,功能很简单:每天自动扫描 NodeSeek 的第一页 50个帖子,算一下热度,生成一张“今日词云”和“热搜榜单”,自动发到 Telegram。

代码逻辑比较简单粗暴(就是暴力翻页 + 正则提取),不依赖复杂的网页结构分析,主打一个**“能跑就行”**。

发出来给有需要的兄弟玩玩,代码写得比较烂,求大佬们轻喷,顺便看看哪里能优化!🙏


1. 环境准备 (Debian/Ubuntu)

需要安装 Python3、Chrome 环境(DrissionPage需要)和中文字体(不然词云是乱码)。
直接复制下面这行命令一把梭:

apt updateapt install -y python3-pip chromium fonts-noto-cjkpip install requests DrissionPage jieba wordcloud --break-system-packages

2. 脚本代码

新建一个文件,比如叫 ns_daily.py,把下面代码粘进去。

⚠️ 注意: 代码开头的 BOT_TOKENCHAT_ID 记得改成你自己的!

import requestsfrom DrissionPage import ChromiumPage, ChromiumOptionsimport jiebafrom wordcloud import WordCloudimport datetimeimport reimport timeimport random# ================= 配置区域 =================# 1. 去 @BotFather 申请一个机器人拿到 TokenBOT_TOKEN = '这里填你的BotToken' # 2. 去 @userinfobot 获取你的数字 IDCHAT_ID = '这里填你的ChatID'# ===========================================def send_telegram_package(img_path, caption):    """推送到 Telegram"""    url = f"[https://api.telegram.org/bot](https://api.telegram.org/bot){BOT_TOKEN}/sendPhoto"    try:        with open(img_path, 'rb') as f:            data = {'chat_id': CHAT_ID, 'caption': caption, 'parse_mode': 'Markdown'}            files = {'photo': f}            requests.post(url, data=data, files=files)            print(">>> ✅ 推送成功!")    except Exception as e:        print(f"!!! 发送失败: {e}")def run():    # 配置无头浏览器    co = ChromiumOptions()    co.set_browser_path('/usr/bin/chromium') # Linux 默认路径    co.headless(True)    co.set_argument('--no-sandbox')    co.set_argument('--disable-gpu')    # 伪装一下 User-Agent    co.set_user_agent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36')    page = ChromiumPage(co)    raw_posts = []    try:        print(">>> 🚀 启动抓取 (范围: 前15页)...")        base_url = '[https://www.nodeseek.com/](https://www.nodeseek.com/)'                # 暴力扫前 15 页,覆盖全天内容        TOTAL_PAGES = 15                for page_num in range(1, TOTAL_PAGES + 1):            try:                # 拼 URL 翻页                url = base_url if page_num == 1 else f"{base_url}?page={page_num}"                page.get(url)                # 随机延时,像个真人一样                time.sleep(random.uniform(1.5, 3))                                 titles = page.eles('.post-title')                if not titles:                    print(f"⚠️ 第 {page_num} 页没抓到数据,跳过")                    continue                                print(f"--- 正在扫描第 {page_num} 页 ({len(titles)}贴) ---")                for t in titles:                    try:                        title_text = t.text                        link = t.attr('href')                        # 修复链接拼接逻辑                        if not link.startswith('http'):                            link = f"[https://www.nodeseek.com](https://www.nodeseek.com){link}"                                                # 暴力提取回复数 (从整行文本找最大数字)                        replies = 0                        try:                            row_text = t.parent().text                            nums = re.findall(r'\d+', row_text)                            # 过滤年份和ID,取剩下的最大值                            valid_nums = [int(n) for n in nums if int(n) < 3000]                             # 再次过滤掉太大的数字(可能是uid),一般回复没那么多                            real_nums = [n for n in valid_nums if n < 2000]                            if real_nums:                                replies = max(real_nums)                        except:                            pass                        if len(title_text) > 2:                            # 简单的热度加权算法:                            # 越靠前的页码,基础分越高 (新鲜度加分)                            # 最终分 = 真实回复数 + 新鲜度加分                            freshness_score = (TOTAL_PAGES - page_num) * 2                            final_score = replies + freshness_score                                                        raw_posts.append({                                'title': title_text,                                'link': link,                                'replies': replies,                                'score': final_score                            })                    except:                        continue            except Exception as e:                print(f"翻页出错: {e}")                continue                print(f"\n>>> 采集结束,共 {len(raw_posts)} 个帖子,正在计算排名...")        if raw_posts:            # 按分数倒序排列            raw_posts.sort(key=lambda x: x['score'], reverse=True)                        # --- 1. 生成词云 (取前150个标题) ---            top_titles = [p['title'] for p in raw_posts[:150]]            text_pool = " ".join(top_titles)                        # 简单的屏蔽词            ignore = ['求助', '大佬', '问题', '有没有', '怎么', '什么', '就是', '觉得', '帖子', '回复', '积分', '元', '出', '收', '还是', '现在', '知道', '今天', '可以', '多少', '感觉', '甚至', '或者', '一下', '便宜', '因为', '所以', '看到']            words = jieba.lcut(text_pool)            clean = [w for w in words if len(w) > 1 and w not in ignore and not w.isdigit()]                        # 字体路径 (Debian/Ubuntu 默认位置)            font = '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc'            wc = WordCloud(font_path=font, width=1200, height=800, background_color='white', colormap='Dark2').generate(" ".join(clean))                        filename = "ns_hot.png"            wc.to_file(filename)                        # --- 2. 发送 Telegram 榜单 ---            today = datetime.date.today()            caption = f"📅 **NodeSeek 24H 热度榜 ({today})**\n"            caption += f"🔥 数据源: 全站前 {TOTAL_PAGES} 页\n\n"                        # 取 Top 12            for i, post in enumerate(raw_posts[:12]):                rank = i + 1                icon = "🔥"                if rank == 1: icon = "🥇"                if rank == 2: icon = "🥈"                if rank == 3: icon = "🥉"                                # 格式:排名. 图标 [标题](链接) (回复数)                caption += f"{rank}. {icon} [{post['title']}]({post['link']}) `({post['replies']}回)`\n"            caption += "\n#NS自动推送 #每日总结"            send_telegram_package(filename, caption)        else:            print("!!! 没抓到数据,检查网络")    except Exception as e:        print(f"!!! 运行崩溃: {e}")    finally:        page.quit()if __name__ == "__main__":    run()

3. 运行方法

python3 ns_daily.py

没报错的话,你的手机应该就会收到图片和榜单了。

也可以加到 crontab 里每天5个小时跑一次,当做日报看。


碎碎念:
本来想写个精确识别时间的正则,但是不同设备显示的时间格式太乱了(什么昨天、1天前、10 min ago...),实在搞不定。
后来一想,反正排在前 15 页的肯定是最新的,索性直接按页码倒推新鲜度,没想到效果还挺好 😂。

抛砖引玉,有大佬能优化代码的话求指点!
觉得好用的兄弟给加个鸡腿呗~ 🍗