用于多个标签的 Python 正则表达式

Posted

技术标签:

【中文标题】用于多个标签的 Python 正则表达式【英文标题】:Python regular expression for multiple tags 【发布时间】:2010-11-01 15:30:28 【问题描述】:

我想知道如何从每个<p> 标记中检索所有结果。

import re
htmlText = '<p data="5" size="4">item1</p><p size="4">item2</p><p size="4">item3</p>'
print re.match('<p[^>]*size="[0-9]">(.*?)</p>', htmlText).groups()

结果:

('item1', )

我需要什么:

('item1', 'item2', 'item3')

【问题讨论】:

-1 用于尝试使用正则表达式解析非常规语言。 同意,不是有一个以解析html而闻名的python库吗?美丽汤? htmllib? 感谢您的回复。我需要一种 python 方法来从一个小 html 中打印出 p 标记的所有值,而无需在服务器中安装任何新内容。 【参考方案1】:

你可以像这样使用re.findall

import re
html = '<p data="5" size="4">item1</p><p size="4">item2</p><p size="4">item3</p>'
print re.findall('<p[^>]*size="[0-9]">(.*?)</p>', html)
# This prints: ['item1', 'item2', 'item3']

编辑:...但正如许多评论者指出的那样,使用正则表达式解析 HTML 通常是一个坏主意。

【讨论】:

谢谢!我刚刚在 Python 文档上找到了它! docs.python.org/dev/howto/regex.html 很抱歉,这是一个糟糕的答案。如果 size 属性和右括号之间有空格怎么办:

?

@Triptych:没有。您是否考虑过 OP 知道他在做什么的可能性? 8-) 问题是“我如何解析这个 HTML?”那么我不会建议使用正则表达式。但它是“如何使我的正则表达式工作?”,这是对这个问题的回答。 -1:给出了一个正则表达式解析html的例子,甚至没有说这真的很糟糕,很多新手都会读。邪恶来自这样的行为。 @RichieHindle:原始发帖人没有说任何关于使正则表达式工作的内容。他说他想从每个 p 标签中检索结果。正则表达式不适合这样做。【参考方案2】:

对于此类问题,建议使用 DOM 解析器,而不是正则表达式。

我看到Beautiful Soup 经常被推荐用于 Python

【讨论】:

【参考方案3】:

或者,xml.dom.minidom 将解析您的 HTML,如果,

...格式正确 ...您将其嵌入到单个根元素中。

例如,

>>> import xml.dom.minidom
>>> htmlText = '<p data="5" size="4">item1</p><p size="4">item2</p><p size="4">item3</p>'
>>> d = xml.dom.minidom.parseString('<not_p>%s</not_p>' % htmlText)
>>> tuple(map(lambda e: e.firstChild.wholeText, d.firstChild.childNodes))
('item1', 'item2', 'item3')

【讨论】:

【参考方案4】:

美丽的汤绝对是解决此类问题的方法。代码更简洁,更易于阅读。一旦你安装了它,所有的标签看起来都是这样的。

from BeautifulSoup import BeautifulSoup
import urllib2

def getTags(tag):
  f = urllib2.urlopen("http://cnn.com")
  soup = BeautifulSoup(f.read())
  return soup.findAll(tag)


if __name__ == '__main__':
  tags = getTags('p')
  for tag in tags: print(tag.contents)

这将打印出 p 标签的所有值。

【讨论】:

感谢您的回复。我只需要一种 python 方法来打印出 p 标签的所有值,而无需在服务器中安装任何新东西。【参考方案5】:

正则表达式的答案非常脆弱。这是证明(以及一个有效的 BeautifulSoup 示例)。

from BeautifulSoup import BeautifulSoup

# Here's your HTML
html = '<p data="5" size="4">item1</p><p size="4">item2</p><p size="4">item3</p>'

# Here's some simple HTML that breaks your accepted 
# answer, but doesn't break BeautifulSoup.
# For each example, the regex will ignore the first <p> tag.
html2 = '<p size="4" data="5">item1</p><p size="4">item2</p><p size="4">item3</p>'
html3 = '<p data="5" size="4" >item1</p><p size="4">item2</p><p size="4">item3</p>'
html4 = '<p data="5" size="12">item1</p><p size="4">item2</p><p size="4">item3</p>'

# This BeautifulSoup code works for all the examples.
paragraphs = BeautifulSoup(html).findAll('p')
items = [''.join(p.findAll(text=True)) for p in paragraphs]

使用 BeautifulSoup。

【讨论】:

我认为你不需要导入 re.另外,我很好奇你的例子提供了什么,而我的例子除了列表理解之外没有。 Brett - 我的将正确处理像

item1

这样的情况,而你的会失败。此外,此处的 items 数组将转换为字符串列表,而您的示例将返回 tag.contents,这实际上是一个(非常消耗内存的)BeautifulSoup 对象。
酷!我不知道该对象是内存密集型的,我只在小型解析项目中使用过它,从未遇到过问题。感谢更新。我根据你的解释投了你的票。 我使用 BeautifulSoup 处理一些非常大 (500KB+) 的 HTML 文件,如果你不学会节省内存,你就会遇到一堵难关。 BeautifulSoup 非常方便,但效率不高。

以上是关于用于多个标签的 Python 正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

不包含多个特定单词的字符串的正则表达式

用于查找html标签的正则表达式[重复]

[python] 常用正则表达式爬取网页信息及分析HTML标签总结

用于匹配任意两个 HTML 标签的正则表达式

用于查找 HTML 标签及其内容的正则表达式的否定 - java

[Python正则表达式] 字符串中xml标签的匹配