0
  1. 我知道您通常不应该将 Regex 与 HTML 一起使用。我将它用作一次性工具,以快速从具有恒定模式的文件中删除一些数据,并且永远不会再次使用它。我想使用正则表达式来完成这项任务。我了解您不应该使用正则表达式解析 HTML。
  2. 不,我不想使用 XMl Parser、BeautifulSoup、lxml 等。谢谢。:)
  3. 我只想一次性使用它,并永远完成它。

话虽如此,我写的正则表达式只匹配文件中的最后一个“匹配”。我不确定为什么。该文件具有相当恒定的模式:

<p someAttribute="yes"><b someOtherAttribute="no">My Title - </b> My Description</p>
<p someAttribute="yes"><b someOtherAttribute="no">My 2nd Title - </b> My 2nd Description</p>
<p someAttribute="yes"><b someOtherAttribute="no">My 3rd Title - </b> My 3rd Description</p>
<p class="normal" style="margin-left:1"><b style="font-weight:400">Another one </b>The cake is a lie</p>

我不在乎属性。我正在尝试对<b>标签中的内容和后面的内容进行分组。标题和描述。

def parseData(html):
    pattern = re.compile('.*<p.*><b.*>(.+)</b>(.+)</p>.*')

    matches = re.findall(pattern, str(html))

    for match in matches:
        print(match)

def main():
    htmlFile = "myFile.htm"

    browser = UrlBrowser()

    parseData(browser.getHTML(htmlFile))

此模式仅匹配最后一个可用的“匹配” - 我尝试在.*之前添加一个以查看是否会出现问题,但这并没有什么不同。我在正则表达式上缺少什么?

4

3 回答 3

2

这应该这样做。看到这个工作演示

matches = re.findall(r'<b[^>]+>(.*?)</b>(.*?)</p>', str)

正则表达式:

<b            match start of tag '<b'
 [^>]+        any character except: '>' (1 or more times)
 >            match enclosed '>'
 (            group and capture to \1:
  .*?         any character except \n (0 or more times)
 )            end of \1
 </b>         match '</b>'
 (            group and capture to \2:
  .*?         any character except \n (0 or more times)
 )            end of \2
 </p>         match '</p>'

您正在使用.*哪个是贪婪的(匹配尽可能多的数量)。您想添加?到最后,使其成为非贪婪(匹配尽可能少的数量)

re讨论以下量词的文档中获取解释?+???

*、“+”和“?” 限定符都是贪婪的;它们匹配尽可能多的文本。有时这种行为是不希望的;如果 RE <. > 匹配 '<H1>title</H1>',它将匹配整个字符串,而不仅仅是 '<H1>'。添加“?” 在预选赛使其以非贪婪或最低限度的方式执行比赛之后;将匹配尽可能少的字符。使用 。? 在前面的表达式中将仅匹配“<H1>”。

于 2013-09-24T13:49:22.647 回答
1

是你的领先 .* 导致了最后一场比赛。* 和 + 限定符将尽可能多地匹配前面的项目,同时仍然产生匹配

使用“非贪婪”*?代替每个 * 和 +? 代替每个 + 以获得产生匹配的最短可能序列。

请参阅:http ://docs.python.org/3.3/library/re.html#regular-expression-syntax

于 2013-09-24T13:37:56.890 回答
0

更多的事情正在发生。

import re

data = """\
<p someAttribute="yes"><b someOtherAttribute="no">My Title - </b> My Description</p>
<p someAttribute="yes"><b someOtherAttribute="no">My 2nd Title - </b> My 2nd Description</p>
<p someAttribute="yes"><b someOtherAttribute="no">My 3rd Title - </b> My 3rd Description</p>
<p class="normal" style="margin-left:1"><b style="font-weight:400">Another one </b>The cake is a lie</p>"""

print(*re.findall('.*<p.*><b.*>(.+)</b>(.+)</p>.*', data), sep="\n")
#>>> ('My Title - ', ' My Description')
#>>> ('My 2nd Title - ', ' My 2nd Description')
#>>> ('My 3rd Title - ', ' My 3rd Description')
#>>> ('Another one ', 'The cake is a lie')

请注意,您不需要.*在开头和结尾处使用:

print(*re.findall('<p.*><b.*>(.+)</b>(.+)</p>', data), sep="\n")
#>>> ('My Title - ', ' My Description')
#>>> ('My 2nd Title - ', ' My 2nd Description')
#>>> ('My 3rd Title - ', ' My 3rd Description')
#>>> ('Another one ', 'The cake is a lie')

因为正则表达式已经在整个字符串中搜索匹配项。

您可能还希望更喜欢非贪婪的重复,但我认为这不是问题:

print(*re.findall('<p.*?><b.*?>(.+?)</b>(.+?)</p>', data), sep="\n")
#>>> ('My Title - ', ' My Description')
#>>> ('My 2nd Title - ', ' My 2nd Description')
#>>> ('My 3rd Title - ', ' My 3rd Description')
#>>> ('Another one ', 'The cake is a lie')
于 2013-09-24T13:46:26.773 回答