【问题标题】:BeautifulSoup: Combine consecutive <ul> listsBeautifulSoup:组合连续的 <ul> 列表
【发布时间】:2020-06-17 00:13:30
【问题描述】:

我有一些复杂的 HTML 文件,其中列表被错误地拆分,如下例所示。

<ul>
<li>Foo</li>
</ul>
<ul>
<li>Bar</li>
</ul>

<p>Bla bla bla</p>

<ul>
<li>Foo</li>
</ul>
<ul>
<li>Bar</li>
</ul>
<ul>
<li>Baz</li>
</ul>

我需要将每一系列列表组合成一个列表。但是只有连续的列表,所以第一个列表(&lt;p&gt; 之前)不会与第二个列表(&lt;p&gt; 之后)混在一起。

<ul>
<li>Foo</li>
<li>Bar</li>
</ul>

<p>Bla bla bla</p>

<ul>
<li>Foo</li>
<li>Bar</li>
<li>Baz</li>
</ul>

这是我的 Python 代码:

for tag in soup.find_all('ul'):
    previous_tag_list = tag.find_previous_sibling(tag.name)
    previous_tag = tag.find_previous().find_previous()
    if previous_tag_list is not None and previous_tag_list == previous_tag:
        for tag1 in tag.find_all('li'):
            previous_tag.append(tag1)
            tag.decompose()

对于每个&lt;ul&gt;,它会找到一个以前的&lt;ul&gt;,并将两者结合在一起。所以我明白了:

<ul>
<li>Foo</li>
<li>Bar</li>
</ul>

<p>Bla bla bla</p>

<ul>
<li>Foo</li>
<li>Bar</li>
</ul>
<ul>
<li>Baz</li>
</ul>

这不是我想要的。

【问题讨论】:

  • “仅连续列表”是什么意思?您能否编辑问题并添加一个非连续列表示例以及它对您的预期输出有何作用?
  • @JackFleeting 我编辑了问题,希望现在清楚了!
  • 我怀疑您的实际代码包含两个以上的&lt;ul&gt; 组,并且每个组之间都有

    ` 标签,对吧?另外,如果这是真的,在第一个 &lt;ul&gt; 之前和/或在最后一个 &lt;ul&gt; 组之后是否有 &lt;p&gt;

  • @JackFleeting 是的,实际代码包含多个&lt;ul&gt; 组,这些组之间有很多不同的标签,而不仅仅是&lt;p&gt;

标签: html python-3.x beautifulsoup


【解决方案1】:

一个简单的BeautifulSoup的解决方案:

txt = '''<ul>
<li>Foo</li>
</ul>
<ul>
<li>Bar</li>
</ul>

<p>Bla bla bla</p>

<ul>
<li>Foo</li>
</ul>
<ul>
<li>Bar</li>
</ul>
<ul>
<li>Baz</li>
</ul>'''

from bs4 import BeautifulSoup    
soup = BeautifulSoup(txt, 'html.parser')

for ul in soup.select('ul ~ ul'):
    p = ul.find_previous_sibling()
    if p and p.name == 'ul':
        ul.extract()
        for li in ul.select('li'):
            p.append(li)

print(soup.prettify())

打印:

<ul>
 <li>
  Foo
 </li>
 <li>
  Bar
 </li>
</ul>
<p>
 Bla bla bla
</p>
<ul>
 <li>
  Foo
 </li>
 <li>
  Bar
 </li>
 <li>
  Baz
 </li>
</ul>

【讨论】:

  • 那是一段漂亮且非常干净的代码。非常感谢安德烈!
【解决方案2】:

另一种方法。

from simplified_scrapy import SimplifiedDoc, req, utils
html = '''<ul>
<li>Foo</li>
</ul>
<ul>
<li>Bar</li>
</ul>

<p>Bla bla bla</p>

<ul>
<li>Foo</li>
</ul>
<ul>
<li>Bar</li>
</ul>
<ul>
<li>Baz</li>
</ul>'''
doc = SimplifiedDoc(html)
ul = doc.ul
while True:
    next = ul.next
    if not next: break
    if ul.tag == "ul" and next.tag == "ul":
        ul.setContent(ul.html + next.html)
        next.repleaceSelf("")
    else:
        ul = next
print(doc.html)

结果:

<ul>
<li>Foo</li>

<li>Bar</li>
</ul>


<p>Bla bla bla</p>

<ul>
<li>Foo</li>

<li>Bar</li>

<li>Baz</li>
</ul>

这里有更多示例:https://github.com/yiyedata/simplified-scrapy-demo/tree/master/doc_examples

【讨论】:

  • 哦,我不知道simplified_scrapy,谢谢!会试一试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2022-08-15
  • 1970-01-01
  • 2016-08-26
  • 1970-01-01
相关资源
最近更新 更多