Библиотека 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)>'

Вы можете легко извлечь текст из каждого кортежа.