Python库用于类似jQuery的文本提取?
我有一些HTML内容,里面包含像这样的条目:
<div class="entry">
<h3 class="foo">
<a href="http://www.example.com/blog-entry-slug"
rel="bookmark">Blog Entry</a>
</h3>
...
</div>
我想提取出“博客条目”这段文字(还有其他一些属性,所以我希望能找到一个通用的解决办法)。
在jQuery中,我会这样做:
$('.entry a[rel=bookmark]').text()
在Python中,我能做到的最接近的方式是:
from BeautifulSoup import BeautifulSoup
import soupselect as soup
rawsoup = BeautifulSoup(open('fname.html').read())
for entry in rawsoup.findAll('div', 'entry'):
print soup.select(entry, 'a[rel=bookmark]')[0].string.strip()
我用的是来自 http://code.google.com/p/soupselect/ 的Soupselect。
不过,Soupselect并不完全支持CSS3选择器的语法,像jQuery那样。那么在Python中有没有类似的工具呢?
4 个回答
使用关键字参数其实非常简单。
>>> from BeautifulSoup import BeautifulSoup
>>> soup = BeautifulSoup('''<div class="entry">
... <h3 class="foo">
... <a href="http://www.example.com/blog-entry-slug"
... rel="bookmark">Blog Entry</a>
... </h3>
... ...
... </div>
... ''')
>>> soup.find('div', 'entry').find(rel='bookmark').text
u'Blog Entry'
另外,
>>> for entry in soup('div', 'entry'):
... for bookmark in entry(rel='bookmark'):
... print bookmark.text
...
Blog Entry
你也可以用 attrs
来选择 .entry
,而不是 div.entry
:
>>> for entry in soup(attrs={'class': 'entry'}):
... for bookmark in entry(rel='bookmark'):
... print bookmark.text
...
Blog Entry
(注意,调用 soup 或者 soup 的一部分相当于 .findAll()
。)
作为一个列表推导式,这段代码是 [b.text for e in soup('div', 'entry') for b in e(rel='bookmark')]
(结果是 [u'Blog Entry']
)。
如果你想要真正的 CSS3 选择器,我不知道 BeautifulSoup 有没有这样的功能。几乎所有的操作都可以通过简单的嵌套、条件和正则表达式来完成(你也可以使用 entry(rel=re.compile('^bookmark$'))
)。如果你想要这样的功能,可以把它当作下一个项目来做!这可能对简化代码和让网页开发者更容易理解会有帮助。
你可能还想看看pyquery。pyquery是一个类似于jQuery的Python库。你可以在这里找到它。
你可以看看 lxml 的 CSSSelector 类,它试图按照 w3c 的规范来实现 CSS 选择器。顺便提一下,很多人 推荐 现在使用 lxml 来解析 HTML/XML,而不是 BeautifulSoup,主要是因为性能和其他一些原因。
我觉得 lxml 的 CSSSelector 是用 XPath 来选择元素的,不过你可以自己去查查文档。下面是你用 lxml 的示例:
>>> from lxml.cssselect import CSSSelector
>>> from lxml.html import fromstring
>>> html = '<div class="entry"><h3 class="foo"><a href="http://www.example.com/blog-entry-slug" rel="bookmark">Blog Entry</a></h3></div>'
>>> h = fromstring(html)
>>> sel = CSSSelector("a[rel=bookmark]")
>>> [e.text for e in sel(h)]
['Blog Entry']