在实际内容创作和媒体发布领域自动化流程正从简单的脚本拼接演变为需要理解业务逻辑、处理多源数据、生成结构化内容并最终发布的复杂系统。一个典型的例子是如何将新闻报纸的编辑、排版、发布流程自动化。这不仅仅是技术上的“跑通”更涉及到内容获取、格式转换、样式渲染、版本控制和持续部署等多个环节的串联。本文将以一个基于 Claude API 和 GitHub Pages 的自动化报纸项目为蓝本深入剖析其背后的技术架构、实现细节和工程考量。我们将从零开始拆解如何构建这样一个自动化系统。适合的读者包括希望将重复性内容工作流程化的开发者、对 AI 辅助内容生成与静态站点发布结合感兴趣的技术爱好者以及任何想要了解现代自动化发布流水线如何落地的工程师。通过本文你将理解如何设计一个健壮的自动化 Routine处理常见的格式和样式问题并最终获得一个可自行运行、可监控、可扩展的自动化发布系统。1. 理解自动化报纸的核心组件与工作流一个自动化报纸系统其核心目标是将非结构化的信息源如 RSS 订阅、API 数据、爬虫结果或 AI 生成内容转化为结构化的、可读的、并具备固定发布周期的网页或文档。它不是一个简单的“定时任务”而是一个包含数据输入、内容处理、格式生成和最终发布的完整管道。1.1 核心工作流分解典型的自动化报纸工作流可以分解为以下四个主要阶段数据采集与聚合从多个预设的源新闻网站 RSS、特定 API、数据库收集原始内容。这一步的关键是稳定性和容错因为外部源可能不可用或格式发生变化。内容处理与增强这是系统的“大脑”。原始内容可能是纯文本、带混乱标签的 HTML 或 JSON 数据。需要对其进行清洗、摘要、分类甚至利用像 Claude 这样的大语言模型进行重写、风格统一或生成评论。处理后的内容需要被赋予统一的元数据如标题、作者可标记为“AI 编辑”、分类、发布时间和摘要。静态页面生成将处理后的结构化数据通常是 Markdown 或 JSON 文件通过静态站点生成器如 Jekyll, Hugo, Next.js转化为最终的 HTML、CSS 和 JavaScript 文件。这一步决定了报纸的最终外观和阅读体验。发布与部署将生成的静态文件推送到托管服务上。GitHub Pages 因其与 Git 工作流的无缝集成、免费及自动化部署能力成为个人或小型项目的理想选择。每次内容更新都对应一次 Git 提交和自动构建发布。1.2 为什么选择 Claude GitHub Pages 的组合Claude API提供了强大的自然语言理解和生成能力。相较于简单的文本拼接Claude 可以理解上下文执行诸如“将这篇技术文章改写成面向大众的科普风格”、“为这组新闻生成一个简短的每日摘要”、“检查并修正文本中的事实性错误需配合检索”等复杂指令。这使得自动化内容的质量和灵活性大幅提升。GitHub Pages它是一个基于 Git 的持续集成/持续部署CI/CD平台。开发者只需将静态文件或静态站点生成器的源代码推送到特定分支GitHub Actions 就会自动执行构建并将结果发布到线上。这完美契合了自动化流程我们的程序生成新内容并提交到仓库发布过程完全自动化。组合优势Claude 负责处理非结构化的、需要“智能”的部分GitHub Actions 负责结构化的、重复性的构建和发布任务。两者通过脚本连接形成了一个从“信息”到“成品”的端到端自动化管道。2. 环境准备与项目初始化在开始编写自动化 Routine 之前需要准备好所有依赖的环境和工具。我们将创建一个标准的项目目录结构。2.1 前置条件与工具清单确保你的开发环境中已安装以下工具工具/服务用途安装/注册指引Python 3.8编写主控脚本调用 API处理数据。从 python.org 下载。Git版本控制与 GitHub 交互。从 git-scm.com 下载。GitHub 账户代码仓库托管和 Pages 服务。在 github.com 注册。Anthropic Claude API 密钥调用 Claude 模型进行内容处理。在 console.anthropic.com 注册并获取。Jekyll / Hugo(可选)静态站点生成器。本文以 Jekyll 为例因其与 GitHub Pages 原生集成。gem install bundler jekyll2.2 项目目录结构初始化创建一个清晰的项目目录是保证后续脚本和配置可维护性的第一步。# 创建项目根目录 mkdir automated-newspaper cd automated-newspaper # 初始化 Git 仓库 git init # 创建核心目录结构 mkdir -p scripts # 存放 Python 自动化脚本 mkdir -p _data # 存放处理后的结构化数据 (Jekyll 数据目录) mkdir -p _posts # 存放最终生成的博客文章 (Markdown 文件) mkdir -p _layouts # 存放 Jekyll 布局模板 (可选) mkdir -p assets # 存放 CSS, 图片等静态资源 # 创建关键文件 touch scripts/news_fetcher.py # 数据采集脚本 touch scripts/content_processor.py # 内容处理脚本 (调用 Claude) touch scripts/publisher.py # 发布脚本 (Git 操作) touch Gemfile # Jekyll 依赖定义 touch _config.yml # Jekyll 配置文件 touch index.md # 网站首页 touch .gitignore # Git 忽略文件 touch README.md # 项目说明一个典型的.gitignore文件内容如下用于排除 API 密钥等敏感信息和 Python 虚拟环境# Python __pycache__/ *.py[cod] *$py.class .Python env/ venv/ .venv/ # API Keys and secrets .env *.key *.pem # Jekyll _site/ .sass-cache/ .jekyll-cache/ .jekyll-metadata # System .DS_Store Thumbs.db2.3 配置 Jekyll 静态站点在_config.yml中定义网站的基本信息这对于自动化生成内容的展示至关重要。# _config.yml title: 自动化日报 email: your-emailexample.com description: - 由 AI 驱动自动采集、处理并发布的每日新闻摘要。 baseurl: # 如果发布到项目 Pages格式为 /repo-name url: https://yourusername.github.io # 你的 GitHub Pages 地址 # 构建设置 markdown: kramdown theme: minima # 使用 Jekyll 默认主题也可换用其他 plugins: - jekyll-feed - jekyll-seo-tag # 自定义变量 author: AI Editor pagination: 5 # 首页每页显示文章数在Gemfile中指定依赖确保 GitHub Actions 能使用相同的环境构建。# Gemfile source https://rubygems.org gem jekyll, ~ 4.3 gem minima, ~ 2.5 gem jekyll-feed, ~ 0.17 gem jekyll-seo-tag, ~ 2.8 group :jekyll_plugins do gem jekyll-feed gem jekyll-seo-tag end运行bundle install来安装本地依赖用于测试。3. 构建自动化内容处理管道这是整个系统的核心。我们将编写三个 Python 脚本分别负责获取数据、处理内容和发布更新。3.1 数据采集脚本 (news_fetcher.py)这个脚本负责从外部源获取原始数据。这里以抓取一个 RSS 源为例。我们使用feedparser和requests库。# 安装必要的 Python 库 pip install feedparser requests beautifulsoup4 python-dotenv首先将敏感的 API 密钥存储在环境变量中。创建一个.env文件务必加入.gitignore# .env ANTHROPIC_API_KEYyour_actual_claude_api_key_here然后编写采集脚本# scripts/news_fetcher.py import feedparser import requests from bs4 import BeautifulSoup import json from datetime import datetime import os from urllib.parse import urlparse def fetch_rss_feed(feed_url): 从给定的 RSS URL 抓取内容 print(f正在抓取 RSS 源: {feed_url}) feed feedparser.parse(feed_url) articles [] for entry in feed.entries[:5]: # 限制每次抓取5条避免过量 article { source_title: feed.feed.get(title, Unknown Source), original_title: entry.get(title, No Title), original_link: entry.get(link, #), original_summary: entry.get(summary, entry.get(description, )), published: entry.get(published, entry.get(updated, datetime.now().isoformat())), fetched_at: datetime.now().isoformat(), # 可选尝试获取更干净的内容 cleaned_content: clean_article_content(entry.get(link)) } articles.append(article) return articles def clean_article_content(article_url): 尝试从原文链接获取更干净的正文内容可选更复杂 try: headers {User-Agent: Mozilla/5.0 (Automated Newspaper Bot)} resp requests.get(article_url, headersheaders, timeout10) soup BeautifulSoup(resp.content, html.parser) # 简单的清理策略移除脚本、样式标签获取段落文本 for tag in soup([script, style, nav, footer]): tag.decompose() main_content soup.find(article) or soup.find(main) or soup.body if main_content: text .join(main_content.stripped_strings)[:2000] # 限制长度 return text except Exception as e: print(f清理内容时出错 {article_url}: {e}) return None if __name__ __main__: # 示例抓取 Hacker News 的 RSS hn_rss_url https://news.ycombinator.com/rss articles fetch_rss_feed(hn_rss_url) # 将抓取的数据保存为 JSON供下一个处理阶段使用 output_path os.path.join(os.path.dirname(__file__), .., _data, raw_articles.json) os.makedirs(os.path.dirname(output_path), exist_okTrue) with open(output_path, w, encodingutf-8) as f: json.dump(articles, f, ensure_asciiFalse, indent2) print(f已抓取 {len(articles)} 篇文章保存至 {output_path})注意网络爬虫应遵守网站的robots.txt规则并设置合理的请求间隔和 User-Agent。对于生产环境需要考虑代理、重试、缓存等机制。3.2 内容处理脚本 (content_processor.py)这是与 Claude API 交互的核心。脚本读取原始数据调用 Claude 进行摘要、改写或分类然后生成适合 Jekyll 的 Markdown 文件。# scripts/content_processor.py import json import os from datetime import datetime from anthropic import Anthropic from dotenv import load_dotenv import time # 加载环境变量中的 API 密钥 load_dotenv() api_key os.getenv(ANTHROPIC_API_KEY) if not api_key: raise ValueError(请在 .env 文件中设置 ANTHROPIC_API_KEY) client Anthropic(api_keyapi_key) def process_with_claude(raw_article, system_prompt): 调用 Claude API 处理单篇文章 user_message f 请根据以下原始文章信息生成一份适合在技术日报中发布的摘要。 要求 1. 语言中文。 2. 风格简洁、客观、信息量大。 3. 结构先给出一个吸引人的标题不要直接复制原标题然后是3-4个要点的摘要最后附上原文链接。 4. 长度摘要部分控制在150字左右。 原始信息 标题{raw_article[original_title]} 来源{raw_article[source_title]} 链接{raw_article[original_link]} 摘要/内容{raw_article.get(cleaned_content) or raw_article[original_summary]} try: response client.messages.create( modelclaude-3-haiku-20240307, # 使用成本较低的 Haiku 模型也可用 Sonnet max_tokens500, systemsystem_prompt, messages[{role: user, content: user_message}] ) return response.content[0].text except Exception as e: print(f调用 Claude API 处理文章失败: {e}) return None def generate_jekyll_post(processed_content, raw_article): 将处理后的内容格式化为 Jekyll 博文 Markdown 文件 # Jekyll 要求文件名格式: YYYY-MM-DD-title.md date_str datetime.now().strftime(%Y-%m-%d) # 从 Claude 的回复中提取第一行作为标题假设第一行是标题 title_line processed_content.split(\n)[0].strip() # 简单清理标题中的 Markdown 标记 title title_line.replace(#, ).strip() safe_title .join(c for c in title if c.isalnum() or c in ( , -, _)).rstrip().replace( , -) filename f{date_str}-{safe_title}.md filepath os.path.join(os.path.dirname(__file__), .., _posts, filename) front_matter { layout: post, title: title, date: f{date_str} {datetime.now().strftime(%H:%M:%S)} 0800, categories: [daily-news], # 可让 Claude 分类这里写固定值 author: AI Editor, source: raw_article[source_title], original_link: raw_article[original_link] } content f--- layout: {front_matter[layout]} title: {front_matter[title]} date: {front_matter[date]} categories: {front_matter[categories]} author: {front_matter[author]} source: {front_matter[source]} original_link: {front_matter[original_link]} --- {processed_content} os.makedirs(os.path.dirname(filepath), exist_okTrue) with open(filepath, w, encodingutf-8) as f: f.write(content) print(f已生成文章文件: {filepath}) return filepath if __name__ __main__: system_prompt 你是一个专业的技术新闻编辑擅长将冗长的技术文章提炼成精炼的每日简报。 raw_data_path os.path.join(os.path.dirname(__file__), .., _data, raw_articles.json) with open(raw_data_path, r, encodingutf-8) as f: raw_articles json.load(f) for article in raw_articles[:3]: # 每次处理3篇控制成本和速度 print(f处理文章: {article[original_title][:50]}...) processed_text process_with_claude(article, system_prompt) if processed_text: generate_jekyll_post(processed_text, article) time.sleep(1) # 避免 API 速率限制 print(内容处理完成。)3.3 发布脚本 (publisher.py)这个脚本负责将生成的新文章提交到 Git 仓库并推送到 GitHub触发 GitHub Pages 的自动构建。# scripts/publisher.py import os import subprocess import sys from datetime import datetime def run_git_command(cmd_list, cwdNone): 执行 Git 命令并返回结果 try: result subprocess.run(cmd_list, capture_outputTrue, textTrue, checkTrue, cwdcwd) return result.stdout.strip() except subprocess.CalledProcessError as e: print(fGit 命令执行失败: { .join(cmd_list)}) print(f错误输出: {e.stderr}) return None def main(): # 设置仓库路径为项目根目录 repo_path os.path.abspath(os.path.join(os.path.dirname(__file__), ..)) # 检查 _posts 目录是否有新文件 posts_dir os.path.join(repo_path, _posts) new_files [f for f in os.listdir(posts_dir) if f.endswith(.md)] if not new_files: print(_posts 目录下没有新的 Markdown 文件无需发布。) sys.exit(0) # 切换到仓库目录 os.chdir(repo_path) # 1. 添加所有更改 print(添加更改到 Git 暂存区...) run_git_command([git, add, .]) # 2. 提交 commit_message fAuto-update: {datetime.now().strftime(%Y-%m-%d %H:%M)} print(f提交更改: {commit_message}) run_git_command([git, commit, -m, commit_message]) # 3. 推送到远程仓库 (假设远程仓库名为 origin分支为 main) print(推送更改到 GitHub...) run_git_command([git, push, origin, main]) print(发布完成GitHub Pages 将自动开始构建。) if __name__ __main__: main()4. 整合与调度创建自动化 Routine现在我们需要将上述三个脚本串联起来并设置定时任务形成一个完整的自动化 Routine。4.1 创建主控脚本 (main.py)在主目录下创建一个main.py按顺序调用各个模块。# main.py import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), scripts)) # 导入各阶段脚本的函数假设已将脚本重构为函数式 from news_fetcher import fetch_rss_feed, save_raw_articles from content_processor import process_articles_batch from publisher import publish_changes def main(): print( 开始自动化报纸流程 ) # 阶段1采集 print(\n[阶段1] 数据采集...) feed_url https://news.ycombinator.com/rss # 可配置化 raw_articles fetch_rss_feed(feed_url) save_raw_articles(raw_articles) # 阶段2处理 print(\n[阶段2] 内容处理...) process_articles_batch(raw_articles[:3]) # 处理前3条 # 阶段3发布 print(\n[阶段3] 发布更新...) publish_changes() print(\n 自动化流程执行完毕 ) if __name__ __main__: main()4.2 使用 GitHub Actions 实现定时调度本地定时任务如 cron不适合长期运行且受本地机器限制。最佳实践是使用 GitHub Actions 的定时任务功能。在项目根目录创建.github/workflows/daily-paper.yml# .github/workflows/daily-paper.yml name: Daily Newspaper Automation on: schedule: # 每天 UTC 时间 00:00 运行 (北京时间 08:00) - cron: 0 0 * * * workflow_dispatch: # 允许手动触发 push: branches: [ main ] # 推送时也运行用于测试 jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkoutv4 with: token: ${{ secrets.GITHUB_TOKEN }} - name: Set up Python uses: actions/setup-pythonv5 with: python-version: 3.10 - name: Install Python dependencies run: | pip install feedparser requests beautifulsoup4 python-dotenv anthropic - name: Install Jekyll dependencies run: | gem install bundler bundle install - name: Run automation script env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: | python main.py - name: Build Jekyll site run: bundle exec jekyll build - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pagesv3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./_site关键配置说明on.schedule.cron: 定义了自动运行的时间表。0 0 * * *表示每天 UTC 零点运行。workflow_dispatch: 允许在 GitHub Actions 页面手动触发工作流便于测试。secrets.ANTHROPIC_API_KEY: 需要在 GitHub 仓库的 Settings - Secrets and variables - Actions 中添加一个名为ANTHROPIC_API_KEY的 Secret值为你的 Claude API 密钥。这是保护敏感信息的安全做法。peaceiris/actions-gh-pages: 一个流行的 Action用于将_site目录下的构建结果部署到gh-pages分支从而更新 GitHub Pages。5. 运行验证与结果检查5.1 本地测试流程在配置 GitHub Actions 之前务必在本地完整测试一遍流程。环境变量在项目根目录创建.env文件并填入 API 密钥。安装依赖pip install -r requirements.txt # 如果创建了该文件 bundle install手动运行python main.py本地构建 Jekyllbundle exec jekyll serve访问http://localhost:4000查看生成的报纸网站。检查 Git 状态运行git status查看是否有新生成的_posts/*.md文件被添加。可以手动git push测试。5.2 验证 GitHub Actions 运行将代码推送到 GitHub 仓库的main分支。进入仓库的Actions标签页你应该能看到Daily Newspaper Automation工作流。点击Run workflow手动触发一次观察各步骤是否成功绿色对勾。工作流成功后访问你的https://username.github.io/repo-name查看更新后的网站。5.3 预期输出成功运行后你的_posts目录下会生成类似这样的 Markdown 文件--- layout: post title: 深度解析新一代开源数据库的性能突破 date: 2023-10-27 08:00:00 0800 categories: [daily-news] author: AI Editor source: Hacker News original_link: https://example.com/original-article --- ## 新一代开源数据库性能大幅提升 近日一款名为“XXDB”的开源数据库发布了其 2.0 版本在基准测试中表现出色。 **核心要点** - 查询延迟平均降低 40%尤其在复杂联表查询场景下。 - 引入了新的存储引擎支持实时数据分析与事务处理混合负载。 - 社区活跃已有多个大型科技公司开始在生产环境中试用。 [... 更多摘要内容 ...] *原文链接[点击查看](https://example.com/original-article)*你的 GitHub Pages 网站首页将按时间倒序列出这些自动生成的文章。6. 常见问题排查与优化自动化流程在运行中会遇到各种问题以下是一些典型场景的排查路径。6.1 内容生成相关问题问题现象可能原因检查与解决方式Claude API 返回空或错误1. API 密钥无效或过期。2. 请求超时或网络问题。3. 提示词Prompt不符合模型要求。1. 检查ANTHROPIC_API_KEY环境变量是否正确设置。2. 在脚本中加入更详细的错误捕获和日志。3. 简化 Prompt 进行测试确保指令清晰。生成的内容格式混乱提示词中对输出格式的约束不够强。在系统提示词中更严格地规定输出格式例如“请严格按照以下 Markdown 格式输出## 标题\n\n要点1...\n\n要点2...”。处理速度慢或触发速率限制免费或低层级 API 有速率限制。在content_processor.py的循环中加入time.sleep(1)或更长间隔。考虑使用异步请求或批量处理 API如果支持。6.2 构建与部署相关问题问题现象可能原因检查与解决方式GitHub Actions 工作流失败1. 依赖安装失败。2. Python 脚本执行错误。3. 密钥Secrets未正确配置。1. 查看 Actions 运行日志找到失败的具体步骤和错误信息。2. 检查requirements.txt或Gemfile中的版本兼容性。3. 确认仓库 Settings 中已配置ANTHROPIC_API_KEYSecret。网站无更新1. 脚本未成功生成新文件。2. Git 提交/推送失败。3.gh-pages分支未成功更新。1. 检查 Actions 日志中“Run automation script”步骤的输出看是否有新文章生成。2. 检查 Git 操作步骤的日志。3. 查看gh-pages分支的最后提交时间。本地jekyll serve正常但线上样式丢失GitHub Pages 使用的 Jekyll 版本或插件与本地不一致。确保Gemfile中指定的主题和插件是 GitHub Pages 支持的。可参考 官方文档 。最简单的办法是使用remote_theme配置。6.3 数据源与稳定性问题问题现象可能原因检查与解决方式RSS 源抓取失败1. 网站屏蔽或限制。2. RSS 链接失效。3. 网络超时。1. 在请求头中添加合理的User-Agent。2. 实现重试机制如tenacity库。3. 考虑使用备用数据源。抓取的内容质量差RSS 源只提供摘要无全文。启用clean_article_content函数但需谨慎尊重版权和robots.txt或寻找提供全文 RSS 的源。7. 生产环境最佳实践与扩展方向将个人项目升级为更稳定、可维护的生产系统需要考虑以下几点。7.1 安全性增强密钥管理绝对不要将 API 密钥硬编码在脚本中或提交到仓库。始终使用环境变量或类似 GitHub Secrets 的服务。输入消毒对从外部源获取的任何文本在传递给 Claude API 或写入文件前进行基本的消毒处理防止注入攻击。权限控制GitHub Actions 工作流使用的GITHUB_TOKEN默认具有读写权限。如果仓库是公开的考虑将其权限限制为最小必要范围。7.2 可靠性提升错误处理与重试在网络请求、API 调用、文件操作等环节加入完整的try-except块并实现指数退避重试逻辑。日志记录不要只使用print。集成logging模块将不同级别的日志输出到文件并可在 GitHub Actions 中查看。数据备份定期备份_data/raw_articles.json和_posts/目录下的内容到其他存储如 Git 标签、对象存储防止误操作丢失。健康检查可以创建一个简单的健康检查端点或脚本定期验证网站可访问且内容在更新。7.3 功能扩展多数据源集成多个 RSS 源、News API、甚至爬取特定 Twitter 列表或 Reddit 板块。内容分类让 Claude 除了摘要外还对文章进行分类如“人工智能”、“区块链”、“编程语言”并自动生成分类页面。个性化根据用户偏好如果有多用户系统过滤或排序新闻。多格式输出不仅生成网页还可以让 Claude 生成一份简短的文本摘要通过 Telegram Bot 或电子邮件发送。人工审核环节在自动发布前将生成的内容先提交到一个“待审核”分支人工确认后再合并到主分支触发发布。7.4 成本与性能优化缓存策略对于频繁抓取的源可以将原始内容缓存一段时间避免重复处理相同文章。模型选择根据任务复杂度选择合适的 Claude 模型。haiku模型速度快、成本低适合摘要sonnet或opus模型能力更强适合需要深度分析或创造性写作的任务。提示词工程精心设计系统提示词System Prompt是控制输出质量和成本的关键。清晰、具体的指令能减少无效的 token 消耗。通过以上步骤你不仅搭建了一个自动化的“报纸”系统更掌握了一套将 AI 能力与现有开发运维工具Git, CI/CD结合的标准方法。这套方法可以迁移到任何需要定期、自动处理信息并发布的内容流水线上。