feat: 通用采集+模板注入引擎:配置驱动多源采集,Jinja2 模板注入成文档,不绑定单机
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
---
|
||||
name: "morning-digest"
|
||||
description: "通用「数据采集 + 模板注入」引擎:用一份 YAML 配置声明多路数据源(http_json/command/static),采集后用 Jinja2 模板注入成 markdown 文档。适合日报/周报/聚合摘要,不绑定单台机器。"
|
||||
metadata:
|
||||
author: xf
|
||||
version: "2.0.0"
|
||||
---
|
||||
|
||||
# morning-digest — 通用采集 + 模板注入引擎
|
||||
|
||||
把「数据采集 → 模板注入 → 输出文档」抽象成一套**配置驱动**的通用 skill,不绑定任何具体机器/域名/IP。早报只是其一例用法,换一份配置即可复用到日报、周报、榜单、聚合摘要。
|
||||
|
||||
核心思路:**采集用脚本,排版用模板注入**,全程确定性,不依赖 LLM 排版。
|
||||
|
||||
## 流水线
|
||||
|
||||
```
|
||||
build.py --config config/digest.yaml
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 1. 读配置(YAML/JSON) │
|
||||
│ 2. ${ENV} 占位符替换(机器相关项从环境变量注入)│
|
||||
│ 3. 逐 source 采集(http_json / command / static_json)
|
||||
│ 4. Jinja2 模板注入 → 输出 markdown │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
```bash
|
||||
# 1. 准备环境变量(不写死进仓库)
|
||||
set -a; . ./.env; set +a
|
||||
|
||||
# 2. 一键采集 + 渲染
|
||||
python3 scripts/build.py --config config/morning-digest.yaml
|
||||
# 输出:/tmp/digest_today.md(配置里 render.output 决定)
|
||||
|
||||
# 只看数据不写文件
|
||||
python3 scripts/build.py --config config/morning-digest.yaml --dry-run
|
||||
|
||||
# 临时覆盖环境变量
|
||||
python3 scripts/build.py --config config/morning-digest.yaml --env HOT_API=http://localhost:6688
|
||||
```
|
||||
|
||||
## 配置文件结构(YAML)
|
||||
|
||||
```yaml
|
||||
meta:
|
||||
name: morning-digest
|
||||
date_format: "%Y-%m-%d"
|
||||
|
||||
sources:
|
||||
<section名>: # 会成为模板变量
|
||||
type: http_json | command | static_json
|
||||
# ...adapter 参数
|
||||
map: # 原始 item → 输出字段
|
||||
字段名: 表达式
|
||||
|
||||
render:
|
||||
template: templates/digest.md
|
||||
output: /tmp/xxx.md
|
||||
```
|
||||
|
||||
## Source 类型与适配器
|
||||
|
||||
### `http_json` — 拉一个 JSON 接口取列表
|
||||
```yaml
|
||||
news:
|
||||
type: http_json
|
||||
url: "https://host/api/{country}" # {param} 由 param_loop 填充
|
||||
param_loop: { key: country, values: [china, us] } # 可选:循环发多请求
|
||||
items_path: headlines # 响应里取列表的路径
|
||||
limit: 5
|
||||
map:
|
||||
title: "title|headline|name" # | 表示依次回退取第一个非空
|
||||
url: "url|link"
|
||||
source: "sourceLabel|{loop.country}" # {loop.key} = 当前循环值
|
||||
```
|
||||
|
||||
### `command` — 跑 shell 命令,读出 JSON
|
||||
```yaml
|
||||
github:
|
||||
type: command
|
||||
cmd: "python3 ${GITHUB_TRENDING_SCRIPT} {out}" # {out} = 临时 JSON 文件路径
|
||||
items_from_file: "{out}" # 从文件读(默认解析 stdout)
|
||||
map: { name: name, desc: desc, url: url, lang: lang, stars: stars, stars_today: stars_today }
|
||||
```
|
||||
|
||||
### `static_json` — 读本地文件(供 LLM/外部注入)
|
||||
```yaml
|
||||
tech:
|
||||
type: static_json
|
||||
file: "${TECH_FILE}" # 未设置则跳过(optional: true)
|
||||
map: { title: title, url: url, summary: summary }
|
||||
```
|
||||
|
||||
## map 取值表达式
|
||||
|
||||
- `a|b|c` — 依次尝试,取第一个非空字段
|
||||
- `{loop.key}` — 当前 param_loop 循环值
|
||||
- `@index` — 1 起始序号
|
||||
- 空串/缺失 → 该字段为空
|
||||
|
||||
## 模板
|
||||
|
||||
`templates/digest.md`(Jinja2)。每个 `source` 的 section 名成为一个模板变量(列表)。改排版只改模板,不动脚本。
|
||||
|
||||
早报模板里 GitHub Trending 已渲染成 markdown 超链接:
|
||||
|
||||
```
|
||||
**[org/name](https://github.com/org/name)**(lang):desc
|
||||
```
|
||||
|
||||
## 环境变量(`.env.example`)
|
||||
|
||||
机器相关项**一律从环境变量注入**,仓库不写死。
|
||||
|
||||
| 变量 | 说明 |
|
||||
|------|------|
|
||||
| `HOT_API` | DailyHotApi 基址 |
|
||||
| `GITHUB_TRENDING_SCRIPT` | GitHub Trending 采集脚本 |
|
||||
| `RSS_SCRIPT` | RSS 采集脚本 |
|
||||
| `TECH_FILE` | 科技动态注入 JSON(可选) |
|
||||
| `FEISHU_CREATE_SCRIPT` | 飞书知识库写入脚本(可选) |
|
||||
|
||||
## 失败隔离
|
||||
|
||||
每个 source 独立 try/except:失败 → 该 section 为空数组,错误写进输出 JSON 顶部的 `_errors`(不影响其他 source,流程不中断)。
|
||||
|
||||
## 依赖
|
||||
|
||||
- Python 3.10+(`requests`、`jinja2`、`pyyaml` 可选、`bs4` 视 source)
|
||||
- source 脚本(`${GITHUB_TRENDING_SCRIPT}`、`${RSS_SCRIPT}` 等)按各自配置
|
||||
|
||||
## 已知坑
|
||||
|
||||
- **github.com 直连间歇性超时**:GitHub Trending source 依赖直连官方页面,外网抖动时会空(记入 `_errors` 不中断)。
|
||||
- **海外 RSS DNS 吊死**:ak-rss-digest 用子进程隔离 + feedparser,个别源超时不影响整体。
|
||||
- **飞书写入幂等**:`create_digest.py` 同标题自动复用节点,不重复建文档。
|
||||
|
||||
## 扩展
|
||||
|
||||
想加数据源?在 `sources` 里加一个 section(选一种 adapter,配好 `map`)→ 在模板里用它,即可。无需改引擎。
|
||||
Reference in New Issue
Block a user