【问题标题】:Regular Expression to Ignore html tags忽略html标签的正则表达式
【发布时间】:2018-06-13 08:54:28
【问题描述】:

我需要匹配 HTML 文档文本中的正则表达式。 1) html 格式正确,并且 2) 没有不是 html 标签的 '' 符号。 我遇到的问题是我需要知道原始 html 文档中匹配项的索引,因为我需要将匹配项转换为原始文档中的链接。这意味着我不能只使用漂亮的汤或其他解析器来提取文本。因为该解析结果中的匹配项将具有不同的索引。我也不能只匹配 html 文档,因为一些标签字面上出现在单词的中间,破坏了正则表达式。我需要一种方法: 1) 将已解析文档中的匹配索引映射到原始文档中的位置,或者, 2)让我的正则表达式忽略任何标签并继续搜索。

我正在使用 python re flavor。 我见过这个问题:skip over HTML tags in Regular Expression patterns 但它有所不同,因为 OP 想要忽略标签上下文中的空格。那里的答案没有给我解决方案。

这是一个(非常简化的)示例。有没有办法匹配:

r'(hello world)'

在字符串中:

string = "<p>hell</p>o world"

match.start 会在哪里返回 3?

谢谢!

【问题讨论】:

标签: python html regex


【解决方案1】:

好的,我自己想出了一个解决方案:

import re 

test_html = r'font></font><font face="Tahoma"><font size="4"> alleging that </font></font><font face="Tahoma"><font size="4">soldiers of the Uganda Peoples <span class="scayt-misspell" data-scayt_word="Defence" data-scaytid="32">Defence</span>'


NOT_TAG_REGEX = re.compile(r'(?<=\>)[^<>]+(?=\<)')


def create_chunks(html: str = None):
    """
    Divides an html string into the
    text chunks between tags, while
    storing the start and end indexes of the text
    in both the origional html string, and in the string
    that will be formed by concatenating the text in
    all the chunks.
    """
    matches = NOT_TAG_REGEX.finditer(html)

    text_cursor = 0
    chunks = []
    for match in matches:
        chunk = {
            "text": match.group(),
            "html_start": match.start(),
            "html_end": match.end(),
            "txt_start": text_cursor
        }
        text_cursor += match.end() - match.start()
        chunk["txt_end"] = text_cursor
        chunks.append(chunk)
    return chunks


def to_html_indx(txt_indx, chunks):
    """
    Given the index of a regex match in a string formed from 
    html, returns the index of that same string in the 
    origional html document
    """
    for chunk in chunks:
        if chunk["txt_start"] <= txt_indx <= chunk["txt_end"]:
            txt_indx_in_txt_chunk = txt_indx - chunk["txt_start"]
            html_indx = txt_indx_in_txt_chunk + chunk["html_start"]
            return html_indx
    else:
        print("some error message")
        return None


def main():
    chunks = create_chunks(test_html)
    text = "".join(chunk["text"] for chunk in chunks)
    print(text)
    example_regex = re.compile(r'that soldiers of')
    matches = example_regex.finditer(text)

    for match in matches:
        print("text match: " + match.group())
        txt_start = match.start()
        txt_end = match.end()
        html_start = to_html_indx(txt_start, chunks)
        html_end = to_html_indx(txt_end, chunks)
        print("html match: " + test_html[html_start: html_end])

if __name__ == "__main__":
    main()

这会产生:

text match: that soldiers of

html match: that </font></font><font face="Tahoma"><font size="4">soldiers of

【讨论】: