Python Show-Me-the-Code 第 0008 题:用 TaoToken 统一 Key 提取 HTML 正文内容
1. 从一道老题说起HTML 正文提取到底难在哪如果你刷过 Python 的 Show-Me-the-Code 系列第 0008 题大概率让你卡过壳给一个 HTML 文件把里面的正文抠出来。题目描述只有一句话但真动手写才发现网页里塞满了导航栏、侧边栏、评论区、广告位、页脚版权正文往往只占整个 DOM 的百分之十几。用正则去匹配p标签遇到嵌套结构直接崩。用 BeautifulSoup 一把梭soup.get_text()结果把菜单和推荐阅读全带出来了读起来像一锅乱炖。这道题的核心检索词就是Python HTML 正文内容提取它要解决的问题是从一堆标签和噪声里稳定地还原出人眼看到的那段文章。适合谁写爬虫做数据清洗的、做 RAG 需要把网页转成干净文本喂给模型的、以及想批量归档博客文章的人。我试过纯手写规则维护成本高得离谱换个站点就得重调后来转向「解析库 正文算法 模型兜底」的组合才把链路跑顺。这篇文章不讲空理论直接给你一条能复制的完整链路requests 抓页面、BeautifulSoup 做初步清洗、正文提取算法去噪、最后把模型调用 endpoint 统一改到 TaoToken 管理 Key用一组样例页面验证输出是否干净可读。每一步都有代码和参数你可以边看边跑。先说清楚一个认知正文提取没有银弹。不同站点结构差异巨大纯算法方案在新闻站表现好在论坛或文档站可能翻车。所以我的策略是「算法打底 模型补刀」——先用轻量算法拿到 80% 的干净文本剩下结构诡异的页面再交给模型做二次抽取。而模型调用这块如果每个项目都散落着不同的 Key管理起来就是灾难这也是我把 endpoint 统一到 TaoToken 的原因。2. 前置准备requests BeautifulSoup 环境与 TaoToken Key 统一管理动手之前先把环境搭好。正文提取这条链路依赖两个库requests负责发请求拿 HTMLbeautifulsoup4负责解析 DOM再配一个lxml解析器提速。安装命令很直接pip install requests beautifulsoup4 lxml如果你还想用现成的正文提取库做对照可以顺手装trafilatura它在多语言新闻正文上表现稳定后面我会拿它和手写方案对比。安装pip install trafilatura环境好了接下来是 Key 管理。为什么要在正文提取里提模型调用因为纯算法搞不定的页面你需要一个模型来做「这段文本是不是正文」的判断或直接抽取。问题在于如果你同时用 OpenAI、Claude、国产模型Key 散落在各个脚本和环境变量里换台机器就得重新配一遍团队协作更是互相覆盖。我的做法是把所有模型调用统一走一个 endpointKey 只维护一份。TaoToken 在这里扮演的就是统一入口的角色。它的 API 地址是https://taotoken.net/api兼容 OpenAI 的接口格式意味着你原来用openaiSDK 写的代码只需要改base_url和api_key两个参数其余逻辑不动。先去控制台创建一个 Key控制台入口https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewriteAPI Keys 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite创建完 Key 之后把它写进环境变量别硬编码在脚本里export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api这样你的正文提取脚本里模型调用部分就只认这两个变量。后面无论换模型还是加新模型都只改配置不改代码。对于正文提取这种需要反复调试 prompt 的场景统一 Key 能省掉大量「这个 Key 是哪个账号的」的排查时间。注意Key 属于敏感凭证不要提交到 Git 仓库。建议用.env文件配合python-dotenv加载或者直接用系统环境变量。3. 可复制配置requests 抓取 BeautifulSoup 清洗 模型 endpoint 片段这一节给你可以直接抄的配置。先看抓取和清洗部分。核心思路是requests 拿到 HTML 后先用 BeautifulSoup 干掉 script、style、nav、footer 这些明显不是正文的标签再提取候选文本块。import os import requests from bs4 import BeautifulSoup HEADERS { User-Agent: ( Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0 Safari/537.36 ) } NOISE_TAGS [script, style, nav, footer, header, aside, form, iframe, noscript] def fetch_html(url: str, timeout: int 15) - str: resp requests.get(url, headersHEADERS, timeouttimeout) resp.raise_for_status() resp.encoding resp.apparent_encoding return resp.text def clean_soup(html: str) - BeautifulSoup: soup BeautifulSoup(html, lxml) for tag in soup(NOISE_TAGS): tag.decompose() return soup上面这段是基础。真正决定正文质量的是「候选块打分」。我用的简化版逻辑是遍历所有p和div按文本长度和标点密度打分取分数最高的容器作为正文根节点。完整函数import re def score_block(text: str) - float: if not text: return 0.0 length len(text) punct len(re.findall(r[。,.!?;:], text)) link_density text.count(http) / max(length, 1) return length * 0.5 punct * 2 - link_density * 100 def extract_main_text(soup: BeautifulSoup) - str: candidates soup.find_all([p, div, article, section]) best, best_score None, 0.0 for node in candidates: text node.get_text(stripTrue) s score_block(text) if s best_score: best, best_score node, s if best is None: return soup.get_text(\n, stripTrue) return best.get_text(\n, stripTrue)接下来是模型 endpoint 配置。当算法提取结果不理想时把候选文本丢给模型做二次判断。这里用 OpenAI 兼容格式base_url指向 TaoTokenfrom openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ.get(TAOTOKEN_BASE_URL, https://taotoken.net/api), ) MODEL_ID gpt-4o-mini # 按需替换为控制台可用的模型 ID def refine_with_model(raw_text: str) - str: prompt ( 下面是从网页提取的候选文本请只保留文章正文 去掉导航、广告、评论、版权等噪声直接输出正文\n\n raw_text[:6000] ) resp client.chat.completions.create( modelMODEL_ID, messages[{role: user, content: prompt}], temperature0, ) return resp.choices[0].message.content.strip()如果你更习惯用配置文件管理可以写一个settings.toml[taotoken] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY model_id gpt-4o-mini三件套齐了Base URL 是https://taotoken.net/apiKey 从环境变量读Model ID 按控制台可用列表填。这样无论你后面接 Claude Code 还是别的工具配置结构都一致。4. 验证请求跑一组样例页面看正文是否干净可读配置写完必须验证。我准备了三个不同类型的页面一篇技术博客、一个新闻页、一个文档页。跑下面这段主流程def pipeline(url: str, use_model: bool False) - str: html fetch_html(url) soup clean_soup(html) text extract_main_text(soup) if use_model: text refine_with_model(text) return text if __name__ __main__: url https://example.com/blog/some-post result pipeline(url, use_modelFalse) print(result[:800])实测下来技术博客类页面用纯算法就能拿到比较干净的结果正文段落完整导航和页脚被decompose掉了。新闻页因为正文集中在article里打分逻辑能准确命中。文档页稍微麻烦因为侧边栏目录和正文都是长文本链接密度特征帮了忙——目录里链接多得分被压低正文胜出。如果你想看模型二次抽取的效果把use_modelTrue打开对比两次输出。模型版的好处是能处理「正文里混了推荐阅读」这种算法难判断的情况代价是多一次网络请求和 token 消耗。我的建议是批量任务先用算法跑一遍把明显异常的页面文本过短或过长挑出来只对这些页面调模型成本可控。验证时重点看三个指标正文首段是否完整、有没有混入「相关阅读」「版权声明」、段落之间是否保留了换行。如果换行丢了检查get_text的分隔符参数用\n而不是默认空串。5. 常见报错排查401、local proxy failed、reading choices 与 OAuth链路跑起来后报错基本集中在这几类我按真实遇到的顺序列一下。401 Unauthorized最常见。要么 Key 没设进环境变量要么base_url写错了。检查echo $TAOTOKEN_API_KEY是否有值再确认base_url是https://taotoken.net/api而不是带多余路径。注意有些 SDK 会自动拼接/v1如果报 404 而不是 401多半是路径重复了。local proxy failed / connection error这类通常是本机网络环境或代理配置导致的连接失败。先确认你的请求能正常访问外网再检查requests是否被系统代理干扰。可以在代码里显式传proxies{http: None, https: None}排除干扰或者检查环境变量HTTP_PROXY是否指向了失效地址。reading choices of undefined这个报错说明返回体结构和你预期的不一样。常见原因是模型 ID 填错服务端返回了错误对象而不是标准的choices数组。打印完整resp看error字段确认MODEL_ID在控制台可用列表里。另外如果用了流式但没处理 chunk也会出现类似问题。OAuth / 认证失败如果你在 Claude Code 或类似工具里配置注意区分 API Key 认证和 OAuth 认证。走 API Key 时Base URL 填https://taotoken.net/apiKey 填控制台生成的sk-开头字符串。OAuth 流程和 API Key 是两套东西别混用。Claude Code 的接入文档在这里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite排查时养成习惯先单独用 curl 测通接口再回到 Python 脚本。curl 命令curl https://taotoken.net/api/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d {model:gpt-4o-mini,messages:[{role:user,content:ping}]}curl 通了脚本不通问题就在代码curl 也不通问题在 Key 或网络配置。6. 把链路用起来从单页提取到批量归档单页跑通只是开始。实际场景里你面对的是几百上千个 URL需要批量处理、去重、存盘。我的做法是把上面的pipeline包一层加并发和重试from concurrent.futures import ThreadPoolExecutor import time def safe_pipeline(url: str, retries: int 3) - str: for i in range(retries): try: return pipeline(url, use_modelFalse) except Exception as e: if i retries - 1: return f[FAILED] {url}: {e} time.sleep(1.5 * (i 1)) urls [https://example.com/a, https://example.com/b] with ThreadPoolExecutor(max_workers5) as pool: results list(pool.map(safe_pipeline, urls))并发数别开太大5 到 8 比较稳避免被目标站限流。存盘时按 URL 的 hash 命名方便断点续跑。如果你要把提取结果喂给模型做摘要或问答直接复用第 3 节的 client把refine_with_model换成你的业务 prompt 即可。长期做编码和 Agent 任务的话可以考虑 Coding Plan把模型调用额度集中管理https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite想先验证模型输出质量用模型对话页面快速试 prompthttps://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite最后给一个实用技巧正文提取的质量七分靠清洗三分靠算法。与其花时间调打分公式不如先把NOISE_TAGS列表按目标站点补全把评论区和推荐模块的 class 名加进黑名单。这一步的收益比换任何库都大。

相关新闻

webpack打包下anti-content逆向:补环境与JS逆向实战

webpack打包下anti-content逆向:补环境与JS逆向实战

简介:这份资源面向有一定 JavaScript 基础、希望入门 Webpack 打包与补环境逆向的开发者,聚焦拼多多 anti_content 安全机制的应对思路。包内共 2 个文件,包含 1 个 Python 脚本与 1 个 JavaScript 文件,压缩包约 40KB&#xff0c…

2026/10/1 19:54:28 阅读更多 →
Windows Server 2016 安装 OpenSSH 并配置密钥登录

Windows Server 2016 安装 OpenSSH 并配置密钥登录

1. 把 SSH 装到 Windows Server 2016 上,到底图什么第一次有人问我「Windows Server 2016 能不能装 OpenSSH Server」的时候,我的反应是:能装,但别指望像 Server 2019 那样一条命令搞定。Server 2016 这个版本比较尴尬&#xff0c…

2026/10/2 22:52:06 阅读更多 →
一句话生成一张idea card:ResearchStudio IdeaSpark上手教程,把模糊方向变成可答辩的研究想法

一句话生成一张idea card:ResearchStudio IdeaSpark上手教程,把模糊方向变成可答辩的研究想法

一句话生成一张idea card:ResearchStudio IdeaSpark上手教程,把模糊方向变成可答辩的研究想法 【免费下载链接】ResearchStudio ResearchStudio: Our AI co-author, from research problem to final publication. 项目地址: https://gitcode.com/gh_mi…

2026/10/2 15:13:27 阅读更多 →

最新新闻

互联网商业医疗保险直付平台:从理赔垫付到秒级结算的落地拆解

互联网商业医疗保险直付平台:从理赔垫付到秒级结算的落地拆解

简介:这份PDF文献面向医疗信息化从业者、医院信息中心技术人员及医疗保障研究者,聚焦互联网商业医疗保险直付平台的解决方案。内容系统梳理了商保的概况与现状、传统理赔流程的痛点,并重点论述平台设计原则,包括数据安全、实时性、…

2026/10/2 22:52:08 阅读更多 →
PPTX作为云架构契约:从幻灯片到可执行基础设施

PPTX作为云架构契约:从幻灯片到可执行基础设施

简介:本资源是一份面向智慧城市、大数据与人工智能领域技术决策者及系统架构师的《高效数据中心云基础架构解决方案》专业PPT课件,聚焦企业级IT基础设施向云化演进的核心路径。内容系统阐述动态基础架构管理(AIM)、基础架构云&…

2026/10/2 22:52:08 阅读更多 →
Jev AI研发智能体:任务闭环、本地部署与Codex集成实践

Jev AI研发智能体:任务闭环、本地部署与Codex集成实践

最近社区里聊 Jev 的人越来越多了,但大部分人还停留在"听说它很厉害"的阶段。有人说它是新的 AI 模型,有人说它就是个编码插件,还有人拿它和 Codex 对比,问是不是要抢饭碗。我前阵子也花了不少时间研究 Jev,…

2026/10/2 22:52:08 阅读更多 →
RAGFlow深度解析:企业知识库文档解析与本地部署实战

RAGFlow深度解析:企业知识库文档解析与本地部署实战

1. 先从“文档抽血”说起:RAGFlow 到底解决了什么 企业知识库这条赛道上,开源方案看着一堆,真能拿来当生产力的没几个。RAGFlow 是其中一个让我愿意花时间反复测试的项目。它最打动我的地方,不是又出了一款“聊天问答机器人”&…

2026/10/2 22:52:08 阅读更多 →
从数据传输结构拆解AXI协议:通道、握手与突发机制

从数据传输结构拆解AXI协议:通道、握手与突发机制

AXI协议这个东西,做数字IC和SoC的同学迟早要正面硬刚它。不管你是做设计、验证还是FPGA原型验证,面试时被问AXI的概率几乎是百分之百。但市面上讲AXI的资料两极分化严重:要么是ARM官方手册那种几百页的规格书,啃下来耗神费力&…

2026/10/2 22:52:08 阅读更多 →
TerraScan点云处理实战:参数原理与LiDAR测绘精度控制

TerraScan点云处理实战:参数原理与LiDAR测绘精度控制

简介:本资源是一份面向测绘、遥感、地理信息系统(GIS)及三维建模领域从业者与高校相关专业师生的技术参考文献,系统讲解基于TerraScan软件的LiDAR点云数据处理全流程。内容涵盖LiDAR技术原理与发展现状、TerraScan核心功能&#x…

2026/10/2 22:51:07 阅读更多 →

日新闻

从零搭建AI工程化:模型之外的完整闭环

从零搭建AI工程化:模型之外的完整闭环

先搞清楚一件事:从零开始做 AI 工程化,难的从来不是调模型、写提示词,而是把一套原型 Demo 变成长得像是“正经系统”的东西。你手里可能已经有了能跑通的代码,也可能刚读完一些概念,但真到了要把它变成可维护、可观测…

2026/10/2 0:00:20 阅读更多 →
大模型训练显存估计与混合精度训练实战指南

大模型训练显存估计与混合精度训练实战指南

1. 大模型训练显存估计与混合精度训练详解显存不够用,几乎是每个做大模型训练的人都会撞上的第一堵墙。你可能也经历过:模型代码写完了,数据管道跑通了,满心欢喜地按下训练启动脚本,结果几秒钟后终端弹出一行红字——C…

2026/10/2 0:00:20 阅读更多 →
小样本学习数据集选型指南:27个真正可用的高质量数据集

小样本学习数据集选型指南:27个真正可用的高质量数据集

1. 小样本学习的“弹药库”:为什么你总在找数据集,却总找不到真正能用的? 小样本、数据集——这两个词最近半年在我处理的200多个AI项目咨询里,出现频率排进前三。不是模型调不好,不是代码写不对,而是卡在…

2026/10/2 0:00:20 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 19:40:48 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/1 19:41:40 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/1 20:05:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 5:26:06 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 6:09:11 阅读更多 →