如何美化HTML,以便标记属性将保留在一行中?

BPL:

我得到了这段小代码:

text = """<html><head></head><body>
    <h1 style="
    text-align: center;
">Main site</h1>
    <div>
        <p style="
    color: blue;
    text-align: center;
">text1
        </p>
        <p style="
    color: blueviolet;
    text-align: center;
">text2
        </p>
    </div>
    <div>
        <p style="text-align:center">
            <img src="./foo/test.jpg" alt="Testing static images" style="
">
        </p>
    </div>
</body></html>
"""

import sys
import re
import bs4


def prettify(soup, indent_width=4):
    r = re.compile(r'^(\s*)', re.MULTILINE)
    return r.sub(r'\1' * indent_width, soup.prettify())

soup = bs4.BeautifulSoup(text, "html.parser")
print(prettify(soup))

现在,以上代码段的输出为:

<html>
    <head>
    </head>
    <body>
        <h1 style="
                text-align: center;
">
            Main site
        </h1>
        <div>
            <p style="
                color: blue;
                text-align: center;
">
                text1
            </p>
            <p style="
                color: blueviolet;
                text-align: center;
">
                text2
            </p>
        </div>
        <div>
            <p style="text-align:center">
                <img alt="Testing static images" src="./foo/test.jpg" style="
"/>
            </p>
        </div>
    </body>
</html>

我想弄清楚如何格式化输出,使其变为:

<html>
    <head>
    </head>
    <body>
        <h1 style="text-align: center;">
            Main site
        </h1>
        <div>
            <p style="color: blue;text-align: center;">
                text1
            </p>
            <p style="color: blueviolet;text-align: center;">
                text2
            </p>
        </div>
        <div>
            <p style="text-align:center">
                <img alt="Testing static images" src="./foo/test.jpg" style=""/>
            </p>
        </div>
    </body>
</html>

换句话说,<tag attrib1=value1 attrib2=value2 ... attribn=valuen>如果可能的话,我想将html语句保持在一行中。当我说“如果可能”时,我的意思是不弄乱属性本身的值(值1,值2,...,值n)。

使用beautifulsoup4可以实现吗?据我在文档中阅读的内容来看,您似乎可以使用自定义格式化程序,但我不知道如何拥有自定义格式化程序,以便它可以满足上述要求。

编辑:

@alecxe解决方案非常简单,不幸的是,在以下更复杂的情况下失败,例如:

test1 = """
<div id="dialer-capmaign-console" class="fill-vertically" style="flex: 1 1 auto;">
    <div id="sessionsGrid" data-columns="[
        { field: 'dialerSession.startTime', format:'{0:G}', title:'Start time', width:122 },
        { field: 'dialerSession.endTime', format:'{0:G}', title:'End time', width:122, attributes: {class:'tooltip-column'}},
        { field: 'conversationStartTime', template: cty.ui.gct.duration_dialerSession_conversationStartTime_endTime, title:'Duration', width:80},
        { field: 'dialerSession.caller.lastName',template: cty.ui.gct.person_dialerSession_caller_link, title:'Caller', width:160 },
        { field: 'noteType',template:cty.ui.gct.nameDescription_noteType, title:'Note type', width:150, attributes: {class:'tooltip-column'}},
        { field: 'note', title:'Note'}
        ]">
</div>
</div>
"""

from bs4 import BeautifulSoup
import re


def prettify(soup, indent_width=4, single_lines=True):
    if single_lines:
        for tag in soup():
            for attr in tag.attrs:
                print(tag.attrs[attr], tag.attrs[attr].__class__)
                tag.attrs[attr] = " ".join(
                    tag.attrs[attr].replace("\n", " ").split())

    r = re.compile(r'^(\s*)', re.MULTILINE)
    return r.sub(r'\1' * indent_width, soup.prettify())


def html_beautify(text):
    soup = BeautifulSoup(text, "html.parser")
    return prettify(soup)

print(html_beautify(test1))

追溯:

dialer-capmaign-console <class 'str'>
['fill-vertically'] <class 'list'>
Traceback (most recent call last):
  File "d:\mcve\x.py", line 35, in <module>
    print(html_beautify(test1))
  File "d:\mcve\x.py", line 33, in html_beautify
    return prettify(soup)
  File "d:\mcve\x.py", line 25, in prettify
    tag.attrs[attr].replace("\n", " ").split())
AttributeError: 'list' object has no attribute 'replace'
alecxe:

BeautifulSoup 尝试保留输入HTML中属性值中的换行符和多个空格。

这里的一种解决方法是遍历元素属性并在整理之前清理它们 -删除换行符并用单个空格替换多个连续的空格:

for tag in soup():
    for attr in tag.attrs:
        tag.attrs[attr] = " ".join(tag.attrs[attr].replace("\n", " ").split())

print(soup.prettify())

印刷品:

<html>
 <head>
 </head>
 <body>
  <h1 style="text-align: center;">
   Main site
  </h1>
  <div>
   <p style="color: blue; text-align: center;">
    text1
   </p>
   <p style="color: blueviolet; text-align: center;">
    text2
   </p>
  </div>
  <div>
   <p style="text-align:center">
    <img alt="Testing static images" src="./foo/test.jpg" style=""/>
   </p>
  </div>
 </body>
</html>

更新(以解决诸如多值属性class):

您只需要添加一些细微的修改即可为属性为list类型的情况添加特殊处理

for tag in soup():
    tag.attrs = {
        attr: [" ".join(attr_value.replace("\n", " ").split()) for attr_value in value] 
              if isinstance(value, list)
              else " ".join(value.replace("\n", " ").split())
        for attr, value in tag.attrs.items()
    }

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何让 Prettier 将结束标记的结束符号保留在同一行上

从html获取纯文本,但希望使用javascript将标题属性保留在选择标记中

fittext-将文字保留在一行中,而不要换成两行

熊猫wide_to_long-将值保留在i中的行保留或将空白保留为一行

如何使用 css 或 javascript 将文本保留在一行上

如何只将第一行文本保留在多行单元格中?

根据优先级将值保留在特定列中,并删除每一行的其他值

Oracle - 将第一列分组并保留在同一行

折叠多行,将某些行的值保留在一个变量中,将另一行的值保留在另一个变量中

IntelliJ代码样式将方法名称和参数保留在同一行

熊猫:删除重复但连续的行,并将第一行保留在组中

如何将列表输出全部保留在一行上,而没有获取下一行代码

将所有列值保留在Pandas组的第一行中,并保留后续行中的任何更新?

动态调整水平<li>元素的大小以保留在一行中

在Matlab中将最大和最小元素保留在矩阵的每一行中

如何合并对象数组,仅将属性保留在第一个数组中

只需将第一行/第一行保留在换行的文本列中

使用timedelta将df1中的每一行都保留在df2中的pandas DataFrame行

snapPointsToLines无法将属性保留在R中

如何在BI Publisher报表中将Word女士表格的第一行和第二行保留在一页中?

尝试将两个按钮和段落保留在表格中同一行的同一水平线上

SQL查询根据ID将多行合并为一个,同时将其他值保留在同一行中?

如何将所有中间属性变量保留在深度嵌套的结构中

R:如何根据另一个变量中的值选择dplyr :: distinct()保留在哪一行?

用于将行以一定长度保留在文件中的命令

如何仅将非重复行保留在文件中?

如何对每n行分组并求和,但将原始结构保留在熊猫中

如何仅将具有多个值的行保留在pandas DataFrame中?

Pandas - 使用第二行作为标题并将第一行保留在数据框中