如何使用BeautifulSoup根据标签的子级和同级来选择标签?

2024-06-06 19:49:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图从2012年奥巴马-罗姆尼总统辩论中摘录一些话。问题是the site组织得不好。结构如下:

<span class="displaytext">
    <p>
        <i>OBAMA</i>Obama's first quotes
    </p>
    <p>More quotes from Obama</p>
    <p>Some more Obama quotes</p>

    <p>
        <i>Moderator</i>Moderator's quotes
    </p>
    <p>Some more quotes</p>

    <p>
        <i>ROMNEY</i>Romney's quotes
    </p>
    <p>More quotes from Romney</p>
    <p>Some more Romney quotes</p>
</span>

有没有办法选择一个<p>的第一个孩子是一个i有文本的OBAMA和它的所有p兄弟姐妹,直到你碰到下一个p的孩子,他的第一个孩子是一个i没有文本的Obama

这是我到目前为止所做的尝试,但它只是抓住了第一个p,忽略了兄弟姐妹

input = '''<span class="displaytext">
        <p>
            <i>OBAMA</i>Obama's first quotes
        </p>
        <p>More quotes from Obama</p>
        <p>Some more Obama quotes</p>

       <p>
           <i>Moderator</i>Moderator's quotes
       </p>
       <p>Some more quotes</p>

       <p>
           <i>ROMNEY</i>Romney's quotes
       </p>
       <p>More quotes from Romney</p>
       <p>Some more Romney quotes</p>
       </span>'''

soup = BeautifulSoup(input)
debate_text = soup.find("span", { "class" : "displaytext" })
president_quotes = debate_text.find_all("i", text="OBAMA")

for i in president_quotes:
    siblings = i.next_siblings
    for sibling in siblings:
        print(sibling)

只打印Obama's first quotes


Tags: textfrommore孩子someclassquotesfirst
2条回答

我认为一种类似于finite state machine的解决方案会在这里起作用。像这样:

soup = BeautifulSoup(input, 'lxml')
debate_text = soup.find("span", { "class" : "displaytext" })
obama_is_on = False
obama_tags = []
for p in debate_text("p"):
    if p.i and 'OBAMA' in p.i:
        # assuming <i> is used only to indicate speaker
        obama_is_on = True
    if p.i and 'OBAMA' not in p.i:
        obama_is_on = False
        continue
    if obama_is_on:
        obama_tags.append(p)
print(obama_tags)

[<p>
<i>OBAMA</i>Obama's first quotes
        </p>, <p>More quotes from Obama</p>, <p>Some more Obama quotes</p>]

其他的Obama引号是p的兄弟姐妹,而不是i,因此您需要找到i的父母的兄弟姐妹。当您在这些兄弟姐妹之间循环时,您可以在有i时停止。像这样:

for i in president_quotes:
    print(i.next_sibling)
    siblings = i.parent.find_next_siblings('p')
    for sibling in siblings:
        if sibling.find("i"):
            break
        print(sibling.string)

打印内容:

Obama's first quotes

More quotes from Obama
Some more Obama quotes

相关问题 更多 >