
1. 从一条新闻到一句话这个工具到底解决什么问题刷新闻最烦的不是没内容而是内容太多。一条深度报道动辄三四千字你只想花十秒知道谁、干了什么、结果如何却得先滑过三段背景铺垫和两段专家点评。我平时做技术选题一天要扫几十条链接靠肉眼读根本不现实于是就想用 Python 把这件事自动化给一个新闻 URL程序抓正文、丢给大模型、吐回一句不超过 50 字的总结。这个一句话总结新闻工具的核心链路只有四步输入新闻 URL → 抓取正文 → 调用大模型 API 生成摘要 → 输出一句话总结。听起来简单但真正动手会撞上三个坑第一每家模型厂商的 API Key、Base URL、请求格式都不一样换一个模型就要改一遍代码第二网页正文提取没有万能选择器不同站点结构差异极大第三Prompt 写不好模型要么总结成三句话要么把导语原样抄回来。这篇面向 Python 开发者从零跑通整条链路。重点不是教你注册某个平台而是用 TaoToken 统一通道把多模型切换这件事一次性解决——你只维护一个 Key、一个 Base URL模型名当参数传想换就换。适合谁会写基础 Python、想快速接大模型 API、又不想被各家 SDK 差异折腾的人。下面直接给可复制的 config.toml 骨架、请求封装代码和一句话总结 Prompt 模板最后用样例新闻验证输出并排查常见错误。2. TaoToken 前置准备一个 Key 打通多模型通道2.1 为什么用统一通道而不是直连各家直连的问题很具体。假设你今天用 A 家的模型明天想对比 B 家的摘要质量代码里base_url、api_key、model三处都要改环境变量还得再加一个。项目里如果同时用两三个模型配置会迅速失控。TaoToken 的思路是把这些差异收敛到一层对外暴露 OpenAI 兼容接口你只填一个 API Key 和一个 Base URL模型名通过参数传入。对一句话总结新闻这种需要反复试不同模型找最佳摘要效果的场景这个抽象非常省事。需要说明的是TaoToken 是合规的 API 聚合通道不是让你绕过什么限制它做的就是统一接口、统一计费、统一 Key 管理。你调用的是它转发到各模型厂商的标准接口用法和直连官方 SDK 完全一致。2.2 拿到 Key 和 Base URL先去控制台创建 API Key地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。创建后复制那串sk-开头的字符串只显示一次丢了就重新建。Base URL 固定为https://taotoken.net/api注意这个地址后面不加 UTM 参数直接写进代码即可。它兼容 OpenAI 的/v1/chat/completions路径所以你可以直接用官方openai这个 Python 包把base_url指过来就行不需要装任何私有 SDK。如果你还没决定用哪个模型可以先到模型对话页面手动试几条新闻看看哪个模型的摘要风格合你口味https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。试好之后把模型名记下来填进后面的配置。2.3 环境与依赖Python 3.9 以上即可。依赖只有四个requests抓网页、beautifulsoup4加lxml解析 HTML、openai调接口。一条命令装完pip install requests beautifulsoup4 lxml openaiKey 不要硬编码进代码用环境变量。Linux/macOS 下export TAOTOKEN_API_KEYsk-你的keyWindows PowerShell$env:TAOTOKEN_API_KEYsk-你的key3. 可复制配置config.toml 骨架与请求封装3.1 config.toml 骨架把易变的东西抽到配置文件代码只读配置。新建config.toml[api] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY default_model gpt-4o-mini timeout 30 [summarize] max_input_chars 4000 temperature 0.3 max_tokens 120 [fetch] user_agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 timeout 15 min_paragraph_len 20api_key_env存的是环境变量名而不是 Key 本身这样配置文件可以安全提交到仓库。default_model先随便填一个后面验证时再换成你在对话页面试好的模型。Python 3.11 起标准库自带tomllib低版本用pip install tomli即可。3.2 请求封装一个函数搞定所有模型核心是把 OpenAI 客户端包一层模型名当参数传import os import tomllib from openai import OpenAI def load_config(path: str config.toml) - dict: with open(path, rb) as f: return tomllib.load(f) def build_client(cfg: dict) - OpenAI: api_key os.getenv(cfg[api][api_key_env]) if not api_key: raise ValueError(f环境变量 {cfg[api][api_key_env]} 未设置) return OpenAI( api_keyapi_key, base_urlcfg[api][base_url], timeoutcfg[api][timeout], ) def summarize(text: str, client: OpenAI, cfg: dict, model: str None) - str: model model or cfg[api][default_model] max_chars cfg[summarize][max_input_chars] if len(text) max_chars: text text[:max_chars] system_prompt ( 你是一位专业新闻编辑。请严格遵循以下规则\n 1. 用一句话总结新闻核心内容不超过50字\n 2. 必须包含主体谁 事件做了什么/发生了什么 关键结果或影响\n 3. 客观陈述不加入主观评价\n 4. 如果原文是英文请用中文总结。 ) resp client.chat.completions.create( modelmodel, messages[ {role: system, content: system_prompt}, {role: user, content: f请总结以下新闻\n\n{text}}, ], temperaturecfg[summarize][temperature], max_tokenscfg[summarize][max_tokens], ) return resp.choices[0].message.content.strip().strip(\)注意base_url用的是https://taotoken.net/apiopenai包会自动拼上/v1/chat/completions。如果你手动用requests发请求完整地址就是https://taotoken.net/api/v1/chat/completions请求体和 OpenAI 官方格式一模一样。3.3 正文抓取三级降级策略网页结构千差万别单一选择器必然翻车。用三级降级先找article再找常见正文容器 class最后按段落文本密度兜底。import re import requests from bs4 import BeautifulSoup def fetch_news_content(url: str, cfg: dict) - str: headers {User-Agent: cfg[fetch][user_agent]} resp requests.get(url, headersheaders, timeoutcfg[fetch][timeout]) resp.encoding resp.apparent_encoding or utf-8 soup BeautifulSoup(resp.text, lxml) for tag in soup([script, style, nav, header, footer, aside]): tag.decompose() article soup.find(article) if article: text article.get_text(separator\n, stripTrue) if len(text) 200: return clean_text(text) selectors [ div[class*content], div[class*article], div[class*post], div[id*content], .article-content, .post-content, .entry-content, ] for sel in selectors: el soup.select_one(sel) if el: text el.get_text(separator\n, stripTrue) if len(text) 200: return clean_text(text) min_len cfg[fetch][min_paragraph_len] paras [p.get_text(stripTrue) for p in soup.find_all(p) if len(p.get_text(stripTrue)) min_len] return clean_text(\n\n.join(paras)) def clean_text(text: str) - str: text re.sub(r\n\s*\n, \n\n, text) text re.sub(r分享到.*|推荐阅读.*|相关阅读.*, , text, flagsre.DOTALL) return text.strip()三级降级的好处是结构规范的站点走第一级快且准结构一般的走第二级实在没规律的走第三级虽然可能混入少量噪声但大模型对噪声有一定容忍度摘要质量不会崩。4. 验证请求用样例新闻跑通一句话总结4.1 主程序把上面几块拼起来加个命令行入口import argparse def main(): parser argparse.ArgumentParser(description一句话总结新闻) parser.add_argument(url, help新闻链接) parser.add_argument(--model, defaultNone, help模型名覆盖配置) args parser.parse_args() cfg load_config() client build_client(cfg) print(f正在抓取: {args.url}) content fetch_news_content(args.url, cfg) print(f正文长度: {len(content)} 字符) summary summarize(content, client, cfg, args.model) print( * 50) print(f一句话总结: {summary}) print( * 50) if __name__ __main__: main()4.2 用样例新闻验证找一条真实新闻链接跑python news_summarizer.py https://example.com/news/12345预期输出类似正在抓取: https://example.com/news/12345 正文长度: 2847 字符 一句话总结: 某科技公司发布新一代开源大模型参数规模翻倍且推理成本下降四成。 验证要点有三个正文长度是否在合理区间几百到几千字符如果只有几十字符说明抓取失败总结是否包含主体、事件、结果三要素字数是否控制在 50 字内。如果总结明显偏长或漏要素先调 Prompt再考虑换模型。想快速对比不同模型的摘要质量不用改代码直接传--modelpython news_summarizer.py https://example.com/news/12345 --model gpt-4o-mini python news_summarizer.py https://example.com/news/12345 --model claude-3-5-sonnet这就是统一通道的价值换模型只是换个字符串。如果你打算长期做这类摘要任务、甚至接进自动化流程可以了解下 Coding Plan它更适合高频、批量调用场景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。5. 本篇常见错误排查5.1 401 Unauthorized最常见。九成是环境变量没生效或 Key 复制时带了空格。先确认echo $TAOTOKEN_API_KEY如果输出为空说明当前终端没读到。注意export只对当前会话有效换终端要重新设。另外检查代码里读的是不是TAOTOKEN_API_KEY这个名字和config.toml里的api_key_env必须一致。5.2 404 Not Found多半是base_url写错了。正确值是https://taotoken.net/api不要手动加/v1openai包会自己拼。如果你用requests手写请求才需要写全https://taotoken.net/api/v1/chat/completions。两种方式别混用。5.3 正文抓取为空或极短先打印resp.status_code看是不是 403。很多站点对无 UA 的请求直接拒绝config.toml里的user_agent要填一个正常的浏览器 UA。如果状态码是 200 但正文很短说明选择器没命中把resp.text存下来用浏览器开发者工具对照着调选择器。对结构特别复杂的页面可以考虑换newspaper3k这类专门做正文提取的库。5.4 摘要变成三句话或直接抄导语这是 Prompt 问题不是模型问题。检查 system prompt 里不超过50字和一句话是否同时强调max_tokens是否设得太大设 120 足够设 500 模型就会放飞。另外temperature建议 0.3 左右太高输出不稳定太低有时会偷懒直接摘抄。如果某条新闻原文本身就很短模型可能觉得没必要压缩可以在 user 消息里补一句即使原文很短也请重新组织为一句话。5.5 超时或连接错误timeout设太短长文摘要容易超时。config.toml里 API 的timeout给 30 秒比较稳。如果频繁超时先确认网络能正常访问https://taotoken.net/api再检查是不是输入文本太长导致模型处理慢适当调小max_input_chars。6. 继续往下走把工具接进你的工作流跑通单条新闻之后最自然的下一步是批量化。把 URL 列表读进来循环调用结果写进 JSON加个基于 URL 哈希的本地缓存避免重复请求这些都是在现有代码上加几十行的事。再进一步可以挂个定时任务每天早上自动摘要你关注的几个新闻源输出成 Markdown 日报。模型选择上短新闻用轻量模型就够深度长文再换上下文更长的模型反正统一通道下切换成本几乎为零。如果你要把这个能力接进更大的 Agent 或自动化编码流程Coding Plan 的额度模型会更划算。接入文档和完整参数说明在这里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API Key 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。建议先把config.toml里的default_model换成你自己试过最顺手的那个再开始批量跑。