代码之家  ›  专栏  ›  技术社区  ›  agenis

扁平化HTML代码,使用树结构分隔符

  •  -2
  • agenis  · 技术社区  · 6 年前

    我有一些原始的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]]]]'
    

    到目前为止,我试着用漂亮的汤(这个 answer 是有帮助的)我想我应该把工作分成两个步骤: -提取HTML DOM的标记“骨架”,清空所有内容,如字符串、属性和 <html> . -返回平面HTMLDOM,但其结构中有树型分隔符,指示每个子代和兄弟代,如括号。 我把代码贴出来作为自己的答案

    2 回复  |  直到 6 年前
        1
  •  1
  •   Bitto    6 年前

    您可以使用递归。这个 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]]]]
    
        2
  •  0
  •   agenis    6 年前

    我在这里发布了我的第一个解决方案,它仍然有点混乱,使用了很多regex。第一个函数获取空的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]]]]'