我正在解析博客的评论部分。不幸的是,这种结构非常不规则。
我面临两种情况:
第一条评论将分为多段
<p>My first paragraph.<br />But this a second line</p>
<p>And this is a third line</p>
而第二段仅在一段中。
我想解析字符串变量中的每个注释。但是执行以下代码
from bs4 import BeautifulSoup
html_doc = """
<!DOCTYPE html>
<html>
<body>
<div id="firstDiv">
<br></br>
<p>First comment and first line</p>
<p>First comment and second line</p>
<div id="secondDiv">
<b>Date1</b>
</div>
<br></br>
<p>Second comment</p>
<div id="secondDiv">
<b>Date2</b>
</div>
<br></br>
</div>
<br></br>
</div>
</body>
</html>
"""
soup = BeautifulSoup(html_doc)
for p in soup.find(id="firstDiv").find_all("p"):
print "Print comment: " + p.get_text()
print "End of loop"
程序将在循环的不同实例中捕获前两个段落,打印
Print comment: First comment and first line
End of loop
Print comment: First comment and second line
End of loop
Print comment: Second comment
End of loop
我怎样才能在同一循环中打印前两段?
答案 0 :(得分:0)
soup = BeautifulSoup(html_doc)
text = [''.join(s.findAll(text=True))for s in soup.findAll('p')]
text = [''.join(s.findAll(text=True))for s in soup.findAll('p')]
print ", ".join(text[:2])
print " ".join(text[2:])
First comment and first line, First comment and second line
Second comment
当调用soup.find(id="firstDiv").find_all("p")
时,它会创建一个如下所示的列表,因此在列表中迭代三个元素就可以获得三个循环:
[<p>First comment and first line</p>, <p>First comment and second line</p>, <p>Second comment</p>]
答案 1 :(得分:0)
你在这里尝试做的事情不是汤的工作,因为你处理的是平面数据,其结构没有反映在HTML中。所以,你想让汤尽可能地带你,然后切换到迭代。
获取父p
的{{1}}和div
子女的最简单方法就是让所有孩子都来。我们只想要HTML节点,而不是它们之间的字符串,所以我们可以找到没有参数的。像这样:
div
输出将是:
def chunkify(parent):
"""yields groups of <p> nodes separated by <div> siblings"""
chunk = []
for element in parent.find_all():
if element.name == 'p':
chunk.append(element)
elif element.name == 'div':
yield chunk
chunk = []
if chunk:
yield chunk
for paras in chunkify(soup.find(id="firstDiv")):
print "Print comment: " + '\n'.join(p.get_text() for p in paras)
print "End of loop"
这就是你想要的,对吧?
你可以更紧凑地编写这个函数,如果你理解Print comment: First comment and first line
First comment and second line
End of loop
Print comment: Second comment
End of loop
我觉得更可读...但是我想以一种对新手更有意义的方式来编写它,即使它&#39;先是笨重的这是一个较短的版本:
itertools
您还可以使用包含def chunkify(parent):
"""yields groups of <p> nodes separated by <div> siblings"""
grouped = groupby(parent.find_all(), lambda element: element.name != 'div')
groups = (g for k, g in grouped if k)
return ([node for node in g if node.name == 'p'] for g in groups)
的更高级别函数替换前两行;我groupby
有这个,或至少有一些接近它的东西:
more-itertools