2011-12-27 50 views
1

需要使用re模块在Python中的href属性标签之间拉字符串。新手Python /正则表达式:使用正则表达式在<a>标签之间拉字符串

我已经试过无数的图案,如:

patFinderLink = re.compile('\>"(CVE.*)"\<\/a>') 

例子:我需要从拉是什么(在这种情况下, “CVE-2010-3718”)标记之间:

<pre> 
<a href="https://www.redhat.com/security/data/cve/CVE-2010-3718.html">CVE-2010-3718</a> 
</pre> 

我在这里做错了什么?任何意见是极大的赞赏。先谢谢你。

太阳

回答

0

我很惊讶没有人建议用BeautifulSoup:

这里是我会怎么做:

from BeautifulSoup import BeautifulSoup 
import re 

hello = """ 
<pre> 
<a href="https://www.redhat.com/security/data/cve/CVE-2010-3718.html">CVE-2010-3718</a> 
<a href="https://www.redhat.com/security/data/cve/CVE-2010-3710.html">CVE-2010-3718</a> 
<a href="https://www.redhat.com/security/data/cve/CVE-2010-3700.html">CVE-2010-3718</a> 
</pre> 
""" 

target = re.compile("CVE-\d+-\d+.html") 
commentSoup = BeautifulSoup(hello) 
atags = commentSoup.findAll(href=target) 
for a in atags: 
    match = re.findall(target, a['href'])[0] 
    print match 

结果:

CVE-2010-3718.html 
CVE-2010-3710.html 
CVE-2010-3700.html 
+0

尽管其他答案提出了更优雅的解决方案,这一个为我捏了一把。谢谢。 – user1117603 2011-12-27 22:30:09

6

你需要使用正则表达式吗?我不认为你这样做,你不能用正则表达式解析SGML,因为SGML本身并不经常,请参阅这个着名的计算器回答的推理:https://stackoverflow.com/a/1732454/88123

无论如何。您应该使用lxml Python模块及其xpath实现。 xpath支持选择以开头的文本。

XPath在这种情况下将是//h1/text()

或者,使用Python模块BeautifulSoup

+0

+1对于lxml,我会为着名的反注册答案给出另一个+1! – 2011-12-27 13:13:08

+0

'// h1/text()'? – Acorn 2011-12-27 13:15:30

+0

@Acorn - 我实际上看过他链接的页面,看到了h1中表示的CVE编号。 – ikanobori 2011-12-27 13:16:23

2

不要试图使用正则表达式来解析HTML或XML。使用解析器,如lxml

import lxml.html as lh 

tree = lh.fromstring(html) 

print tree.xpath("//pre/a[starts-with(., 'CVE')]/text()") 

结果:

 
['CVE-2010-3718'] 
+0

_lxml_至少比正则表达式慢20倍。事实上,我有一天测量了100次,但它可能并不代表中等量的_lxml_解决方案的时间超过正则表达式解决方案,所以我更愿意说20 ..... – eyquem 2011-12-27 14:25:23

0

如果你仍然想使用HTML正则表达式解析(虽然它不是建议作为被alredy提到的 - 但我不知道为什么)试试这个:

a = re.compile('<a href=".*">(.*)</a>') 
result = a.match(string).group(0) 

结果将包含CVE-2010-3718

1

使用

re.compile('">(CVE.*?)</a>') 

# instead of your re.compile('\>"(CVE.*)"\<\/a>') 

注意的是字符<> /不需要在正则表达式模式

进行转义并注意.*?字符停止以便量词*的贪婪行为的匹配在第一个</a>受到阻止时停止。关于这一点请参阅文档,这是基本的

有时使用re时,分析一个XML有问题| GML文本
有一次,我被告知,一个可能的问题是,标签可以在几行写,例如:

ss = ''' 
<pre> 
    <a href="https://www.redhat.com/security/data/cve/CVE-2010-3718.html">CVE-20 
    10-371 
    8</a> 
</pre>''' 

在这种情况下,不会有任何匹配,因为在正则表达式模式中用作符号的点不会象征换行符'\ n'。因此该模式的.*?部分将不允许按行运行。

要纠正此问题,请使用re.DOTALL规范,该规范为点符号提供了表示任何和所有字符的权力。

请注意,常见的信念是,不得使用工具来解析SGML或XML文本。但很少有人能够彻底解释为什么。我是其中一个不知道原因的人。

但个人而言,我认为正则表达式可以用来分析文本。我写'分析'而不是'PARSE'。

据我所知,解析是分析文本和基于标签构建树形表示的过程。
虽然我将文本分析定义为...分析它,但没有获得树表示的目的。
当树形表示不需要从文本中提取数据时,请使用正则表达式,并且不要听那些对这个主题有宗教考虑的人,比如在有趣但欺骗性(在我看来)的帖子中,其链接已被鉴于

0

正如其他人已经建议的,正则表达式通常不是HTML解析的好工具。

但是,如果你想使用正则表达式,这是我怎么会提取<a> </a>标签之间的两个URL的所有元组和内容的一个例子:

import re 

#example html string with various hits 
html_string = """ 
    <pre> 
    <a href="https://www.redhat.com/security/data/cve/CVE-2010-3718.html">CVE-2010-3718</a> 
    <a href="https://www.redhat.com/security/data/cve/CVE-2010-3710.html">CVE-2010-3710</a> 
    <a href="https://www.redhat.com/security/data/cve/CVE-2010-3700.html">CVE-2010-3700</a> 
    </pre> 
""" 

#regular expression: 
pattern = re.compile('<a href=([^>]*)>([^<]*)</a>') 

#find all matches in our html string: 
tuples = pattern.findall(html_string) 

for tuple in tuples: 
    print "%s —> %s" % (tuple[1], tuple[0]) 

正如其他人所提到的,LXML将是一个更适合工具。

如果你打算这样做,我建议你按照@Acorn的回复。

相关问题