添加按订阅导出文章的参数设置

This commit is contained in:
2026-08-30 15:50:07 +08:00
parent 146350565c
commit 8f5043759f
2 changed files with 52 additions and 16 deletions

View File

@@ -1,7 +1,7 @@
---
name: blogwatcher-daily
description: RSS 订阅监控 + 文章管理 + 导出。使用 RSSHub + feedparser 抓取订阅,自动去重入库 SQLite;支持按单个订阅更新/查看/标记已读/删除文章,可将文章按 txt/markdown/html 导出。附「自然语言操作指南」,AI 智能体可直接把用户口语映射到 CLI 命令。
version: 1.4
version: 1.5
category: custom
tags: [rss, blog, monitoring, automation, export]
metadata:
@@ -219,9 +219,13 @@ python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
# 全库最新 20 篇 → 纯文本
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--export txt --limit 20
# 单订阅最新 20 篇 → Markdown(按订阅名或 --list 序号)
python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
--export markdown --sub "异次元软件世界" --limit 20
```
**过滤规则**(`--date` 与 `--limit` 的组合语义)
**过滤规则**(`--date` / `--limit` / `--sub` 的组合语义)
| 参数组合 | 行为 |
|---------|------|
@@ -229,6 +233,12 @@ python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
| `--export FMT --date X` | 指定日期 X 的所有文章 |
| `--export FMT --limit N` | 忽略日期,取**全库最新 N 篇** |
| `--export FMT --date X --limit N` | 日期 X 的最新 N 篇 |
| `--export FMT --sub SUB` | 该订阅**全部**文章(`--sub` 也会让默认日期失效) |
| `--export FMT --sub SUB --limit N` | 该订阅最新 N 篇 |
| `--export FMT --sub SUB --date X` | 该订阅在日期 X 的文章 |
| `--export FMT --sub SUB --date X --limit N` | 该订阅在日期 X 的最新 N 篇 |
> `--sub` 的 SUB 参数解析规则与 `--articles / --update / --mark-read / --delete` 完全一致(序号 → 精确 → 忽略大小写精确 → 忽略大小写子串),详见「订阅标识(SUB)」。
**参数速查**
@@ -237,6 +247,7 @@ python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py \
| `--export {txt,markdown,html}` | 触发导出模式并指定格式 |
| `--date YYYY-MM-DD` | 目标日期(本地时区,默认今天) |
| `--limit N` | 文章数上限;单独使用时忽略日期 |
| `--sub SUB` | 只导出该订阅的文章(SUB=`--list` 序号或名称) |
**输出去向**
@@ -315,6 +326,9 @@ python3 ~/.hermes/skills/custom/blogwatcher-daily/scripts/blogwatcher-daily.py
| "把今天的文章导出成 markdown"、"生成今日摘要 md" | `--export markdown` |
| "导出 2026-08-28 的 HTML"、"我要那天的网页版" | `--export html --date 2026-08-28` |
| "最新 20 篇导出为 txt"、"给我全库最新 20 篇" | `--export txt --limit 20` |
| "把异次元软件世界的文章导成 markdown"、"只导 Engadget 的" | `--export markdown --sub "SUB"` |
| "导出异次元最新 20 篇 md"、"给我 Slashdot 最近 20 条 html" | `--export markdown --sub "SUB" --limit 20` |
| "把 X 昨天的文章导出成 html" | `--export html --sub "SUB" --date YYYY-MM-DD` |
| "今天的文章导 html 到桌面" | `--export html > ~/Desktop/$(date +%Y-%m-%d).html` |
### 订阅标识(SUB)如何解析
@@ -427,7 +441,7 @@ cronjob --create \
### 导出(`--export`)
1. **查询**:`fetch_articles()` 按 `date(fetched_at, 'localtime')` 过滤 + 可选 `LIMIT N`
1. **查询**:`fetch_articles()` 按 `date(fetched_at, 'localtime')` 过滤 + 可选 `feed_url` 按订阅过滤(`--sub`)+ 可选 `LIMIT N`
2. **分组**:`_group_by_channel()` 按 `channel_title` 分桶
3. **格式化**:`FORMATTERS[fmt]` 分发到 `format_txt` / `format_markdown` / `format_html`
4. **输出**:正文写 stdout,`📊 N 篇文章 → FMT` 进度写 stderr

View File

@@ -29,6 +29,7 @@ Usage:
python3 blogwatcher-daily.py --export markdown # 把今天的文章导出为 Markdown
python3 blogwatcher-daily.py --export html --date 2026-08-28
python3 blogwatcher-daily.py --export txt --limit 20
python3 blogwatcher-daily.py --export markdown --sub "异次元软件世界" --limit 20 # 单订阅最新 20 篇
订阅标识(SUB):
可传 --list 输出中的整数序号(如 3),也可传订阅名(精确 → 忽略大小写精确 → 忽略大小写包含)。
@@ -437,8 +438,9 @@ def delete_articles_for_subscription(sub, article_index=None):
return True
# ========== 导出 ==========
def fetch_articles(target_date=None, limit=None):
"""从 articles 表读取;可选按本地日期过滤(date(fetched_at,'localtime'))+ 可选限制数量"""
def fetch_articles(target_date=None, limit=None, feed_url=None):
"""从 articles 表读取;可选按本地日期过滤(date(fetched_at,'localtime'))
+ 可选按订阅 feed_url 过滤 + 可选限制数量。"""
if not os.path.exists(DB_PATH):
print(f"❌ 数据库不存在: {DB_PATH}", file=sys.stderr)
return []
@@ -446,11 +448,15 @@ def fetch_articles(target_date=None, limit=None):
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
where = ""
conditions = []
params = []
if target_date:
where = "WHERE date(fetched_at, 'localtime') = ?"
conditions.append("date(fetched_at, 'localtime') = ?")
params.append(target_date)
if feed_url:
conditions.append("feed_url = ?")
params.append(feed_url)
where = ("WHERE " + " AND ".join(conditions)) if conditions else ""
query = f"""
SELECT channel_title, title, link, description, pub_date, fetched_at
@@ -550,14 +556,21 @@ FORMATTERS = {
"html": format_html,
}
def export_articles(fmt, target_date, limit):
articles = fetch_articles(target_date, limit)
def export_articles(fmt, target_date, limit, sub=None):
feed_url = sub['url'] if sub else None
articles = fetch_articles(target_date, limit, feed_url=feed_url)
label_parts = []
if sub:
label_parts.append(sub['name'])
if target_date:
label = target_date
elif limit:
label = f"最新 {limit} 篇"
else:
label = "全部"
label_parts.append(target_date)
if limit:
label_parts.append(f"最新 {limit} 篇")
if not label_parts:
label_parts.append("全部")
label = " — ".join(label_parts)
print(f"📊 {len(articles)} 篇文章 → {fmt}", file=sys.stderr)
sys.stdout.write(FORMATTERS[fmt](articles, label))
@@ -585,6 +598,8 @@ def main():
parser.add_argument('--date', help='导出的目标日期 YYYY-MM-DD(默认今天,仅 --export 有效)')
parser.add_argument('--limit', type=int,
help='导出的文章数上限;单独使用时忽略日期取全库最新 N 篇(仅 --export 有效)')
parser.add_argument('--sub', metavar='SUB',
help='与 --export 搭配:只导出指定订阅的文章(SUB=--list 序号或名称)')
args = parser.parse_args()
@@ -592,6 +607,8 @@ def main():
parser.error("--unread 必须与 --articles 一起使用")
if args.article_id is not None and not args.delete:
parser.error("--article-id 必须与 --delete 一起使用")
if args.sub and not args.export:
parser.error("--sub 必须与 --export 一起使用")
global RSSHUB_BASE
if args.rsshub:
@@ -642,13 +659,18 @@ def main():
sys.exit(1)
elif args.export:
sub = None
if args.sub:
sub = find_subscription(args.sub)
if not sub:
sys.exit(1)
if args.date:
target_date = args.date
elif args.limit:
elif args.limit or sub:
target_date = None
else:
target_date = date.today().isoformat()
export_articles(args.export, target_date, args.limit)
export_articles(args.export, target_date, args.limit, sub=sub)
else:
scan_all(force_all=args.all)