Python 如何在html文件中执行标记无关的文本字符串搜索?

Python 如何在html文件中执行标记无关的文本字符串搜索?,python,html,parsing,tags,languagetool,Python,Html,Parsing,Tags,Languagetool,我正在使用(LT)并启用--xmlfilter选项来检查HTML文件的拼写。这将强制LanguageTool在运行拼写检查之前剥离所有标记 这也意味着所有报告的字符位置都处于关闭状态,因为它没有“看到”标记 例如,如果我检查以下HTML片段: <p>This is kin<b>d</b> o<i>f</i> a <b>stupid</b> question.</p> 并返回以下消息: <err

我正在使用(LT)并启用--xmlfilter选项来检查HTML文件的拼写。这将强制LanguageTool在运行拼写检查之前剥离所有标记

这也意味着所有报告的字符位置都处于关闭状态,因为它没有“看到”标记

例如,如果我检查以下HTML片段:

<p>This is kin<b>d</b> o<i>f</i> a <b>stupid</b> question.</p>
并返回以下消息:

<error category="Grammar" categoryid="GRAMMAR" context="                This is kind of a stupid question.    " contextoffset="24" errorlength="9" fromx="8" fromy="8" locqualityissuetype="grammar" msg="Don't include 'a' after a classification term. Use simply 'kind of'." offset="24" replacements="kind of" ruleId="KIND_OF_A" shortmsg="Grammatical problem" subId="1" tox="17" toy="8"/>

(在本例中,LT标记为“种类a”)

由于搜索字符串可能被包装在标记中,并且可能出现多次,因此我无法进行简单的索引搜索

要在HTML文件中可靠地定位任何给定的文本字符串,最有效的Python解决方案是什么?(LT返回一个近似的字符位置,根据标记的数量以及标记单词前后的单词,该位置可能会关闭10-30%。)

也就是说,我需要进行一次搜索,忽略所有标记,但将它们包含在角色位置计数中

在这个特定的例子中,我必须找到“种类a”并找到字母k的位置:

kin<b>d</b> o<i>f</i>a
一种
由于此类问题,
--xmlfilter
选项已被弃用。正确的解决方案是自己移除标记,但保留位置,这样您就有了一个映射来纠正从LT返回的结果。当使用Java中的LT时,这是受支持的,但算法应该足够简单,可以移植它。(完全公开:我是LT的维护者)

由于类似的问题,
--xmlfilter
选项被弃用。正确的解决方案是自己移除标记,但保留位置,这样您就有了一个映射来纠正从LT返回的结果。当使用Java中的LT时,这是受支持的,但算法应该足够简单,可以移植它。(完全公开:我是LT的维护者)

这可能不是最快的方法,但是pyparsing可以识别大多数表单中的HTML标记。下面的代码反转了典型的扫描,创建一个与任何单个字符匹配的扫描程序,然后将扫描程序配置为跳过HTML打开和关闭标记,以及常见的HTML
“&xxx;”实体。pyparsing的
scanString
方法返回一个生成器,生成匹配的标记、每个匹配的起始位置和结束位置,因此很容易构建一个列表,将标记之外的每个字符映射到其原始位置。从这里开始,剩下的基本上就是
”。加入
并索引到列表中。请参见下面代码中的注释:

test = "<p>This &nbsp;is kin<b>d</b> o<i>f</i> a <b>stupid</b> question.</p>"

from pyparsing import Word, printables, anyOpenTag, anyCloseTag, commonHTMLEntity

non_tag_text = Word(printables+' ',  exact=1).leaveWhitespace()
non_tag_text.ignore(anyOpenTag | anyCloseTag | commonHTMLEntity)

# use scanString to get all characters outside of tags, and build list
# of (char,loc) tuples
char_locs = [(t[0], loc) for t,loc,endloc in non_tag_text.scanString(test)]

# imagine a world without HTML tags...
untagged = ''.join(ch for ch, loc in char_locs)

# look for our string in the untagged text, then index into the char,loc list
# to find the original location
search_str = 'kind of a'
orig_loc = char_locs[untagged.find(search_str)][1]

# print the test string, and mark where we found the matching text
print(test)
print(' '*orig_loc + '^')

"""
Should look like this:

<p>This &nbsp;is kin<b>d</b> o<i>f</i> a <b>stupid</b> question.</p>
                 ^
"""
test=“这是一个愚蠢的问题。

” 从pyparsing导入Word、printables、anyOpenTag、anyCloseTag、CommonHtmlenty 非标签文本=Word(可打印文件+“”,精确=1) 非标记文本。忽略(anyOpenTag | anyCloseTag | commonHTMLEntity) #使用scanString获取标记之外的所有字符,并生成列表 #(char,loc)元组的 char_locs=[(t[0],loc)表示非标记文本中的t、loc、endloc。扫描字符串(测试)] #想象一个没有HTML标签的世界。。。 untaged=''.join(ch表示ch,loc表示字符) #在未标记的文本中查找我们的字符串,然后索引到char,loc列表中 #找到原始位置 search_str='有点像' orig_loc=char_locs[untaged.find(search_str)][1] #打印测试字符串,并标记找到匹配文本的位置 打印(测试) 打印(''*orig_loc+'^') """ 应该是这样的: 这是一个愚蠢的问题

^ """
这可能不是最快的方法,但是pyparsing可以识别大多数表单中的HTML标记。下面的代码反转了典型的扫描,创建一个与任何单个字符匹配的扫描程序,然后将扫描程序配置为跳过HTML打开和关闭标记,以及常见的HTML
“&xxx;”实体。pyparsing的
scanString
方法返回一个生成器,生成匹配的标记、每个匹配的起始位置和结束位置,因此很容易构建一个列表,将标记之外的每个字符映射到其原始位置。从这里开始,剩下的基本上就是
”。加入
并索引到列表中。请参见下面代码中的注释:

test = "<p>This &nbsp;is kin<b>d</b> o<i>f</i> a <b>stupid</b> question.</p>"

from pyparsing import Word, printables, anyOpenTag, anyCloseTag, commonHTMLEntity

non_tag_text = Word(printables+' ',  exact=1).leaveWhitespace()
non_tag_text.ignore(anyOpenTag | anyCloseTag | commonHTMLEntity)

# use scanString to get all characters outside of tags, and build list
# of (char,loc) tuples
char_locs = [(t[0], loc) for t,loc,endloc in non_tag_text.scanString(test)]

# imagine a world without HTML tags...
untagged = ''.join(ch for ch, loc in char_locs)

# look for our string in the untagged text, then index into the char,loc list
# to find the original location
search_str = 'kind of a'
orig_loc = char_locs[untagged.find(search_str)][1]

# print the test string, and mark where we found the matching text
print(test)
print(' '*orig_loc + '^')

"""
Should look like this:

<p>This &nbsp;is kin<b>d</b> o<i>f</i> a <b>stupid</b> question.</p>
                 ^
"""
test=“这是一个愚蠢的问题。

” 从pyparsing导入Word、printables、anyOpenTag、anyCloseTag、CommonHtmlenty 非标签文本=Word(可打印文件+“”,精确=1) 非标记文本。忽略(anyOpenTag | anyCloseTag | commonHTMLEntity) #使用scanString获取标记之外的所有字符,并生成列表 #(char,loc)元组的 char_locs=[(t[0],loc)表示非标记文本中的t、loc、endloc。扫描字符串(测试)] #想象一个没有HTML标签的世界。。。 untaged=''.join(ch表示ch,loc表示字符) #在未标记的文本中查找我们的字符串,然后索引到char,loc列表中 #找到原始位置 search_str='有点像' orig_loc=char_locs[untaged.find(search_str)][1] #打印测试字符串,并标记找到匹配文本的位置 打印(测试) 打印(''*orig_loc+'^') """ 应该是这样的: 这是一个愚蠢的问题

^ """
“也就是说,我需要进行一次搜索,忽略所有标记,但将它们包含在字符位置计数中…”——我可以告诉您如何使用utf-8字符集innerhtml和正则表达式来完成此操作,但只能使用查找/替换-我对LanguageTool一无所知。我怀疑我的答案不是最好的——如果在几天内没有比我更好的答案,那就给我回电话,我会解释我的方法(至少有用)。@Tony Duffill谢谢!我很感谢您的提议。我不清楚您是要搜索“的上下文属性中给出的字符串,还是要搜索“的数字属性”给出的位置。也就是说,我需要进行忽略所有标记的搜索,但在字符位置计数中包含它们…“--我可以告诉您如何使用utf-8字符集innerhtml和正则表达式来实现这一点,但只能使用find/replace—我对Languag一无所知