【发布时间】:2012-12-07 08:42:26
【问题描述】:
YCombinator 很好地提供了一个RSS feed 和一个big RSS feed,其中包含HackerNews 上的顶级项目。我正在尝试编写一个 python 脚本来访问 RSS 提要文档,然后使用 BeautifulSoup 解析出某些信息。但是,当 BeautifulSoup 尝试获取每个项目的内容时,我遇到了一些奇怪的行为。
以下是 RSS 提要的几行示例:
<rss version="2.0">
<channel>
<title>Hacker News</title><link>http://news.ycombinator.com/</link><description>Links for the intellectually curious, ranked by readers.</description>
<item>
<title>EFF Patent Project Gets Half-Million-Dollar Boost from Mark Cuban and 'Notch'</title>
<link>https://www.eff.org/press/releases/eff-patent-project-gets-half-million-dollar-boost-mark-cuban-and-notch</link>
<comments>http://news.ycombinator.com/item?id=4944322</comments>
<description><![CDATA[<a href="http://news.ycombinator.com/item?id=4944322">Comments</a>]]></description>
</item>
<item>
<title>Two Billion Pixel Photo of Mount Everest (can you find the climbers?)</title>
<link>https://s3.amazonaws.com/Gigapans/EBC_Pumori_050112_8bit_FLAT/EBC_Pumori_050112_8bit_FLAT.html</link>
<comments>http://news.ycombinator.com/item?id=4943361</comments>
<description><![CDATA[<a href="http://news.ycombinator.com/item?id=4943361">Comments</a>]]></description>
</item>
...
</channel>
</rss>
这是我编写的代码(在 python 中),用于访问此提要并打印出每个项目的 title、link 和 comments:
import sys
import requests
from bs4 import BeautifulSoup
request = requests.get('http://news.ycombinator.com/rss')
soup = BeautifulSoup(request.text)
items = soup.find_all('item')
for item in items:
title = item.find('title').text
link = item.find('link').text
comments = item.find('comments').text
print title + ' - ' + link + ' - ' + comments
但是,此脚本给出的输出如下所示:
EFF Patent Project Gets Half-Million-Dollar Boost from Mark Cuban and 'Notch' - - http://news.ycombinator.com/item?id=4944322
Two Billion Pixel Photo of Mount Everest (can you find the climbers?) - - http://news.ycombinator.com/item?id=4943361
...
如您所见,中间的项目link 不知何故被省略了。也就是说,link 的结果值在某种程度上是一个空字符串。那为什么会这样呢?
当我深入研究 soup 中的内容时,我意识到它在解析 XML 时会以某种方式窒息。这可以通过查看items 中的第一项来看出:
>>> print items[0]
<item><title>EFF Patent Project Gets Half-Million-Dollar Boost from Mark Cuban and 'Notch'</title></link>https://www.eff.org/press/releases/eff-patent-project-gets-half-million-dollar-boost-mark-cuban-and-notch<comments>http://news.ycombinator.com/item?id=4944322</comments><description>...</description></item>
您会注意到仅使用link 标记就发生了一些奇怪的事情。它只是获取关闭标签,然后是该标签的文本。这是一些非常奇怪的行为,尤其是与 title 和 comments 被毫无问题地解析相比。
这似乎是 BeautifulSoup 的问题,因为请求实际读取的内容没有任何问题。我不认为它仅限于 BeautifulSoup,因为我也尝试使用 xml.etree.ElementTree API 并且出现了同样的问题(BeautifulSoup 是基于此 API 构建的吗?)。
有谁知道为什么会发生这种情况,或者我如何仍然可以使用 BeautifulSoup 而不会出现此错误?
注意:我终于能够使用 xml.dom.minidom 获得我想要的东西,但这似乎不是一个强烈推荐的库。如果可能,我想继续使用 BeautifulSoup。
更新:我在 Mac 上运行 OSX 10.8,使用 Python 2.7.2 和 BS4 4.1.3。
更新 2:我有 lxml,它是用 pip 安装的。它是 3.0.2 版。至于 libxml,我检查了 /usr/lib,显示的是 libxml2.2.dylib。不确定何时或如何安装。
【问题讨论】:
-
你确定这是真正的 RSS 吗?因为我刚刚用
ElementTree、cElementTree和lxml实现对其进行了测试,它们都得到了link节点就好了。所以,要么你对xml.etree.ElementTree做错了,要么你没有给我们正确的输入数据。 -
另外,您使用的是什么版本的 Python 和 BS4? (你是否安装了 lxml,如果有,libxml 和 lxml 的版本是什么?)我刚刚完成了 Python 3.3.0 和 BS4 4.1.3 的全新安装,它能够很好地解析该 RSS。使用 Apple Python 2.7.2 和 BS4 4.1.3,同样没问题。
-
@abarnert 我已经使用请求和 urllib2 直接从 news.ycombinator.com/rss 拉取。因此,除非 ycombinator 提供的内容有问题,否则我不知道 RSS 可能存在什么问题。
-
那么,您是否通过直接从您的代码看到的相同内容中复制和粘贴来获得上面的 RSS?还是有可能您的代码在一段时间内遇到了损坏的 RSS 提要,但当您将其粘贴到此处时,它已修复? (事实上,jdotjdot 在您粘贴的代码中看到了同样的问题,这意味着这实际上是您的两个版本的 BS4 有问题,而不是那个 RSS,但在我问的时候我不知道。)
-
另外,你在什么平台上?
标签: python xml rss beautifulsoup