问题 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-']

865
2017-07-19 15:33


起源

为什么不建立正则表达式 'Product [1-3]'? - mgilson
有关: stackoverflow.com/questions/616292/... - Gustav Larsson
@IonutHulub如果生成的正则表达式也消耗了周围的空白,那么它是不是更“通用”: \s*<td>(.*?)</td>\s*?什么是告诉算法停在边界的原理 td 标签?您是否真的对通用正则表达式感兴趣或者发现字符串在HTML或XML样式文档的层次结构中的位置? - FMc
这听起来像是一个 XY问题。您应该打开一个StackOverflow问题,询问您遇到的问题,而不是您认为对解决问题有用的工具。 - user2357112
推导XPath / CSS选择器比在此推导正则表达式更有意义 - Eric


答案:


您的要求同时非常具体且非常一般。

除非你自己编写,否则我认为你找不到任何图书馆。

另一方面,如果你花费太多时间编写正则表达式,你可以使用一些GUI工具来帮助你构建它们,例如: http://www.regular-expressions.info/regexmagic.html

但是,如果您只需要从html文档中提取数据,则应考虑使用html解析器,它应该使事情变得更容易。

我建议 beautifulsoup 在python中解析html文档: https://pypi.python.org/pypi/beautifulsoup4/4.2.1


9
2017-07-21 21:46



Regexmagic对我的需求并不好。我已经开始使用库,我使用beautifulsoup4来解析html。当我有一个稳定的版本时,我会在这里发布。 - Ionut Hulub


我很确定在一般情况下(没有迂腐)这个问题的答案是 没有。问题在于,任意文本以及该文本的任意子串都不会严格定义单个正则表达式。

正如一对人提到的,功能可以简单地返回 .* 对于每组输入。或者它可以返回,输入字符串 ['desired', 'input', 'strings'],正则表达式

'(desired)+|(input)+|(strings)+'

或者还有很多其他非常正确但完全没用的结果。

您面临的问题是,为了构建正则表达式,您需要严格定义它。要做到这一点,你需要使用语言描述所需的表达式,就像你正在使用的正则表达式语言一样......字符串加上一个子串列表是不够的(只需查看RegexMagic需要的工具的所有选项)在有限的环境中计算正则表达式!)。实际上,这意味着您需要所需的正则表达式,以便有效地计算它。


当然,你总是可以去百万只猴子路线并尝试 发展 一个适当的正则表达式,但你仍然会有一个问题,需要一个巨大的文本输入文本+预期输出,以获得一个可行的表达式。此外,它还需要很长时间才能运行,并且可能会在星期天以无用的碎屑六种方式臃肿。你最好自己写一下。


5
2017-07-24 16:54



也许我没有明确表达我的不好,但我不希望函数通过查看样本来构建正则表达式,而是通过查看样本的周期。因此,最终的正则表达式将始终采用以下形式: before_regex + (.*?) + after_regex,哪里 (.*?) 会抓住样品。 - Ionut Hulub
@IonutHulub请求更长的正则表达式并不会改变基本问题,即您希望提供的输入根本不足以描述正则表达式。我可以想出任何形式的正则表达式 before+(group)+after,所有这些都是“正确的”,其中没有一个实际上有用。 a*(sample)b*, b*(sample)a*等等......您想要使用的输入对于手头的任务来说还不够。 - Henry Keiter
@HenryKeiter不要在正则表达式中包含样本。只看周围。在我提供的示例中,函数应该注意到所有3个样本都有 <td> 在他们面前 </td> 之后,所以它应该构建一个正则表达式 <td>(.*?)</td>。这是可行的...我在约2小时内制作原型。我正在为其他一些项目工作,但是当我完成它时,我会在这里发布这个库。 - Ionut Hulub
@IonutHulub 怎么样 功能是否应该注意到所有样品都有 <td> 之前和 </td> 之后,而不是 [fubar]* 之前和之后?或者`之前的`<td>` </td>\n  后?正如mgilson在评论中所说,为什么它不能归还正则表达式 'Product [1-3]'?毕竟, 那 完全复制你想要的匹配,而获得正则表达式 <td>(.*?)</td>,函数必须以某种方式推断你想要匹配的不仅仅是 ['Product 1', 'Product 2', 'Product 3'] 你提供。 - Henry Keiter
来自RegexMagic的@IonutHulub 关于这个问题的页面 (诚​​然,这是一个有点偏颇的来源,但这不会改变事实):“计算机构建可预测的正则表达式的唯一方法是要求你列出所有可能的匹配。然后它可以生成一个完全匹配的搜索模式那些比赛,没有别的。通常,提供详尽的比赛清单正是我们要避免的。“ - Henry Keiter


我有类似的问题。 Pyparsing是一个很好的工具,就像你说的那样。

http://pyparsing.wikispaces.com/

它允许你构建表达式列表正则表达式,但更灵活。该网站有一些很好的例子。

以下是您在上面提出的问题的快速脚本:

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

2
2017-07-24 00:01



只是为了我的好奇心:上面打印的程序是什么? - dma_k
Wikispaces.com上不再托管Pyparsing。去 github.com/pyparsing/pyparsing - PaulMcG


尝试这个:

https://github.com/noprompt/frak

它是用Clojure编写的,并不能保证它输出的是最简洁的表达,但似乎有一些潜力


1
2017-11-25 23:01



您还可以修改由Tom Mitchell开发的候选消除算法来执行注册前学习: artint.info/html/ArtInt_193.html。您将从逐字逐句匹配句子的正则表达式开始,然后通过删除单词来概括它们。 - Simon


也许最好使用支持XPATH的Python HTML解析器(参见 这个相关的问题),查找HTML代码中感兴趣的位,然后记录他们的XPATH - 或者至少是由多个示例共享的那些?


0
2017-07-22 09:02





而不是生成正则表达式,如何使用更一般的正则表达式?如果您的数据被约束到一个本身不包含元素的元素的内部文本,那么与re.findall一起使用的这个正则表达式将产生一个元组列表,其中每个元组都是(标记名,文本):

r'<(?P<tag>[^>]*)>([^<>]+?)</(?P=tag)>'

然后,您可以轻松地从每个元组中提取文本。


-2
2017-07-21 20:42



注意,这个正则表达式对命名组使用特定于python的语法,但它们在大多数其他版本中使用不同的语法。 - Chip Camden