通用摘要解析器问题
我正在写一个Python脚本,用来解析RSS链接。
我使用了通用Feed解析器,但是在处理一些链接时遇到了问题,比如在解析FreeBSD安全公告时。以下是我的示例代码:
feed = feedparser.parse(url)
items = feed["items"]
基本上,feed["items"]应该返回所有的条目,也就是以item开头的字段,但它总是返回空。
我可以确认,以下链接的解析结果是正常的:
这是不是因为FreeBSD的链接不符合标准,导致的问题呢?
编辑:
我使用的是Python 2.7。最后我决定结合使用feedparser和BeautifulSoup,正如Hai Vu所建议的那样。以下是我稍微修改过的示例代码:
def rss_get_items_feedparser(self, webData):
feed = feedparser.parse(webData)
items = feed["items"]
return items
def rss_get_items_beautifulSoup(self, webData):
soup = BeautifulSoup(webData)
for item_node in soup.find_all('item'):
item = {}
for subitem_node in item_node.findChildren():
if subitem_node.name is not None:
item[str(subitem_node.name)] = str(subitem_node.contents[0])
yield item
def rss_get_items(self, webData):
items = self.rss_get_items_feedparser(webData)
if (len(items) > 0):
return items;
return self.rss_get_items_beautifulSoup(webData)
def parse(self, url):
request = urllib2.Request(url)
response = urllib2.urlopen(request)
webData = response .read()
for item in self.rss_get_items(webData):
#parse items
我还尝试直接将响应传递给rss_get_items,而不先读取它,但当BeautifulSoup尝试读取时,它会抛出一个异常:
File "bs4/__init__.py", line 161, in __init__
markup = markup.read()
TypeError: 'NoneType' object is not callable
1 个回答
1
我发现问题出在使用了 namespace。
对于 FreeBSD 的 RSS 源:
<rss xmlns:atom="http://www.w3.org/2005/Atom"
xmlns="http://www.w3.org/1999/xhtml"
version="2.0">
对于 Ubuntu 的源:
<rss xmlns:atom="http://www.w3.org/2005/Atom"
version="2.0">
当我从 FreeBSD 的源中去掉多余的命名空间声明后,一切都正常了。
那么这对你意味着什么呢?我想到几种不同的方法:
- 使用其他工具,比如 BeautifulSoup。我试过,似乎可以正常工作。
- 下载整个 RSS 源,进行一些搜索和替换来修复命名空间,然后再使用
feedparser.parse()
。这种方法有点 hack,不推荐自己使用。
更新
这里有一段 rss_get_items()
的示例代码,它会返回一个 RSS 源中的项目列表。每个项目都是一个字典,包含一些标准的键,比如 title(标题)、pubdate(发布日期)、link(链接)和 guid(唯一标识)。
from bs4 import BeautifulSoup
import urllib2
def rss_get_items(url):
request = urllib2.Request(url)
response = urllib2.urlopen(request)
soup = BeautifulSoup(response)
for item_node in soup.find_all('item'):
item = {}
for subitem_node in item_node.findChildren():
key = subitem_node.name
value = subitem_node.text
item[key] = value
yield item
if __name__ == '__main__':
url = 'http://www.freebsd.org/security/rss.xml'
for item in rss_get_items(url):
print item['title']
print item['pubdate']
print item['link']
print item['guid']
print '---'
输出:
FreeBSD-SA-14:04.bind
Tue, 14 Jan 2014 00:00:00 PST
http://security.FreeBSD.org/advisories/FreeBSD-SA-14:04.bind.asc
http://security.FreeBSD.org/advisories/FreeBSD-SA-14:04.bind.asc
---
FreeBSD-SA-14:03.openssl
Tue, 14 Jan 2014 00:00:00 PST
http://security.FreeBSD.org/advisories/FreeBSD-SA-14:03.openssl.asc
http://security.FreeBSD.org/advisories/FreeBSD-SA-14:03.openssl.asc
---
...
注意事项:
- 为了简洁,我省略了错误检查。
- 我建议只有在
feedparser
失败时才使用BeautifulSoup
API。原因是feedparser
是处理这个任务的合适工具。希望他们将来能更新得更宽容一些。