2016-10-02 73 views
2

我刮了所有具有相似格式的多个页面,但它在这里和那里稍微变化,并且没有用于搜索我需要的类。Beautifulsoup基于nextSibling标记名称获取文本

的格式如下:

<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 

等等

这是为什么不喜欢工作我认为会呢?如果下一个标签是<ol>,我怎样才能从<p>元素只得到

回答

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 
+0

啊哈!谢谢。我发现我可以通过使用'if d.nextSibling.nextSibling.name =='ol'来准确找到它:'但我无法弄清楚为什么我必须去两个兄弟姐妹才能获得下一个兄弟姐妹。 – DjH

+0

是的,在这种情况下,这也会起作用。但是,如果只遍历两个兄弟姐妹是不够的?因为'html'可能是不可预知的。我认为在这里检查对象类型是个好主意。 –

+1

我绝对同意。谢谢 – DjH

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的,然后寻找以前的兄弟姐妹电话号码:

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

这也会给你:

['Text I WANT', 'Text I WANT'] 
+0

'print([p.text for p在soup.select(“#mainContent ul〜p”)])'工作,+1为单行。你在'soup.select(“#mainContent ol”)]给'print'([ol.find_previous_sibling(“p”)。) ''给出'TypeError:'NavigableString'对象不可调用' – DjH

+0

@ DjH,你确定你使用了'find_previous_sibling(“p”)',那个错误看起来更像'previous_sibling(“p”)'。 –

+1

哦,废话吧。 > – DjH