logo
0
0
WeChat Login
Chief<520@zut.edu.cn>
feat: 优化科技资讯推送系统并添加新功能

📰 科技资讯自动推送系统

基于 CNB 云原生构建平台打造的科技资讯自动化推送系统,每天早上8点自动抓取过去24小时的科技资讯并推送到微信。


✨ 核心特性

特性说明
🌐 多源聚合整合12个国内外顶级科技媒体源
🔄 智能去重基于文章内容的MD5去重机制
时间过滤仅抓取过去24小时内的新文章
💾 本地缓存利用CNB的volume功能实现持久化缓存
🚀 定时触发支持每天固定时间和手动触发
📦 任务分离抓取和推送任务独立,便于维护

📁 项目结构

24hNews/ ├── .cnb.yml # CNB 工作流配置文件(核心) ├── scripts/ │ ├── fetch_tech_news.py # 资讯抓取脚本 │ └── push_to_wechat.py # 微信推送脚本 ├── README.md # 项目文档 └── PROJECT_BLOG.md # 项目博客

🚀 快速开始

步骤 1️⃣ 获取 Server 酱密钥

访问 sct.ftqq.com 微信扫码登录,获取你的 SendKey


步骤 2️⃣ 配置密钥仓库

在 CNB 平台创建密钥仓库,添加环境变量配置文件:

# serverchan_key.yml SERVERCHAN_SENDKEY: "你的SendKey"

步骤 3️⃣ 配置 CNB 工作流

修改 .cnb.yml 中的导入路径:

imports: - cnb.cool/你的用户名/你的仓库名/-/blob/main/secrets/serverchan_key.yml

步骤 4️⃣ 推送到 CNB 平台

git add . git commit -m "Add CNB tech news workflow" git push origin main

就这么简单!✨


⚙️ 工作流触发方式

方式说明
🕐 定时触发每天早上8点自动执行(推荐)
📤 代码推送推送到 main 分支触发
👆 手动触发在 CNB 平台点击"手动触发"

🎛️ 自定义配置

修改推送时间

编辑 .cnb.yml 中的 cron 表达式:

schedule: - cron: "0 8 * * *" # 每天早上8点 # 改为每天早上9点 - cron: "0 9 * * *"

调整抓取参数

.cnb.yml 中修改环境变量:

stages: - name: 抓取科技资讯 env: HOURS_TO_FETCH: 24 # 抓取过去24小时 MAX_ARTICLES_PER_FEED: 8 # 每个源最多8篇 MAX_ARTICLES_TO_PUSH: 20 # 总共推送20篇

添加新的RSS源

编辑 scripts/fetch_tech_news.py

RSS_FEEDS = [ "https://36kr.com/feed", "https://your-new-feed.com/feed", # 添加新源 # ... 其他源 ]

🆚 CNB vs GitHub Actions

特性CNBGitHub Actions
配置文件单文件 .cnb.yml多文件 workflows
运行环境Docker 容器虚拟机/容器
本地缓存volumes 原生支持需要 actions/cache
密钥管理独立密钥仓库Repository Secrets
资源限制可自定义 CPU/内存固定规格

🏗️ 工作流原理

架构设计

┌─────────────────────────────────────────┐ │ CNB 触发器 (08:00) │ └────────────────┬────────────────────────┘ ↓ ┌─────────────────────────────────────────┐ │ Pull 代码仓库 │ └────────────────┬────────────────────────┘ ↓ ┌─────────────────────────────────────────┐ │ Docker 容器 (python:3.11-slim) │ └────────────────┬────────────────────────┘ ↓ ┌─────────────────────────────────────────┐ │ 阶段1: 安装依赖 │ └────────────────┬────────────────────────┘ ↓ ┌─────────────────────────────────────────┐ │ 阶段2: 抓取资讯 │ │ ├─ 从RSS源获取文章 │ │ ├─ 时间过滤(24小时内) │ │ ├─ 去重处理(本地缓存) │ │ └─ 保存到临时JSON文件 │ └────────────────┬────────────────────────┘ ↓ ┌─────────────────────────────────────────┐ │ 阶段3: 推送到微信 │ │ ├─ 读取临时JSON文件 │ │ ├─ 智能翻译(非中文内容) │ │ ├─ 生成Markdown摘要 │ │ └─ 通过Server酱推送到微信 │ └────────────────┬────────────────────────┘ ↓ ┌─────────────────────────────────────────┐ │ 工作流完成 ✅ │ └─────────────────────────────────────────┘

关键技术点

1. 持久化缓存

runner: volumes: - /cache/tech_news # CNB volume 功能

用于存储已推送文章的哈希值,避免重复推送。


2. 环境变量隔离

imports: - cnb.cool/tech-news-config/-/blob/main/secrets/serverchan_key.yml

密钥与代码分离,提高安全性。


3. 任务解耦

stages: - name: 抓取科技资讯 script: python scripts/fetch_tech_news.py - name: 推送到微信 script: python scripts/push_to_wechat.py

抓取和推送分离,便于独立调试和扩展。


🔧 故障排查

问题 1️⃣ 推送失败,提示未设置密钥

项目说明
原因密钥仓库配置错误或路径不正确
解决检查 .cnb.yml 中的 imports 路径,确认密钥仓库中存在 serverchan_key.yml,验证 SendKey 是否有效

问题 2️⃣ 没有文章推送

可能原因:

  • RSS源无法访问
  • 过去24小时没有新文章
  • 所有文章已被推送过

解决方案:

  1. 查看 CNB 工作流日志中的 RSS 解析状态
  2. 使用手动触发测试
  3. 检查 /cache/tech_news/pushed_articles.json 中的历史记录

问题 3️⃣ 重复推送相同文章

项目说明
原因缓存机制失效
解决检查 volume 路径配置是否正确,清空缓存重新运行,查看文章哈希生成逻辑是否正常

💡 高级用法

多环境部署

创建不同的密钥配置:

# 生产环境 - serverchan_key_prod.yml SERVERCHAN_SENDKEY: "生产环境Key" # 测试环境 - serverchan_key_test.yml SERVERCHAN_SENDKEY: "测试环境Key"

.cnb.yml 中根据分支选择配置:

main: push: imports: - cnb.cool/config/-/blob/main/prod/serverchan_key.yml staging: push: imports: - cnb.cool/config/-/blob/main/test/serverchan_key.yml

推送到多个平台

修改 scripts/push_to_wechat.py,添加其他推送方式:

def push_to_multiple_platforms(title: str, content: str): # 微信推送 send_to_wechat(title, content, sendkey) # 钉钉推送 send_to_dingtalk(title, content, webhook) # 邮件推送 send_to_email(title, content, email)

📊 监控和日志

CNB 平台日志

  1. 登录 CNB 平台
  2. 进入你的项目
  3. 查看工作流执行记录
  4. 点击具体的运行查看详细日志

本地测试

# 1. 安装依赖 pip install feedparser requests schedule # 2. 设置环境变量 export SERVERCHAN_SENDKEY="你的SendKey" # 3. 测试抓取 python scripts/fetch_tech_news.py # 4. 测试推送 python scripts/push_to_wechat.py

⚡ 性能优化

1️⃣ 增加并发抓取

使用多线程加速 RSS 抓取:

import concurrent.futures def fetch_all_feeds_concurrently(): with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: futures = [executor.submit(parse_rss_feed, url) for url in RSS_FEEDS] results = [f.result() for f in futures] return results

2️⃣ 使用 Docker 缓存镜像

.cnb.yml 中添加缓存配置:

stages: - name: 构建缓存 type: docker:cache options: dockerfile: cache.dockerfile by: - requirements.txt

🔒 安全建议

类型建议
🔑 密钥管理永远不要将 SendKey 提交到代码仓库,定期轮换密钥,使用独立的密钥仓库
🛡️ 访问控制限制 CNB 平台的访问权限,为不同环境设置不同的密钥
📝 日志脱敏避免在日志中输出密钥信息,对敏感信息进行脱敏处理

🤝 贡献指南

欢迎提交 Issue 和 Pull Request!


📄 许可证

MIT License


📬 联系方式

如有问题,请在 CNB 平台 或 GitHub Issues 中反馈。


Made with ❤️ by HunLi

2026年寒假