Beautifulsoup根据nextSibling标签名称获取文本

时间:2016-10-02 18:03:23

标签: python html beautifulsoup

我正在抓取多个页面,这些页面都具有相似的格式,但它会在这里和那里发生一些变化,并且没有可用于搜索我需要的类。

格式如下:

<div id="mainContent">

    <p>Some Text I don't want</p>
    <p>Some Text I don't want</p>
    <p>Some Text I don't want</p>
    <span> More text I don't want</span>
    <ul>...unordered-list items..</ul>

    <p>Text I WANT</p>
    <ol>...ordered-list items..</ol>

    <p>Text I WANT</p>
    <ol>...ordered-list items..</ol>

</div>

有序/无序列表和其他标签的数量会根据页面而变化,但保持不变的是我始终希望<p>标记中的文本是<ol>的上一个兄弟标签

我正在尝试(并且不工作)是:

main = soup.find("div", {"id":"mainContent"})

for d in main.children:
    if d.name == 'p' and d.nextSibling.name == 'ol':
        print(d.text)
    else:
        print("fail")

每次迭代的输出为fail。在试图弄清楚为什么这不起作用时我尝试了:

for d in main.children:
    if d.name == 'p':
        print(d.nextSibling.name)
    else:
        print("fail")

这的输出类似于:

fail
None
fail
None
fail
None
fail
fail
fail
fail
fail
None
fail

等...

为什么这不像我想的那样工作?如果下一个标记为<p>,我怎样才能从<ol>元素 获取文字?

2 个答案:

答案 0 :(得分:2)

您只需要p代码之前的ol代码。首先找到ol标记,然后找到以前的Tag对象,在这种情况下为p标记。现在您的代码无法正常工作,因为Tag元素之间存在换行符NavigableString类型对象。而且d.nextSibling也会产生这些换行符。所以你必须在这里检查对象的类型。

from bs4 import Tag
# create soup
# find the ols
ols = soup.find_all('ol')
for ol in ols:
     prev = ol.previous_sibling
     while(not isinstance(prev, Tag)):
         prev = prev.previous_sibling
     print(prev.text)

这将为您提供所需的文字。

Text I WANT
Text I WANT

答案 1 :(得分:2)

您可以使用 css选择器,即ul ~ p查找 ul 之前的所有p标签:

html = """<div id="mainContent">

    <p>Some Text I don't want</p>
    <p>Some Text I don't want</p>
    <p>Some Text I don't want</p>
    <span> More text I don't want</span>
    <ul>...unordered-list items..</ul>

    <p>Text I WANT</p>
    <ol>...ordered-list items..</ol>

    <p>Text I WANT</p>
    <ol>...ordered-list items..</ol>

</div>"""

from bs4 import BeautifulSoup

soup = BeautifulSoup(html)


print([p.text for p in soup.select("#mainContent  ul ~ p")])

哪个会给你:

['Text I WANT', 'Text I WANT']

或找到ol,然后寻找上一个兄弟 p:

print([ol.find_previous_sibling("p").text for ol in soup.select("#mainContent ol")])

这也会给你:

['Text I WANT', 'Text I WANT']