如何筛选含<dc:type>Research Article</dc:type>的RSS条目生成新Feed
筛选RSS Feed中指定类型的条目
需求说明
需要从指定RSS源中筛选出包含<dc:type>Research Article</dc:type>子标签的<item>条目,生成可被newsboat等阅读器识别的合法RSS文件。
原有方案的问题分析
xmlstarlet命令问题
原命令仅提取了匹配的<dc:type>文本内容,没有保留完整的RSS结构(如<rss>、<channel>及其中的标题、链接等元信息),无法生成可用的RSS feed。
Python代码问题
- 直接从
root移除<item>错误:<item>是<channel>的子元素,而非root的直接子元素,root.remove(item)无法正确删除目标条目。 - 文本匹配未处理空白:部分
<dc:type>文本可能包含前后空格,直接用text()="Research Article"会匹配失败。
可行解决方案
方案1:使用xmlstarlet命令
该命令会保留完整的RSS结构,仅保留符合条件的<item>:
xmlstarlet edit -N dc="http://purl.org/dc/elements/1.1/" --delete '//item[not(dc:type[normalize-space(text())="Research Article"])]' rssfeed.xml > filtered_rss.xml
-N dc="...":声明dc命名空间,确保XPath能正确匹配标签--delete '//item[not(...)]':删除所有不包含指定<dc:type>的条目- 输出重定向到
filtered_rss.xml,直接生成可用的RSS文件
方案2:修正后的Python代码
修复了元素定位和文本匹配的问题,确保生成合法RSS:
import xml.etree.ElementTree as ET def filter_rss_feed(input_file, output_file): tree = ET.parse(input_file) root = tree.getroot() # 声明命名空间 ns = {'dc': 'http://purl.org/dc/elements/1.1/'} # 找到channel元素(RSS的核心内容容器) channel = root.find('.//channel') if not channel: return # 反向遍历避免索引混乱,移除不符合条件的item for item in reversed(channel.findall('.//item')): type_tag = item.find('dc:type', ns) # 检查标签存在且文本匹配(处理空白) if not type_tag or type_tag.text.strip() != 'Research Article': channel.remove(item) # 写入文件时保留XML声明和UTF-8编码 tree.write(output_file, encoding='utf-8', xml_declaration=True) filter_rss_feed('rssfeed.xml', 'output_feed.xml')
- 反向遍历
<item>:避免正向遍历时删除元素导致的索引错位 strip()处理文本空白:确保匹配到带前后空格的<dc:type>内容- 定位到
<channel>操作:确保正确删除<item>元素
方案3:直接在线获取并筛选(curl + xmlstarlet)
如果不想先下载原RSS文件,可直接用curl获取后实时筛选:
curl -s "https://www.science.org/action/showFeed?type=etoc&feed=rss&jc=science" | xmlstarlet edit -N dc="http://purl.org/dc/elements/1.1/" --delete '//item[not(dc:type[normalize-space(text())="Research Article"])]' > filtered_rss.xml
内容的提问来源于stack exchange,提问作者Galilean
相关产品推荐
相关产品推荐

