如何使用美丽的汤来查找带有特定文本的p标签下的表格

时间:2015-04-20 04:17:09

标签: python beautifulsoup

我是beautifulsoup的新手,我正试图在某个p标签下找到一些表格,里面有文字“子类”

这是HTML示例

<p><b>subclass</b></p>
<table>...<table>
<p><b>frnekr</b></p>
<table>...<table>

我只想抓住p标签下的表格 - &gt;子类。遗憾的是,那些p标签没有类。

2 个答案:

答案 0 :(得分:1)

一种方法是在一个过滤器中完成。

请参阅文档中搜索的Kinds of filters部分。

如果您可以编写一个函数来检查标记是否为文本中带有p的{​​{1}}标记,则可以使用它来查找subclass标记。例如:

p

当然你不需要这个功能。 (它与>>> soup.find_all(lambda tag: tag.name=='p' and tag.text=='subclass') [<p><b>subclass</b></p>] 相同。)但它说明了这个想法。

现在,您要查找遵循此类soup.find_all('p', text='subclass')标记的table代码。这会变得有点复杂,所以让我们把它写出来。

首先,快速而肮脏的解决方案:

p

但这并不是非常强大。你不想浏览所有以前的兄弟姐妹,只需检查一下。此外,如果找不到def is_table_after_subclass(tag): return (tag.name == 'table' and tag.find_previous_sibling('p').text == 'subclass') 标记,您将获得异常而不是false。所以:

p

现在,你可以这样做:

# This is necessary because the table's previous_sibling is the
# '\n' string between the `p` and the `table`, not the `p`.
def previous_tag(tag):
    tag = tag.previous_sibling
    while not isinstance(tag, bs4.Tag):
        tag = tag.previous_sibling
    return tag

def is_table_after_subclass(tag):
    if tag.name != 'table': return False
    prev = previous_tag(tag)
    return prev.name == 'p' and prev.text == 'subclass'

另一种方法是首先迭代所有表,然后跳过前一个兄弟错误的表。或者首先迭代所有子类段落,然后跳过那些错误的下一个兄弟段落。例如:

soup.find_all(is_table_after_subclass)

答案 1 :(得分:0)

Soupy是我尝试使这样的查询更自然(Soupy包装BeautifulSoup,使查询链更容易)。这是一个解决方案:

from soupy import Soupy, Q

text = """
<p><b>subclass</b></p>
<table>...</table>
<p><b>frnekr</b></p>
<table>...</table>
<p><b>subclass</b></p>
<p> No table here </p>
"""
from soupy import Soupy, Q

(dom.find_all('p', text="subclass")     # find relevant p tags
    .each(Q.find_next_sibling('table')) # look for sibling tables
    .filter(Q)                          # drop failed searches
    .val())                             # dump out of Soupy

哪个产生

[<table>...</table>]

这大致相当于@ abarnert的最后一个代码示例