BeautifulSoup: объединение последовательных списков <ul> - PullRequest
1 голос
/ 17 июня 2020

У меня есть несколько надежных 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>

Мне нужно объединить каждую серию списков в один список. Но только последовательные списки , поэтому первый список (до <p>) не смешивается со вторым (после <p>).

<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()

Для каждого <ul> он находит предыдущий <ul> и объединяет их вместе. Итак, я получаю следующее:

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

это не то, что я ищу.

Ответы [ 2 ]

1 голос
/ 17 июня 2020

Решение с обычным 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>
1 голос
/ 17 июня 2020

Другой метод.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...