我正在尝试使用正则表达式创建一个简单的基于Python的HTML解析器。我的问题是试图让我的正则表达式搜索查询找到所有可能的匹配,然后将它们存储在元组中。
假设我有一个页面,其中存储了以下变量HTMLtext
:
<ul>
<li class="active"><b><a href="/blog/home">Back to the index</a></b></li>
<li><b><a href="/blog/about">About Me!</a></b></li>
<li><b><a href="/blog/music">Audio Production</a></b></li>
<li><b><a href="/blog/photos">Gallery</a></b></li>
<li><b><a href="/blog/stuff">Misc</a></b></li>
<li><b><a href="/blog/contact">Shoot me an email</a></b></li>
</ul>
我想对此文本执行正则表达式搜索,并返回包含每个链接的最后一个URL目录的元组。所以,我想回复这样的事情:
pages = ["home", "about", "music", "photos", "stuff", "contact"]
到目前为止,我可以使用正则表达式搜索一个结果:
pages = [re.compile('<a href="/blog/(.*)">').search(HTMLtext).group(1)]
运行此表达式会生成pages = ['home']
。
如何让正则表达式搜索继续整个文本,将匹配的文本附加到此元组?
(注意:I know I probably should NOT be using regex to parse HTML。但我想知道如何做到这一点。)
答案 0 :(得分:2)
使用re
模块的findall
功能:
pages = re.findall('<a href="/blog/([^"]*)">',HTMLtext)
print(pages)
输出:
['home', 'about', 'music', 'photos', 'stuff', 'contact']
答案 1 :(得分:2)
您的模式不适用于所有输入,包括您的输入。 .*
过于贪婪(从技术上讲,它会找到最大匹配),导致它成为第一个href和最后一个相应的关闭。解决这个问题的两种最简单的方法是使用最小匹配,否则使用否定字符类。
# minimal match approach
pages = re.findall(r'<a\s+href="/blog/(.+?)">',
full_html_text, re.I + re.S)
# negated charclass approach
pages = re.findall(r'<a\s+href="/blog/([^"]+)">',
full_html_text, re.I)
对于简单且合理的约束文本,正则表达式很好;毕竟,这就是我们在编辑HTML时在文本编辑器中使用正则表达式搜索和替换的原因!但是,对输入的了解越少,它就会变得越来越复杂,例如
<a
和href
之间有其他字段介入,例如<a title="foo" href="bar">
<A HREF='foo'>
href='/foo/bar'
而不是href="/foo/bar"
这不是关注的唯一清单;还有其他人。所以using regexes on HTML thus is possible,但是否是权宜之计取决于太多其他因素来判断。
然而,从您展示的小例子来看,它看起来完全适合您自己的情况。你只需要调整你的模式并调用正确的方法。
答案 2 :(得分:1)
使用findall
代替search
:
>>> pages = re.compile('<a href="/blog/(.*)">').findall(HTMLtext)
>>> pages
['home', 'about', 'music', 'photos', 'stuff', 'contact']
答案 3 :(得分:1)
re.findall()函数和re.finditer()函数用于查找多个匹配项。
答案 4 :(得分:1)
要查找所有结果,请使用findall()
。此外,您只需编译re
一次,然后您就可以重复使用它。
href_re = re.compile('<a href="/blog/(.*)">') # Compile the regexp once
pages = href_re.findall(HTMLtext) # Find all matches - ["home", "about",