☰
Context Hub 中的 feedparser 6.0.12 Python 包实战指南:RSS/Atom 解析、HTTP 控制与版本漂移应对
2026/10/10 2:41:44 网站建设 项目流程

【免费下载链接】context-hub

项目地址:https://gitcode.com/gh_mirrors/co/context-hub
点击查看免费下载

本文基于 Context Hub 文档库中的 feedparser Python 包指南,系统讲解如何用feedparser.parse(...)完成 RSS/Atom 订阅源解析与字段归一化:从远端 URL 直接解析,到 ETag/Last-Modified 条件请求、自定义请求头,再到认证、代理、超时场景下的"自取 HTTP + 传响应体"模式。读完后你能掌握一份可直接复用于生产环境(以及 Agent 生成代码)的订阅源处理方案,并了解如何在 Context Hub 中按语言与版本检索这份指南。

文档定位:Context Hub 中一份多语言 DOC.md

Context Hub 是一个面向 AI Agent 的"精选、版本化 API 文档"库:CLI 负责检索与拉取文档,content/目录按"作者 → 类型 → 条目"组织内容,具体约定见 内容指南。本条目位于多语言文档结构中:

content/feedparser/docs/package/ python/ DOC.md # 本指南(Python 变体)

按照 内容指南 的规则,多语言文档需在每个语言子目录下各放一份DOC.md,Agent 用chub get feedparser/package --lang py拉取指定语言变体——这一行为由 get.js 中的--lang参数解析实现(支持py/js/ts等短名)。文档头部的 YAML frontmatter 声明了关键元数据:

--- name: package description: "feedparser Python package guide for parsing RSS and Atom feeds with practical HTTP, normalization, and version-drift notes" metadata: languages: "python" versions: "6.0.12" revision: 1 updated-on: "2026-03-12" source: maintainer tags: "feedparser,rss,atom,feeds,xml,http,syndication" ---

这里versions: "6.0.12"指的是 PyPI 上的包版本(内容指南 明确versions字段始终是 npm/PyPI 的包版本,而非 API 版本),Agent 可以据此与requirements.txt中锁定的版本比对;revision与updated-on则提供内容新鲜度信号。source: maintainer标注了信任等级(可选值为official、maintainer、community)。

黄金法则

指南开宗明义给出的使用原则是:解析和归一化交给feedparser.parse(...),但当你需要认证、重试、超时或更严格的请求行为时,把 HTTP 控制权拿回自己手里。生产代码中,应将解析结果视为"半结构化输入":检查bozo标志,优先使用entries、feed、*_parsed等归一化字段,不要假设每个 feed 都暴露相同的键。

这条法则贯穿下文所有章节:feedparser的强项是 XML 解析与字段归一化,弱项(或者说设计上不做的事)是精细的 HTTP 控制。

安装:锁定你项目期望的版本

python -m pip install "feedparser==6.0.12"

常见替代安装方式:

uv add "feedparser==6.0.12" poetry add "feedparser==6.0.12"

feedparser是纯 Python 包,解析 feed 本身不需要 API key 或服务端认证。注意安装时固定到 6.0.12 与本文其余版本敏感说明保持一致。

核心用法

解析远端 feed URL

import feedparser parsed = feedparser.parse("https://planetpython.org/rss20.xml") if parsed.bozo: print(f"Feed was malformed: {parsed.bozo_exception!r}") print(parsed.version) print(parsed.feed.get("title")) for entry in parsed.entries[:5]: print(entry.get("title"), entry.get("link"))

返回值预期结构:

  • parsed.feed:feed 级元数据,如 title、subtitle、links;
  • parsed.entries:归一化后的条目列表;
  • parsed.version:检测到的 feed 类型,如 RSS 或 Atom;
  • parsed.headers、parsed.href、parsed.status:解析 URL 时的 HTTP 元数据;
  • parsed.bozo、parsed.bozo_exception:畸形 feed 的解析告警状态。

返回值是一个"支持属性访问的 dict"。在 Agent 生成的代码中,建议使用.get(...)或存在性检查,因为很多 feed 会省略可选字段。

解析已自行获取的本地字节或 XML

如果你已经拿到了响应体,不要让它再帮你取一次 URL,直接解析:

from io import BytesIO import feedparser import requests url = "https://planetpython.org/rss20.xml" response = requests.get(url, timeout=20) response.raise_for_status() headers = dict(response.headers) headers.setdefault("content-location", response.url) parsed = feedparser.parse( BytesIO(response.content), response_headers=headers, )

传入content-location在 feed 内含相对链接时很关键:它给feedparser一个解析相对链接所用的基础 URI。

安全地解析内存中的 XML

不要把不可信的原始字符串直接传给feedparser.parse(...)——解析器可能把裸字符串解释成 URL 或文件系统路径。把原始 XML 包进文件类对象:

from io import BytesIO import feedparser xml_bytes = b"""<?xml version="1.0"?> <rss version="2.0"> <channel> <title>Example</title> <item><title>Hello</title></item> </channel> </rss> """ parsed = feedparser.parse(BytesIO(xml_bytes)) print(parsed.feed.get("title"))

HTTP、缓存与认证

用 ETag 与 Last-Modified 做条件请求

跨运行持久化etag和modified,避免重复下载未变化的 feed:

import feedparser feed_url = "https://planetpython.org/rss20.xml" stored_etag = 'W/"abc123"' stored_modified = "Wed, 05 Mar 2025 10:00:00 GMT" parsed = feedparser.parse( feed_url, etag=stored_etag, modified=stored_modified, ) if parsed.status == 304: print("Feed not modified") else: print(parsed.get("etag")) print(parsed.get("modified"))

status == 304表示服务端确认未修改;否则从返回中取新的etag/modified存入你的状态存储,供下一次运行使用。

自定义 User-Agent 或请求头

import feedparser parsed = feedparser.parse( "https://example.com/feed.xml", agent="MyFeedBot/1.0 (+https://example.com/bot)", request_headers={ "Accept": "application/atom+xml, application/rss+xml, application/xml;q=0.9, */*;q=0.1", }, )

用request_headers而不是extra_headers。部分官方文档页面仍在提extra_headers,但 6.0.12 的解析签名用的是request_headers(详见文末版本敏感说明)。

认证、代理、重试与超时时,优先显式获取

官方文档里仍有旧式urllib2风格的认证示例。现代 Python 中通常更简单的做法是:用你自选的 HTTP 客户端取回 feed,再把响应体和响应头一起交给feedparser:

from io import BytesIO import feedparser import requests response = requests.get( "https://example.com/private-feed.xml", auth=("username", "password"), headers={"User-Agent": "MyFeedBot/1.0"}, timeout=20, ) response.raise_for_status() headers = dict(response.headers) headers.setdefault("content-location", response.url) parsed = feedparser.parse(BytesIO(response.content), response_headers=headers)

这个模式让你完全掌控认证、重定向、TLS、重试、代理配置与可观测性,而不依赖解析器内置的 URL 获取路径。这也是"黄金法则"中"自己控制 HTTP"的直接落地。

Agent 常用的归一化字段

常见 entry 字段:

  • entry.title
  • entry.link
  • entry.summary
  • entry.content
  • entry.author
  • entry.tags
  • entry.enclosures
  • entry.published、entry.updated
  • entry.published_parsed、entry.updated_parsed

优先用*_parsed而不是原始日期字符串:

import calendar from datetime import datetime, timezone published = entry.get("published_parsed") if published: published_at = datetime.fromtimestamp(calendar.timegm(published), tz=timezone.utc)

feedparser会把许多日期格式归一化为 UTC 的time.struct_time值,这比你自己解析各家出版方五花八门的日期字符串可靠得多。

HTML 与链接处理

默认情况下,feedparser会解析 HTML 内容中的相对 URI,并对常见文本字段中的嵌入式标记做净化。两者都可以按调用关闭:

parsed = feedparser.parse( "https://example.com/feed.xml", resolve_relative_uris=False, sanitize_html=False, )

谨慎使用这些开关:

  • sanitize_html=False只有在你渲染进 HTML 前会自行转义或净化输出时才安全;
  • resolve_relative_uris=False只影响相关的嵌入式 HTML/标记处理,不要假设所有类链接字段都以同样方式被重写。

常见坑位清单

  • bozo == 1不一定致命。许多真实 feed 略有畸形,但依然能产出可用的entries;
  • 不要假设键存在。对summary、author、tags、published_parsed等可选字段一律用.get(...);
  • 需要确定性 HTTP 行为时,自己取 feed,再把response_headers传给feedparser.parse(...);
  • 不可信的 XML 字符串要包进BytesIO或StringIO,裸字符串可能被当作 URL 或文件路径处理;
  • 部分官方示例仍基于 Python 2 的urllib2等旧模块编写,请翻译成urllib.request或直接使用requests;
  • 解析字节(而非 URL)且相对链接重要时,在response_headers里提供content-location;
  • 日期一律用*_parsed字段,原始published、updated字符串在各出版方之间差异极大。

6.0.12 版本敏感说明

  • PyPI 当前列出feedparser 6.0.12,发布于 2025 年 9 月 10 日;
  • 官方 changelog 对 6.0.12 的说明包括:修复 Python 3.10+ 上的AssertionError、来自re.sub的DeprecationWarning,以及 Read the Docs 配置更新;
  • 文档站存在版本漂移:latest/页面仍以 6.0.11 自称,而发布页与 changelog 已包含 6.0.12;
  • 对代码生成而言,应以 6.0.12 源码标签中的request_headers和response_headers为准,不要跟随仍写着extra_headers的过期文档页。

这一节正是 Context Hub 文档库的价值所在:像 get-api-docs 技能 所示范的,Agent 在写代码前先chub get拉取版本对齐的文档,而不是依赖可能过时的训练记忆——"文档站自称 6.0.11,但包已是 6.0.12"这类漂移,正是靠版本化条目(frontmatter 中versions: "6.0.12"、updated-on: "2026-03-12")来锚定的。

延伸阅读

  • 内容指南:DOC.md 的目录结构、frontmatter 字段与版本/修订号约定,本文档即按此规范组织;
  • CLI 参考实现:--lang、--version等参数如何解析多语言多版本条目;
  • CLI README:安装chub并把它作为 Agent 技能接入的完整方式。

【免费下载链接】context-hub

项目地址:https://gitcode.com/gh_mirrors/co/context-hub
点击查看免费下载
上一篇:Feathers 数据库适配器(Database Adapters)完全指南:统一 API、分页、查询限制与服务方法实战
下一篇:lark-cli drive +resolve-comment 详解:用飞书 CLI 将文档评论标记为已解决

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询