我正在抓取多个页面,这些页面都具有相似的格式,但它会在这里和那里发生一些变化,并且没有可用于搜索我需要的类。
格式如下:
<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>
元素 获取文字?
答案 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']