Как выполнить поиск текстовой строки без тегов в html-файле?

python html parsing tags languagetool

164 просмотра

2 ответа

Я использую LanguageTool (LT) с включенной опцией --xmlfilter для проверки правописания HTML-файлов. Это заставляет LanguageTool удалить все теги перед запуском проверки правописания.

Это также означает, что все сообщаемые позиции символов отключены, потому что LT не «видит» теги.

Например, если я проверю следующий фрагмент HTML:

<p>This is kin<b>d</b> o<i>f</i> a <b>stupid</b> question.</p>

LanguageTool будет рассматривать его как текстовое предложение:

    This is kind of a stupid question.

и возвращает следующее сообщение:

<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.»)

Поскольку строка поиска может быть заключена в теги и может встречаться несколько раз, я не могу выполнить простой поиск по индексу.

Каково было бы наиболее эффективное решение Python для надежного поиска любой заданной текстовой строки в файле HTML? (LT возвращает приблизительную позицию символа, которая может быть отключена на 10-30% в зависимости от количества тегов, а также слов до и после помеченного слова (слов).)

Т.е. мне нужно будет выполнить поиск, который игнорирует все теги, но включает их в счетчик символов.

В этом конкретном примере мне нужно найти «вид a» и найти местоположение буквы k в:

kin<b>d</b> o<i>f</i>a
Автор: Nemo XXX Источник Размещён: 08.11.2019 11:26

Ответы (2)


1 плюс

Решение

Это может быть не самым быстрым способом, но pyparsing распознает теги HTML в большинстве форм. Следующий код инвертирует обычное сканирование, создавая сканер, который будет соответствовать любому отдельному символу, а затем настраивая сканер, чтобы пропустить теги открытия и закрытия HTML, а также общие '&xxx;'объекты HTML . Метод pyparsing scanStringвозвращает генератор, который выдает совпадающие токены, начальное и конечное местоположение каждого совпадения, поэтому легко составить список, который отображает каждый символ вне тега в его исходное местоположение. Оттуда все остальное в значительной степени справедливо ''.joinи внесено в список. Смотрите комментарии в коде ниже:

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>
                 ^
"""
Автор: PaulMcG Размещён: 21.08.2016 09:21

1 плюс

Эта --xmlfilterопция устарела из-за подобных проблем. Правильное решение состоит в том, чтобы удалить теги самостоятельно, но сохранить позиции, чтобы у вас было отображение, чтобы исправить результаты, которые возвращаются из LT. При использовании LT из Java это поддерживается AnnotatedText , но алгоритм должен быть достаточно простым для его переноса. (полное раскрытие: я поддерживаю LT)

Автор: Daniel Naber Размещён: 21.08.2016 04:43
Вопросы из категории :
32x32