Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 12 additions & 62 deletions .github/workflows/crawler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,23 @@ name: Get Hot News
on:
schedule:
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# ⚠️ 试用版说明 / Trial Mode
# 每日一次推送 GitHub Trending + Hacker News
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
#
# 🔄 运行机制 / How it works:
# - 每个周期为 7 天,届时自动停止
# - 运行 "Check In" 会重置周期(重新开始 7 天倒计时,而非累加)
# - Each cycle is 7 days, then auto-stops
# - "Check In" resets the cycle (restarts 7-day countdown, not cumulative)
# ⚠️ cron 用的是 UTC 时间,北京时间 = UTC + 8
# "11 2 * * *" → UTC 02:11 = 北京时间 10:11
#
# 💡 设计初衷 / Why this design:
# 如果 7 天都忘了签到,或许这些资讯对你来说并非刚需
# 适时的暂停,能帮你从信息流中抽离,给大脑留出喘息的空间
# If you forget for 7 days, maybe you don't really need it
# A timely pause helps you detach from the stream and gives your mind space
# 📝 想改成别的时间,把小时数换成 (目标北京时间 - 8),负数则 +24:
# 北京 08:00 → "0 0 * * *" 北京 12:30 → "30 4 * * *"
# 北京 20:00 → "0 12 * * *" 北京 07:00 → "0 23 * * *"(前一天 UTC)
#
# 🙏 珍惜资源 / Respect shared resources:
# GitHub Actions 是平台提供的公共资源,每次运行都会消耗算力
# 签到机制确保资源分配给真正需要的用户,感谢你的理解与配合
# GitHub Actions is a shared public resource provided by the platform
# Check-in ensures resources go to those who truly need it — thank you
# ⚠️ GitHub 的定时任务不准时:平台高峰期常延迟 5~15 分钟,实际到达约 10:11~10:30
#
# 🚀 长期使用请部署 Docker 版本 / For long-term use, deploy Docker version
# ⚠️ 注意:GitHub 只在【默认分支】上触发 schedule,改这里必须提交到 master 才生效
# 想先验证,用 Actions 页面的 "Run workflow" 手动触发(可选分支)
#
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
#
# 📝 修改运行时间:只改第一个数字(0-59),表示每小时第几分钟运行
# 📝 Change time: Only modify the first number (0-59) = minute of each hour
#
# 示例 / Examples:
# "15 * * * *" → 每小时第15分钟 / minute 15 every hour
# "30 0-14 * * *" → 北京时间 8:00-22:00 每小时第30分钟 / Beijing 8am-10pm
#
- cron: "33 * * * *"
- cron: "11 2 * * *"

workflow_dispatch:

Expand All @@ -45,7 +29,6 @@ concurrency:

permissions:
contents: read
actions: write

jobs:
crawl:
Expand All @@ -59,41 +42,6 @@ jobs:
fetch-depth: 1
clean: true

- name: Check Expiration
env:
GH_TOKEN: ${{ github.token }}
run: |
WORKFLOW_FILE="crawler.yml"
API_URL="repos/${{ github.repository }}/actions/workflows/$WORKFLOW_FILE/runs"

TOTAL=$(gh api "$API_URL" --jq '.total_count')
if [ -z "$TOTAL" ] || [ "$TOTAL" -eq 0 ]; then
echo "No previous runs found, skipping expiration check"
exit 0
fi

LAST_PAGE=$(( (TOTAL + 99) / 100 ))
FIRST_RUN_DATE=$(gh api "$API_URL?per_page=100&page=$LAST_PAGE" --jq '.workflow_runs[-1].created_at')

if [ -n "$FIRST_RUN_DATE" ]; then
CURRENT_TIMESTAMP=$(date +%s)
FIRST_RUN_TIMESTAMP=$(date -d "$FIRST_RUN_DATE" +%s)
DIFF_SECONDS=$((CURRENT_TIMESTAMP - FIRST_RUN_TIMESTAMP))
LIMIT_SECONDS=604800

if [ $DIFF_SECONDS -gt $LIMIT_SECONDS ]; then
echo "⚠️ 试用期已结束,请运行 'Check In' 签到续期"
echo "⚠️ Trial expired. Run 'Check In' to renew."
gh workflow disable "$WORKFLOW_FILE"
exit 1
else
DAYS_LEFT=$(( (LIMIT_SECONDS - DIFF_SECONDS) / 86400 ))
echo "✅ 试用期剩余 ${DAYS_LEFT} 天,到期前请运行 'Check In' 签到续期"
echo "✅ Trial: ${DAYS_LEFT} days left. Run 'Check In' before expiry to renew."
fi
fi


# --------------------------------------------------------------------------------
# 🚦 TRAFFIC CONTROL / 流量控制
# --------------------------------------------------------------------------------
Expand Down Expand Up @@ -166,6 +114,8 @@ jobs:
S3_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
S3_ENDPOINT_URL: ${{ secrets.S3_ENDPOINT_URL }}
S3_REGION: ${{ secrets.S3_REGION }}
# 使用 GitHub/HN 专用关键词文件(config/custom/keyword/github.txt)
FREQUENCY_WORDS_PATH: github.txt
GITHUB_ACTIONS: true
run: uv run python -m trendradar

Expand Down
86 changes: 50 additions & 36 deletions config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,39 +66,46 @@ platforms:
api_url: "" # 热榜数据 API 地址(留空使用默认地址)
# 如果你自行部署了 newsnow,填入你的地址,如: https://your-domain.com/api/s
sources:
- id: "toutiao"
name: "今日头条"
expected_domain: "toutiao.com"
- id: "baidu"
name: "百度热搜"
expected_domain: "baidu.com"
- id: "wallstreetcn-hot"
name: "华尔街见闻"
expected_domain: "wallstreetcn.com"
- id: "thepaper"
name: "澎湃新闻"
expected_domain: "thepaper.cn"
- id: "bilibili-hot-search"
name: "bilibili 热搜"
expected_domain: "bilibili.com"
- id: "cls-hot"
name: "财联社热门"
expected_domain: "cls.cn"
- id: "ifeng"
name: "凤凰网"
expected_domain: "ifeng.com"
- id: "tieba"
name: "贴吧"
expected_domain: "baidu.com"
- id: "weibo"
name: "微博"
expected_domain: "weibo.com"
- id: "douyin"
name: "抖音"
expected_domain: "douyin.com"
- id: "zhihu"
name: "知乎"
expected_domain: "zhihu.com"
# GitHub 每日热门仓库(newsnow 源 id: github-trending-today)
# 返回数据带 star 数和项目简介
- id: "github-trending-today"
name: "GitHub 热门"
expected_domain: "github.com"

# ── 以下为原中文热榜源,已注释停用。想恢复某个,去掉行首 # 即可 ──
# - id: "toutiao"
# name: "今日头条"
# expected_domain: "toutiao.com"
# - id: "baidu"
# name: "百度热搜"
# expected_domain: "baidu.com"
# - id: "wallstreetcn-hot"
# name: "华尔街见闻"
# expected_domain: "wallstreetcn.com"
# - id: "thepaper"
# name: "澎湃新闻"
# expected_domain: "thepaper.cn"
# - id: "bilibili-hot-search"
# name: "bilibili 热搜"
# expected_domain: "bilibili.com"
# - id: "cls-hot"
# name: "财联社热门"
# expected_domain: "cls.cn"
# - id: "ifeng"
# name: "凤凰网"
# expected_domain: "ifeng.com"
# - id: "tieba"
# name: "贴吧"
# expected_domain: "baidu.com"
# - id: "weibo"
# name: "微博"
# expected_domain: "weibo.com"
# - id: "douyin"
# name: "抖音"
# expected_domain: "douyin.com"
# - id: "zhihu"
# name: "知乎"
# expected_domain: "zhihu.com"



Expand Down Expand Up @@ -136,10 +143,11 @@ rss:
url: "http://www.ruanyifeng.com/blog/atom.xml"
enabled: false # 禁用
# max_age_days: 3 # 示例:推送 3 天内的文章(更新较慢的博客)

- id: "yahoo-finance"
name: "雅虎财经"
url: "https://finance.yahoo.com/news/rssindex"
enabled: false # 禁用(只保留 GitHub + Hacker News)

# 自定义源示例
# - id: "custom-feed"
Expand All @@ -158,9 +166,11 @@ report:
# current = 当前榜单,按时推送当前在榜的匹配新闻(持续在榜的每次都出现)
# incremental = 增量监控,只推送新增内容,零重复(没有新增时不推送)

display_mode: "keyword" # 分组维度
display_mode: "platform" # 分组维度
# keyword = 按关键词分组显示
# platform = 按平台/来源分组显示
# 此处用 platform:catch-all 关键词下所有条目同属一组,
# 按关键词分组会挤成一坨,按来源分组更清晰

sort_by_position_first: false # 关键词模式排序(仅 display_mode=keyword 时生效)
# true = 按 frequency_words.txt 的定义顺序
Expand Down Expand Up @@ -244,8 +254,12 @@ display:

# 独立展示区:将指定平台/RSS 完整展示,不受关键词过滤
# 推送展示由 regions.standalone 控制,AI 分析由 ai_analysis.include_standalone 控制
# ⚠️ 本方案未使用独立展示区(regions.standalone = false)
# 原因:standalone 的数据不参与"是否有内容可推"的判断
# (见 trendradar/__main__.py 的 has_any_content),单靠它会导致完全不推送。
# 改用 catch-all 关键词让全部条目走正常的 hotlist/rss 区域。
standalone:
platforms: ["zhihu", "wallstreetcn-hot"] # 热榜平台 ID 列表(如 ["zhihu", "weibo"])
platforms: [] # 热榜平台 ID 列表(如 ["zhihu", "weibo"])
rss_feeds: [] # RSS 源 ID 列表(如 ["hacker-news"])
max_items: 20 # 每个源最多展示条数(0=不限制)

Expand Down
48 changes: 48 additions & 0 deletions config/custom/keyword/github.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# ═══════════════════════════════════════════════════════════════
# GitHub Trending + Hacker News 专用关键词配置
# ═══════════════════════════════════════════════════════════════
#
# 用途:配合 config.yaml 的 platforms/rss 配置,每日推送
# GitHub 热门仓库 + Hacker News 头条
#
# 由 .github/workflows/crawler.yml 的环境变量指定:
# FREQUENCY_WORDS_PATH: github.txt
#
# ───────────────────────────────────────────────────────────────
# 为什么用 catch-all 而不是具体关键词?
# ───────────────────────────────────────────────────────────────
#
# GitHub 仓库名和 Hacker News 标题都是英文(如 "huggingface /
# speech-to-speech"),而默认的 config/frequency_words.txt 里几乎
# 全是中文关键词,匹配率接近 0。
#
# 更关键的是:推送开关(trendradar/__main__.py 的 has_any_content)
# 只看【关键词匹配结果】,独立展示区(standalone)的数据不算。
# 也就是说关键词一条都没匹配上时,整个推送会被跳过。
#
# 所以这里用 /.*/ 匹配全部条目,等价于"不过滤,全都要"。
#
# ───────────────────────────────────────────────────────────────
# 想只看特定方向的项目?
# ───────────────────────────────────────────────────────────────
#
# 把下面 [每日热点] 整组替换成你关心的词,例如只看 AI 和 Rust:
#
# [AI 项目]
# /\b(ai|llm|agent|rag|gpt|diffusion)\b/
#
# [Rust 项目]
# /\brust\b/
#
# 注意:改成具体关键词后,没有匹配的那天就不会推送(这是预期行为)
#
# ═══════════════════════════════════════════════════════════════


[GLOBAL_FILTER]


[WORD_GROUPS]

[每日热点]
/.*/