Как я могу преобразовать несколько таблиц в неупорядоченный список элементов, где каждая таблица равна <li>? - PullRequest
0 голосов
/ 03 июля 2019

Я пытаюсь исправить файл HTML. Он содержит несколько записей таблицы, и я хотел бы преобразовать его в "ul li" содержимого таблицы.

Я попытался найти все теги "table" и заменил их на "li" (см. Код ниже), но не могу "обернуть" "ul" между списками

<p> Hello world!</p>
<table><tr><td>&nbsp;</td><td>&bull;</td><td><p>First bullet point text</p></td></tr></table>
<table><tr><td>&nbsp;</td><td>&bull;</td><td><p>Second</p></td></tr></table>
<table><tr><td>&nbsp;</td><td>&bull;</td><td><p>Third</p></td></tr></table>
<table><tr><td>&nbsp;</td><td">&bull;</td><td><p>Last</p></td></tr></table>
<p>Some paragraph</p>
<table>&nbsp;</td><td>&bull;</td><td><p>1st item of 2nd list</p></td></tr></table>
<table><tr><td>&nbsp;</td><td>&bull;</td><td><p>2nd item of 2nd list</p></td></tr></table>
<p>Another paragraph</p>

Я сделал следующее:

def replaceBullets(soup):
    if soup.find('table'):
        for table in soup.findAll('table'):
            if isUnordered(table.text):
                replacement = soup.new_tag("li")
                replacement.string = table.p.text
                table.replace_with(replacement)

def isUnordered(line):
    if u'\u2022' in line and u'\xa0' in line:
        return True
    return False

Хотелось бы получить:

<p>Hello world!</p>
<ul><li>First bullet point text</li>
<li>Second</li>
<li>Third</li>
<li>Last</li></ul>
<p>Some paragraph</p>
<ul><li>1st item of 2nd list</li>
<li>2nd item of 2nd list</li></ul>
<p>Another paragraph</p>

но я не могу найти способ вставить тег "ul"

1 Ответ

0 голосов
/ 04 июля 2019

Ого, это была громоздкая задача, но мне наконец удалось это сделать.Я использовал функцию find с функцией фильтра, чтобы найти <p> элементы внутри таблицы.

https://www.crummy.com/software/BeautifulSoup/bs4/doc/#a-function

Обратите внимание, что я исправил искаженные части HTML, которые выопубликовал.

from bs4 import BeautifulSoup, Tag

if __name__ == "__main__":

    html = '''
    <p>Hello world!</p>
<table><tr><td>&nbsp;</td><td>&bull;</td><td><p>First bullet point text</p></td></tr></table>
<table><tr><td>&nbsp;</td><td>&bull;</td><td><p>Second</p></td></tr></table>
<table><tr><td>&nbsp;</td><td>&bull;</td><td><p>Third</p></td></tr></table>
<table><tr><td>&nbsp;</td><td>&bull;</td><td><p>Last</p></td></tr></table>
<p>Some paragraph</p>
<table><tr><td>&nbsp;</td><td>&bull;</td><td><p>1st item of 2nd list</p></td></tr></table>
<table><tr><td>&nbsp;</td><td>&bull;</td><td><p>2nd item of 2nd list</p></td></tr></table>
<p>Another paragraph</p>
    '''

    soup = BeautifulSoup(html, 'html.parser')

    # find all <p>s under a table and replace table with the <p> element
    def p_under_table_extractor(el: Tag):
        table_parent = el.find_parent('table')
        return el.name == 'p' and table_parent

    for p in soup.find_all(p_under_table_extractor):
        table_parent = p.find_parent('table')
        p.name = 'li'
        table_parent.replace_with(p)

    # the only <p>s are the root <p>s
    for p in soup.find_all('p'):
        # find all succeeding <li>s
        li_els = []
        for el in p.find_all_next():
            if el.name != 'li':
                break
            else:
                li_els.append(el)
        # put those <li>s inside a <ul>
        if li_els:
            ul = soup.new_tag('ul')
            for li in li_els:
                ul.append(li)
            # and put <ul> after the <p>
            p.insert_after(ul)

    print(soup.prettify())

который печатает:

<p>Hello world!</p>
<ul>
    <li>First bullet point text</li>
    <li>Second</li>
    <li>Third</li>
    <li>Last</li>
</ul>
<p>Some paragraph</p>
<ul>
    <li>1st item of 2nd list</li>
    <li>2nd item of 2nd list</li>
</ul>
<p>Another paragraph</p>
...