Библиотека Python для генерации регулярных выражений
Есть ли там lib, который может взять текст (например, html-документ) и список строк (например, имя некоторых продуктов), а затем найти шаблон в списке строк и создать регулярное выражение, которое извлечь все строки в тексте (html-документ), которые соответствуют найденному шаблону?
Например, учитывая следующий html:
<table>
<tr>
<td>Product 1</td>
<td>Product 2</td>
<td>Product 3</td>
<td>Product 4</td>
<td>Product 5</td>
<td>Product 6</td>
<td>Product 7</td>
<td>Product 8</td>
</tr>
</table>
и следующий список строк:
['Product 1', 'Product 2', 'Product 3']
Мне нужна функция, которая создаст регулярное выражение, например следующее:
'<td>(.*?)</td>'
а затем извлечь всю информацию из html, которая соответствует регулярному выражению.
В этом случае выход будет:
['Product 1', 'Product 2', 'Product 3', 'Product 4', 'Product 5', 'Product 6', 'Product 7', 'Product 8']
УТОЧНЕНИЕ:
Я хотел бы, чтобы функция смотрела на окружающие образцы, а не на сами образцы.
Так, например, если html был:
<tr>
<td>Word</td>
<td>More words</td>
<td>101</td>
<td>-1-0-1-</td>
</tr>
и образцы ['Word', 'More words']
Я бы хотел его извлечь:
['Word', 'More words', '101', '-1-0-1-']
Ответы
Ответ 1
Ваше требование в то же время очень специфично и очень общее.
Я не думаю, что вы когда-нибудь найдете какую-либо библиотеку для своей цели, если не напишите свой собственный.
С другой стороны, если вы тратите слишком много времени на создание регулярных выражений, вы можете использовать некоторые инструменты графического интерфейса, которые помогут вам их построить, например:
http://www.regular-expressions.info/regexmagic.html
Однако, если вам нужно извлечь данные только из html-документов, вам следует рассмотреть возможность использования синтаксического анализатора html, это должно сделать намного проще.
Я рекомендую beautifulsoup
для разбора html-документа в python:
https://pypi.python.org/pypi/beautifulsoup4/4.2.1
Ответ 2
Я уверен, что ответ на этот вопрос в общем случае (без педантичности) нет. Проблема заключается в том, что произвольный текст вместе с произвольным набором подстрок этого текста строго не определяет одно регулярное выражение.
Как уже упоминалось, люди могут просто вернуть .*
для каждого набора входов. Или он может вернуться для строк ввода ['desired', 'input', 'strings']
, регулярное выражение
'(desired)+|(input)+|(strings)+'
Или множество других тривиально правильных, но абсолютно бесполезных результатов.
Проблема, с которой вы сталкиваетесь, заключается в том, что для создания регулярного выражения вам необходимо строго определить его. И для этого вам нужно описать желаемое выражение, используя язык как выразительный, как язык регулярных выражений, в котором вы работаете... строка и список подстрок недостаточно (просто посмотрите на все параметры, такие как инструмент RegexMagic для вычисления регулярных выражений в ограниченной среде!). В практическом плане это означает, что вам нужно регулярное выражение, которое вы хотите, чтобы эффективно его вычислить.
Конечно, вы всегда можете идти по маршруту миллионов обезьян и пытаться каким-то образом создать подходящее регулярное выражение, но у вас все еще будет проблема с требованием огромного выборочного ввода текста + ожидаемого результата, чтобы получить жизнеспособное выражение. Плюс это займет много времени, чтобы бежать и, вероятно, раздуваться шесть способов с воскресенья с бесполезным детритом. Вероятно, вам лучше написать его сами.
Ответ 3
У меня была аналогичная проблема. Pyparsing - отличный инструмент, чтобы сделать то, что вы сказали.
http://pyparsing.wikispaces.com/
Это позволяет создавать выражения, значительно пересматривающие регулярное выражение, но гораздо более гибкие. На сайте есть несколько хороших примеров.
Ниже приведена script для проблемы, которую вы поставили выше:
from pyparsing import *
cell_contents = []
results = []
text_string="""<table>
<tr>
<td>Product 1</td>
<td>Product 2</td>
<td>Product 3</td>
<td>Product 4</td>
<td>Product 5</td>
<td>Product 6</td>
<td>Product 7</td>
<td>Product 8</td>
</tr>
</table>"""
text_string = text_string.splitlines()
for line in text_string:
anchorStart,anchorEnd = makeHTMLTags("td")
table_cell = anchorStart + SkipTo(anchorEnd).setResultsName("contents") + anchorEnd
for tokens,start,end in table_cell.scanString(line):
cell_contents = ''.join(tokens.contents)
results.append(cell_contents)
for i in results:
print i
Ответ 4
Попробуйте следующее:
https://github.com/noprompt/frak
Он написан в Clojure, и нет никаких гарантий того, что он выводит, является самым сжатым выражением, но, похоже, имеет некоторый потенциал
Ответ 5
Возможно, было бы лучше использовать парсер Python HTML, который поддерживает XPATH (см. этот связанный вопрос), посмотрите на интересующие вас фрагменты кода HTML и затем записывать их XPATH - или, по крайней мере, те, которые разделены более чем одним из примеров?
Ответ 6
Вместо генерации регулярного выражения, как насчет использования более общего регулярного выражения? Если ваши данные ограничены внутренним текстом элемента, который сам не содержит элементов, то это регулярное выражение, используемое с re.findall, даст список кортежей, где каждый кортеж (тэг, текст):
r'<(?P<tag>[^>]*)>([^<>]+?)</(?P=tag)>'
Вы можете легко извлечь текст из каждого кортежа.