做到这一点的一种方法是在一个过滤器中。
请参阅文档中搜索下的Kinds of filters 部分。
如果你可以写一个函数来检查一个标签是否是一个p标签,文本中有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') 相同。)但它说明了这个想法。
所以现在,您要查找此类 p 标记之后的 table 标记。这会变得有点复杂,所以让我们把它写出来。
首先,一个快速而肮脏的解决方案:
def is_table_after_subclass(tag):
return (tag.name == 'table' and
tag.find_previous_sibling('p').text == 'subclass')
但这不是很健壮。您不想扫描所有以前的兄弟姐妹,只需检查直接的兄弟姐妹。此外,如果没有找到 p 标签,您将得到一个异常而不是 false。所以:
# 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)
另一种方法是首先迭代所有表,然后跳过具有错误前一个同级的表。或者首先迭代所有子类段落,然后跳过具有错误下一个兄弟的段落。例如:
def next_tag(tag):
tag = tag.next_sibling
while not isinstance(tag, bs4.Tag):
tag = tag.next_sibling
return tag
for subclass in soup.find_all('p', text='subclass'):
tag = next_tag(subclass)
if tag.name == 'table':
do_stuff(tag)