Свести HTML-код с разделителями древовидной структуры - PullRequest
0 голосов
/ 21 января 2019

У меня есть некоторый необработанный HTML-код со случайного веб-сайта, возможно, грязный, с некоторыми скриптами, самозакрывающимися тегами и т. Д. Пример:

ex="<!DOCTYPE html PUBLIC \\\n><html lang=\\'en-US\\'><head><meta http-equiv=\\'Content-Type\\'/><title>Some text</title></head><body><h1>Some other text</h1><p><span style='color:red'>My</span> first paragraph.</p></body></html>"

Я хочу вернуть HTML DOM без какой-либо строки,атрибуты или тому подобное, только структура тегов, в формате строки, показывающей отношения между родителями, детьми и братьями и сестрами, это будет мой ожидаемый результат (хотя использование скобок - это личный выбор):

'[html[head[meta, title], body[h1, p[span]]]]'

До сих пор я пытался использовать beautifulSoup (этот ответ был полезен).Я понял, что должен разделить работу на два шага: - извлечь тег «скелет» HTML-модели DOM, очистив все, как строки, атрибуты и прочее, до <html>.- вернуть плоский HTML DOM, но структурированный с древовидными разделителями, указывающими каждого потомка и братьев и сестер, таких как скобки.Я отправил код в качестве самостоятельного ответа

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Вы можете использовать рекурсию.Аргумент name даст имя тега.Вы можете проверить, является ли тип bs4.element.Tag, чтобы подтвердить, является ли элемент тегом.

import bs4
ex="<!DOCTYPE html PUBLIC \\\n><html lang=\\'en-US\\'><head><meta http-equiv=\\'Content-Type\\'/><title>Some text</title></head><body><h1>Some other text</h1><p><span style='color:red'>My</span> first paragraph.</p></body></html>"
soup=bs4.BeautifulSoup(ex,'html.parser')
str=''
def recursive_child_seach(tag):
    global str
    str+=tag.name
    child_tag_list=[x for x in tag.children if type(x)==bs4.element.Tag]
    if len(child_tag_list) > 0:
        str+='['
    for i,child in enumerate(child_tag_list):
        recursive_child_seach(child)
        if not i == len(child_tag_list) - 1: #if not last child
            str+=', '
    if len(child_tag_list) > 0:
        str+=']'
    return
recursive_child_seach(soup.find())
print(str)
#html[head[meta, title], body[h1, p[span]]]
print('['+str+']')
#[html[head[meta, title], body[h1, p[span]]]]
0 голосов
/ 21 января 2019

Я публикую здесь свое первое решение, которое все еще немного грязное и использует много регулярных выражений. Первая функция получает очищенную структуру DOM и выводит ее в виде необработанной строки, вторая функция изменяет строку, добавляя разделители.

import re
def clear_tags(htmlstring, remove_scripts=False):
    htmlstring = re.sub("^.*?(<html)",r"\1", htmlstring, flags=re.DOTALL)
    finishyoursoup = soup(htmlstring, 'html.parser')
    for tag in finishyoursoup.find_all():
        tag.attrs = {}
        for sub in tag.contents:
            if sub.string:
                sub.string.replace_with('')
    if remove_scripts:
        [tag.extract() for tag in finishyoursoup.find_all(['script', 'noscript'])]
    return(str(finishyoursoup))
clear_tags(ex)
# '<html><head><meta/><title></title></head><body><h1></h1><p><span></span></p></b
def flattened_html(htmlstring):
    import re
    squeletton = clear_tags(htmlstring)
    step1      = re.sub("<([^/]*?)>", r"[\1",  squeletton) # replace begining of tag
    step2      = re.sub("</(.*?)>",   r"]",    step1) # replace end of tag
    step3      = re.sub("<(.*?)/>",   r"[\1]", step2) # deal with self-closing tag
    step4      = re.sub("\]\[",       ", ",    step3) # gather sibling tags with coma
    return(step4)
flattened_html(ex)
# '[html[head[meta, title], body[h1, p[span]]]]'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...