在Python中合并具有相同内容但重叠HTML标记的多个字符串

2024-09-21 01:18:51 发布

您现在位置:Python中文网/ 问答频道 /正文

标题本身并不是一个明确的问题,因此我将提供一个示例:

我有一个字符串示例:

Created and managed websites for clients to communicate securely

而且有很多“版本”。这意味着字符串的“版本”中的单词或短语将包含在HTML div标记中,即<div style="font-size: 0.1000000">foo bar</div>。(这些标记是任意的,给font-size属性的数字对应于分数,这些分数稍后将用作其他CSS功能,这些功能现在是不相关的。)下面是字符串的4个版本:

Created and <div style="font-size: 1">managed</div> websites for clients to communicate securely
Created and <div style="font-size: 2">managed websites</div> for clients to communicate securely
Created and managed websites for clients to <div style="font-size: 3">communicate</div> securely
<div style="font-size: 4">Created</div> and managed websites for clients to communicate securely

我要将所有这些版本合并到:

<div style="font-size: 4">Created</div> and <div style="font-size: 2"><div style="font-size: 1">managed</div> websites</div> for clients to <div style="font-size: 3">communicate</div> securely

正如我们在这里看到的,有重叠的标签(在带有font-size: 2font-size: 1的标签中)。字符串的版本数可以在1到50之间,因此可能存在多个重叠。你知道吗

到目前为止,我使用regex的方法如下:

import re

div_str = "<div style=.*</div>"  # the div tags
div_text_str = "(?<=(>)).*(?=(</div>))"  # the content inside the div tags

# compile the regexes
div_regex = re.compile(div_str)
div_text_regex = re.compile(div_text_str)

def merge_strings(str1, str2):

    # grab the div tag off the first version
    div = div_regex.search(str1).group()
    # grab the contents of that div tag
    div_text = div_text_regex.search(div).group()

    # find the div content in the second version, then substitute
    # with the div tag
    return re.sub(div_text, div, str2)

我在循环中运行这个函数,试图一次合并两个字符串,直到得到最终输出。我面临的问题是重叠的标记不能与这个函数一起工作,因为regex模式与它不匹配。而且,一次替换多个div标记也会失败。你知道吗

任何帮助都将不胜感激!你知道吗


Tags: andthetodivforsizestylemanaged
2条回答

这不是一个恰当的答案。你知道吗

我要提到的是,用regex解析HTML通常会给生活带来不必要的困难。最好使用诸如BeautifulSoup、lxml、scrapy等解析器

从你作为例子提供的每一行中恢复文本是很容易的。我假设每一个都是一个更大的构造的一部分;因此我将每个都包含在一个div中。你知道吗

在这里,我使用BeautifulSoup从您的每一行中获取文本。你知道吗

>>> for line in open('temp.htm').readlines():
...     line = line.strip()
...     print(line)
...     soup = bs4.BeautifulSoup(line, 'lxml')
...     soup.find('div').text
...     
<div>Created and <div style="font-size: 1">managed</div> websites for clients to communicate securely</div>
'Created and managed websites for clients to communicate securely'
<div>Created and <div style="font-size: 2">managed websites</div> for clients to communicate securely</div>
'Created and managed websites for clients to communicate securely'
<div>Created and managed websites for clients to <div style="font-size: 3">communicate</div> securely</div>
'Created and managed websites for clients to communicate securely'
<div><div style="font-size: 4">Created</div> and managed websites for clients to communicate securely</div>
'Created and managed websites for clients to communicate securely'

不幸的是,我不明白通常如何将输入行映射到输出HTML。你知道吗

我想出来了。用BeautifulSoup替换regex以简化解析,我根据div标记之间的文本长度对这些版本进行排序,以避免在查找子字符串时遇到任何问题。你知道吗

使用相同的样本:

Created and <div style="font-size: 1">managed</div> websites for clients to communicate securely
Created and <div style="font-size: 2">managed websites</div> for clients to communicate securely
Created and managed websites for clients to <div style="font-size: 3">communicate</div> securely
<div style="font-size: 4">Created</div> and managed websites for clients to communicate securely

行在一个列表中表示,然后使用BeautifulSoup按相应div标记之间的文本长度排序。代码如下:

def __merge_strings(final_str, version):

    soup = BeautifulSoup(final_str, "html.parser")

    for fixed_div in soup.find_all("div"):
        if not fixed_div.text == version.text:
            return final_str.replace(
                version.text, unicode(version)
            )

    return final_str

found_terms = (
    (i, BeautifulSoup(i, "html.parser").find("div"))
    for i in found_terms
)  # list of pairs of the version and its div text
found_terms = sorted(
    found_terms, key=lambda x: len(x[-1].text), reverse=True
)  # sort on the length of the div text to avoid issues with substrings

current_div = found_terms[0][0]  # version with the largest div text
for i in xrange(1, len(found_terms)):
    current_div = __merge_strings(current_div, found_terms[i][-1])

相关问题 更多 >

    热门问题