【问题标题】:Python regex - do not match word when it is in html tagPython 正则表达式 - 当它在 html 标记中时不匹配单词
【发布时间】:2016-01-09 13:24:07
【问题描述】:

如果它在 html 标签中,我需要编写不匹配单词的正则表达式。

这里是文本示例:

asdd qwe <a href="http://example.com" title="Some title with word qwe" class="external-link" rel="nofollow">  qwe 

我的正则表达式现在看起来像这样:

(?!(\<.+))[^a-zA-ZąćęłńóśźżĄĆĘŁŃÓŚŹŻ](<class="bad-word"(?: style="[^"]+")?>)?(qwe)(<>)?[^a-zA-ZąćęłńóśźżĄĆĘŁŃÓŚŹŻ](?!.+\>)

这有点复杂,但每个人都认为当我在 regex101.com 和 regexr.com 上测试它时,它只匹配 html 标记之后的单词。

知道为什么吗?

编辑:

我不想使用 html 解析器或 DOM 操作,我不想更改这么多代码。

def test_tagged_word_present(self):
    input = 'words <a href="example.com" title="title with word qwe" class="external-link" rel="nofollow"> qwe some other words'
    expected = 'words <a href="example.com" title="title with word qwe" class="external-link" rel="nofollow"><strong class="bad-word" style="color:red">qwe</strong> some other words'
    parser = self.get_test_parser(input, search_word='qwe')
    text = parser.mark_words()
    self.assertEqual(text, expected)

一切正常,除了正则表达式仍然在标题中缓存qwe

【问题讨论】:

  • 如何使用解析器,将 html 的文本内容反馈给您,然后与文本内容进行匹配?这样一来,标签内的任何文本都不会返回给您。
  • 您是否要匹配 标签之外的所有内容?
  • @Ephreal 我正在尝试匹配不在任何类型的 html 标记中的给定单词的每个出现。
  • 另一种选择,使用 html 解析器 stackoverflow.com/a/2613246/3526330
  • 我认为我无法回答你的问题,确实它并没有按照你在正则表达式 101 中所说的那样做。但是,如果它有效,为什么不使用它呢?您在寻找更简单的示例吗?

标签: python regex


【解决方案1】:

你为什么不使用以下方法:首先从字符串中删除任何html标签,然后搜索单词?

import re
>>> s = "asdd qwe <a href="http://example.com" title="Some title with word qwe" class="external-link" rel="nofollow">  qwe "
>>> re.findall(r"\bqwe\b", re.sub(r"<[^>]*>", "", s))
['qwe', 'qwe']

【讨论】:

  • 我需要这个 html 标记在文本中。我真的怀疑你的想法,但在这种情况下不是。
  • 这会修改文本的副本。所以你可以轻松做到:if re.findall(...) do_something_with_string(s);它只是让测试您要查找的单词是否出现在任何标签之外变得容易。
  • 也许使用 re.search 代替,然后使用索引以任何你想要的方式分割字符串
【解决方案2】:

要排除 HTML 标记中的内容,一个很好的技巧是使用“不跟随”并在其中包含尖括号字符。例如,您的正则表达式以此结尾:

(?!.+\>)

这大概应该意味着'后面没有一个或多个字符和一个右尖括号。'

但是,“一个或多个字符”过于宽泛,并且匹配的次数超出了您的预期:如果您将其设置得更严格一点,那么它就不会那么贪婪了:

(?![^<>]*>)

因此,'后面没有非尖括号和右括号。'

这样它只会在它在 HTML 标记之外时进行替换,因为如果它在内部,那么它将匹配,所以后面的 NOT 将阻止它替换。

您可能还需要在其他字符类中包含 以限制它们。

请注意,这并不是 100% 严格遵守的,因为属性中可以合法地包含这些字符,但是在许多情况下,您对自己的输入有足够的了解,因此您可以安全地使用 [^] 来简化任务,而无需导致任何问题。

$ python
Python 2.6.6 (r266:84292, Jan 22 2014, 09:42:36)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> mystring = 'asdd qwe <a href="http://example.com" title="Some title with word qwe" class="external-link" rel="nofollow">  qwe '
>>> import re
>>> p=re.compile(r'([^\s<>]+)(?![^<>]*>)')
>>> p.findall(mystring)
['asdd', 'qwe', 'qwe']
>>>
$

第二次测试:

$ python
Python 2.6.6 (r266:84292, Jan 22 2014, 09:42:36)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> mystring = r'words <a href="example.com" title="title with word qwe" class="external-link" rel="nofollow"> qwe some other words'
>>> p=re.compile(r'([^\s<>]+)(?![^<>]*>)')
>>> p.findall(mystring)
['words', 'qwe', 'some', 'other', 'words']
>>> mystring = r'words <a href="example.com" title="title with word qwe" class="external-link" rel="nofollow"> qwe <strong class="bad-word" style="color:red">podmiotu</strong> some other words'
>>> p.findall(mystring)
['words', 'qwe', 'podmiotu', 'some', 'other', 'words']
>>>

请注意,'qwe' 在两个字符串中,在 HTML 标记之外,所以我认为它应该匹配。

要搜索特定单词,只需在正则表达式中使用它:

如果它在 HTML 之外,则查找单词“some”:

>>> p=re.compile(r'(some)(?![^<>]*>)')
>>> p.findall(mystring)
['some']
>>>

如果它在 HTML 之外,则找到单词“外部”(失败,正确):

>>> p=re.compile(r'(external)(?![^<>]*>)')
>>> p.findall(mystring)
[]
>>>

【讨论】:

  • 它就像一个魅力,但不是在 Python 中。知道为什么吗?在我的测试中,我的文本与我的问题相同,但更改正则表达式后,测试未通过,链接中的单词仍然匹配。
  • 你能包括你的预期输出吗?我不清楚你实际上想要匹配什么并最终得到什么。谢谢。
  • 测试用例现在有问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-12
  • 1970-01-01
  • 2012-04-02
  • 2013-06-10
  • 2015-12-13
相关资源
最近更新 更多