Beautiful Soup:获取子节点的内容

1 投票
2 回答
1379 浏览
提问于 2025-04-16 05:51

我有以下的Python代码:

def scrapeSite(urlToCheck):
    html = urllib2.urlopen(urlToCheck).read()
    from BeautifulSoup import BeautifulSoup
    soup = BeautifulSoup(html)
    tdtags = soup.findAll('td', { "class" : "c" })
    for t in tdtags:
            print t.encode('latin1')

这段代码会返回以下的HTML代码:

<td class="c">
<a href="more.asp">FOO</a>
</td>
<td class="c">
<a href="alotmore.asp">BAR</a>
</td>

我想获取a节点之间的文本(比如说FOO或BAR),这部分内容应该是t.contents.contents。不过,这并没有那么简单 :)

有没有人知道怎么解决这个问题呢?

非常感谢,任何帮助都很受欢迎!

祝好,
Joseph

2 个回答

1

针对你的具体例子,pyparsing的makeHTMLTags功能可以很有用,因为它能处理很多不同的HTML标签变化,同时还能给结果提供一个方便的结构:

html = """
<td class="c"> 
<a href="more.asp">FOO</a> 
</td> 
<td class="c"> 
<a href="alotmore.asp">BAR</a> 
</td> 
<td class="d"> 
<a href="alotmore.asp">BAZZ</a> 
</td> 
"""

from pyparsing import *

td,tdEnd = makeHTMLTags("td")
a,aEnd = makeHTMLTags("a")
td.setParseAction(withAttribute(**{"class":"c"}))

pattern = td + a("anchor") + SkipTo(aEnd)("aBody") + aEnd + tdEnd

for t,_,_ in pattern.scanString(html):
    print t.aBody, '->', t.anchor.href

输出结果是:

FOO -> more.asp
BAR -> alotmore.asp
3

在这种情况下,你可以使用 t.contents[1].contents[0] 来获取 FOO 和 BAR。

这里要知道的是,contents 返回的是一个包含所有元素(标签和可导航字符串)的列表。如果你打印 contents,你会看到它的样子像这样:

[u'\n', <a href="more.asp">FOO</a>, u'\n']

所以,要获取实际的标签,你需要访问 contents[1](如果你的内容完全一样,这个索引可能会根据源 HTML 的不同而变化)。找到正确的索引后,你可以使用 contents[0] 来获取 a 标签里面的字符串。

不过,由于这取决于 HTML 源的具体内容,所以这种方法比较脆弱。一个更通用和稳健的解决方案是再次使用 find() 来找到 'a' 标签,通过 t.find('a'),然后使用 contents 列表来获取里面的值 t.find('a').contents[0],或者直接用 t.find('a').contents 来获取整个列表。

撰写回答