使用beautifulsoup 4关闭格式错误的html中的<p>标签

时间:2016-07-21 06:00:42

标签: python-3.x beautifulsoup html-parsing

我有一套不太有效的html页面要刮掉。我需要的数据是“p”标签。但是,大多数都没有关闭:

<p>Bla-bla-bla
<p>bla bla
<p>more bla-bla
<p><span class="some_class">another bla</span>
<p>just some more bla bla bla
<div class="another_class"></div>
<script>
<p>here's some more </p>

所以当我执行搜索时,它会给我一个混乱的累积数据结果集:

In [2]: html='''
<p>Bla-bla-bla
<p>bla bla
<p>more bla-bla
<p><span class="some_class">another bla</span>
<p>just some more bla bla bla
<div class="another_class"></div>
<script>
<p>here's some more </p>'''

In [3]: from bs4 import BeautifulSoup

In [4]: soup = BeautifulSoup(html, "html.parser")

In [5]: p = soup.find_all('p')

In [6]: len(p)
Out[6]: 5

In [7]: p[0]
Out[7]: 
<p>Bla-bla-bla
<p>bla bla
<p>more bla-bla
<p><span class="some_class">another bla</span>
<p>just some more bla bla bla
<div class="another_class"></div>
<script></script></p></p></p></p></p>

In [8]: p[1]
Out[8]: 
<p>bla bla
<p>more bla-bla
<p><span class="some_class">another bla</span>
<p>just some more bla bla bla
<div class="another_class"></div>
<script></script></p></p></p></p>

In [9]: p[2]
Out[9]: 
<p>more bla-bla
<p><span class="some_class">another bla</span>
<p>just some more bla bla bla
<div class="another_class"></div>
<script></script></p></p></p>

我猜默认的'html.parser'只关闭输入字符串末尾的所有标签,无论标签是什么。在我的情况下,我希望解析器解析不太贪婪的标签,这样我就可以在一天结束时得到一个段落列表。有没有明显的解决方案,或者我应该处理这个累积的集合,并通过例如后续的字符串或其他东西来清理它?

(汤也失去了最后一个“p” - 唯一一个格式正确的,这很奇怪。)

3 个答案:

答案 0 :(得分:2)

From bs4 docs

  

另一种选择是纯Python html5lib解析器,它以Web浏览器的方式解析HTML。

所以:

pip install html5lib

然后

In [14]: soup = BeautifulSoup(html, "html5lib")

In [15]: p = soup.find_all('p')

In [17]: p[0]
Out[17]: <p>Bla-bla-bla\n</p>

但最后一段仍然丢失了:

In [18]: len(p)
Out[18]: 5

In [19]: p2
Out[19]: 
[<p>Bla-bla-bla\n</p>,
 <p>bla bla\n</p>,
 <p>more bla-bla\n</p>,
 <p><span class="some_class">another bla</span>\n</p>,
 <p>just some more bla bla bla\n</p>]

答案 1 :(得分:0)

你试过了吗?

html.replace("<p>", "</p><p>")

然后:

html.replace("</p><p>", "<p>", 1)

清理第一个标签。

答案 2 :(得分:0)

如果每个p标记都有自己的行,则可以从输入文本中删除空格(以防止末尾出现空白行),然后尝试:

搜索:(?<!(div|script|p)>)$

替换:</p>

如果该行未以开始或结束pdivscript标记结束,则会向每个行结尾添加结束p标记。要排除其他标签(例如table等),请按相同方式添加标签:

(?<!(div|script|p|table|tr|td|th|section)>)$