新手Python / Regex:在<a> tags using regex</a>之间拉字符串

时间:2011-12-27 12:41:11

标签: python regex beautifulsoup

需要使用re模块在Python中的href属性标记之间拉取字符串。

我尝试了很多模式,例如:

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>

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

6 个答案:

答案 0 :(得分:6)

你需要使用正则表达式吗?我不认为你这样做,你不能用正则表达式解析SGML,因为SGML本身不是常规的,请参阅这个着名的stackoverflow答案的原因:https://stackoverflow.com/a/1732454/88123

总之。您应该使用lxml Python模块及其xpath实现。 xpath支持使用以。开头的文本进行选择。

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

或者,使用BeautifulSoup Python模块。

答案 1 :(得分: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']

答案 2 :(得分:1)

使用

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

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

注意字符&lt; &GT; /不需要以正则表达式转义

请注意?之后的.*字符会停止量词*的贪婪行为,以便在第一个</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'。因此模式的.*?部分不允许从一行到另一行运行。

要解决此问题,请使用{dot}符号的re.DOTALL规范来表示任何和所有字符。

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

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

据我所知,解析是分析文本并根据标记构建树的表示的过程。
虽然我将文本分析为...分析它而不是为了获得树形表示 当不需要树形表示来从文本中提取数据时,使用正则表达式,并且不要听那些对该主题有宗教考虑的人,比如在有趣但欺骗(在我看来)的帖子中已经给出了链接< / p>

答案 3 :(得分:0)

如果您仍然希望使用正则表达式来进行HTML解析(虽然不推荐使用它,但我不知道为什么)尝试这个:

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

结果将包含CVE-2010-3718

答案 4 :(得分: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

答案 5 :(得分:0)

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

但是如果你想使用regexp,这是我如何在<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回复。