python中的正则表达式问题
好的,所以我正在使用正则表达式来搜索站点中的所有标头信息。
我已经编译了正则表达式:
regex = re.compile(r''' <h[0-9]>\s? (<a[ ]href="[A-Za-z0-9.]*">)?\s? [A-Za-z0-9.,:'"=/?;\s]*\s? [A-Za-z0-9.,:'"=/?;\s]? ''', re.X)
当我在python reg ex中运行此命令时。测试仪,效果很好。
样本数据:
<body> <h1>Dog </h1> <h2>Cat </h2> <h3>Fancy </h3> <h1>Tall cup of lemons</h1> <h1><a href="dog.com">Dog thing</a></h1> </body>
现在,在REDemo中,它的运行非常出色。
但是,当我将其放入python代码时,它仅显示<a href="dog.com">
这是我的python代码,我不确定我是在做错什么,还是翻译中丢失了什么。我感谢帮助。
stories=[] response = urllib2.urlopen('http://apricotclub.org/duh.html') html = response.read().lower() p = re.compile('<h[0-9]>\s?(<a href=\"[A-Za-z0-9.]*\">)?\s?[A-Za-z0-9.,:\'\"=/?;\s]*\s?[A-Za-z0-9.,:\'\"=/?;\s]?') stories=re.findall(p, html) for i in stories: if len(i) >= 5: print i
我还要注意,当我从正则表达式中取出((<a href=\"[A-Za-z0-9.]*\">)?
时,对非链接<hN >
行。
解决方案
请不要在python中手动解析html!有许多更好的选择。我会推荐美妙的BeautifulSoup
使用正则表达式解析事物适用于正则语言。 HTML不是一种常规语言,这些天我们在网页上找到的东西绝对是垃圾。 BeautifulSoup处理具有类似浏览器启发式功能的标记汤HTML,因此我们将获得类似于浏览器显示内容的已解析HTML。
缺点是它不是很快。有一个用于解析格式正确的html的lxml,但如果我们不确定100%确定输入将始终格式正确,则应该使用BeautifulSoup。
由于锚标签周围有花括号,因此该部分被解释为捕获组。这将导致仅返回捕获组,而不是整个正则表达式匹配项。
将整个正则表达式放在花括号中,我们将看到正确的匹配项显示为返回的元组中的第一个元素。
但是确实,我们应该使用一个真正的解析器。
在过去的几天中,已经以多种形式提出了这个问题,所以我要说得很清楚。
使用BeautifulSoup,html5lib或者lxml.html。请。
如前所述,我们应该使用解析器而不是正则表达式。
但是,这是使用正则表达式的方法:
import re html = ''' <body> <h1>Dog </h1> <h2>Cat </h2> <h3>Fancy </h3> <h1>Tall cup of lemons</h1> <h1><a href="dog.com">Dog thing</a></h1> </body> ''' p = re.compile(r''' <(?P<header>h[0-9])> # store header tag for later use \s* # zero or more whitespace (<a\shref="(?P<href>.*?)">)? # optional link tag. store href portion \s* (?P<title>.*?) # title \s* (</a>)? # optional closing link tag \s* </(?P=header)> # must match opening header tag ''', re.IGNORECASE + re.VERBOSE) stories = p.finditer(html) for match in stories: print '%(title)s [%(href)s]' % match.groupdict()
这里有一些很好的正则表达式资源:
- Python正则表达式HOWTO
- Regular-Expressions.info
到目前为止的答案:
最好使用解析引擎。它可以以优雅的方式涵盖很多情况。我尝试过BeautifulSoup,我非常喜欢。也很容易使用,提供了出色的教程。
如果有时感觉像用大炮射击苍蝇,则可以使用正则表达式进行快速解析。如果我们需要的是经过修改的代码,它将捕获所有标头(即使是多行标头):
p = re.compile(r'<(h[0-9])>(.+?)</>', re.IGNORECASE | re.DOTALL) stories = re.findall(p, html) for i in stories: print i
我已经使用beautifulsoup来解析我们所需的HTML。我在上面的HTML代码中
名为foo.html的文件,以后又作为文件对象读取。
from BeautifulSoup import BeautifulSoup H_TAGS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] def extract_data(): """Extract the data from all headers in a HTML page.""" f = open('foo.html', 'r+') html = f.read() soup = BeautifulSoup(html) headers = [soup.findAll(h) for h in H_TAGS if soup.findAll(h)] lst = [] for x in headers: for y in x: if y.string: lst.append(y.string) else: lst.append(y.contents[0].string) return lst
上面的函数返回:
>>> [u'Dog ', u'Tall cup of lemons', u'Dog thing', u'Cat ', u'Fancy ']
我们可以在h_tags列表中添加任意数量的标题标签。我已经假设了所有标题。
如果我们可以使用BeautifulSoup轻松解决问题,那么最好使用它。 :)