在播客聚合应用或内容分析脚本里,经常需要读取苹果iTunes兼容的播客订阅源。这类源本质是基于RSS 2.0的XML文档,但额外使用了itunes命名空间来承载封面图、节目分类、时长等专属信息。若只用普通文本处理去捞数据,往往会错过这些关键字段。借助Python自带的XML解析模块,我们可以按节点树精准提取所需内容。

理解iTunes播客Feed的XML结构
iTunes播客Feed通常由一个<rss>根节点包裹,其属性中声明了itunes命名空间,例如xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"。频道信息放在<channel>内,单集节目则是若干个<item>节点。除了标准RSS的<title>、<link>、<description>,还有itunes专属的<itunes:image>、<itunes:duration>、<itunes:explicit>等。
很多初学者尝试用正则表达式抓取,但XML属性顺序不固定、命名空间前缀可能变化,正则极易失效。正确思路是把文档当成树来处理。Python的xml.etree.ElementTree能把整个Feed解析为元素树,每个标签成为带标签名与属性的节点。只要按路径或迭代查找,就能忽略排版差异,稳定拿到数据。
需要注意,itunes前缀只是本地别名,真实匹配要靠命名空间URI。解析时若不加命名空间映射,直接找itunes:duration会返回空。下面章节会展示如何注册命名空间并用带URI的查找方式获取节点。
使用ElementTree解析并提取字段
标准库xml.etree.ElementTree提供了parse函数读取文件或类文件对象。由于iTunes Feed带有命名空间,我们先定义前缀到URI的字典,再用带大括号的标签名检索。例如ITUNES_NS = {'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd'},查找封面可用tree.find('channel/itunes:image', ITUNES_NS)。
下面示例展示如何打开一个本地Feed文件,提取频道标题、作者与每集的标题、时长、音频链接。音频地址在标准<enclosure>标签的url属性中,而时长是itunes:duration的文本。代码同时演示了命名空间的安全用法,避免硬编码前缀导致解析失败。
import xml.etree.ElementTree as ET
feed_path = 'podcast_feed.xml'
ITUNES_NS = {'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd'}
tree = ET.parse(feed_path)
root = tree.getroot()
channel = root.find('channel')
channel_title = channel.find('title').text
author = channel.find('itunes:author', ITUNES_NS)
author_text = author.text if author is not None else '未知'
print('频道:', channel_title)
print('作者:', author_text)
for item in channel.findall('item'):
ep_title = item.find('title').text
duration = item.find('itunes:duration', ITUNES_NS)
dur_text = duration.text if duration is not None else '0'
encl = item.find('enclosure')
audio_url = encl.get('url') if encl is not None else ''
print(ep_title, '|', dur_text, '|', audio_url)
上述代码对每个<item>做了空值判断,因为并非所有播客都填了itunes:author或duration。生产环境中还应处理网络读取:用requests拿到响应体后,以ET.fromstring(response.content)解析字节串,这样能顺带尊重服务器声明的编码。
如果Feed体积很大,一次性解析成树会占较多内存。此时可用iterparse做事件驱动解析,在end事件碰到item标签时提取并清空引用,从而降低峰值内存。但对多数播客源而言,全量解析已经足够快且代码易读。
feedparser库与常见陷阱对比
除了标准库,第三方feedparser库对播客源更友好。它会自动识别命名空间,把itunes字段拍平到条目的itunes属性里。比如entry.itunes_duration直接给出时长,entry.enclosures[0]['href']给出音频。对于快速原型或不想处理XML细节的脚本,feedparser能省去大量样板代码。
不过feedparser返回的结构经过封装,遇到不规范的Feed可能静默丢弃字段;而ElementTree让你直面原始节点,便于排查缺失原因。下面用feedparser重写前面的提取逻辑,可以看出代码更短,但依赖外部包且可控性略低。
import feedparser
d = feedparser.parse('podcast_feed.xml')
print('频道:', d.feed.get('title'))
print('作者:', d.feed.get('author', '未知'))
for entry in d.entries:
title = entry.get('title')
dur = entry.get('itunes_duration', '0')
url = ''
if entry.enclosures:
url = entry.enclosures[0].get('href', '')
print(title, '|', dur, '|', url)
实际解析时常踩两个坑。其一是编码:某些老Feed用Latin-1却声明UTF-8,ElementTree按声明解码会报错,此时可先以二进制读入并手动修整再解析。其二是相对链接:enclosure的url偶尔是相对路径,需结合<channel>里的<link>拼成绝对地址,否则下载会404。无论用哪种方案,都建议对提取结果做URL归一化与长度校验。
综合来看,若项目已引入requests且追求轻量,用ElementTree加命名空间映射最直观;若做通用聚合器、要兼容大量来源,feedparser更稳妥。两者都强于正则,核心在于尊重XML树结构与命名空间规则,才能把iTunes播客Feed真正解析干净。
PythonXML解析iTunes_podcast修改时间:2026-08-15 05:30:29