Python正则表达式无法识别Markdown链接

5 投票
1 回答
2889 浏览
提问于 2025-04-18 04:55

我正在尝试在Python中写一个正则表达式,用来在Markdown文本中找到网址。
一旦找到网址,我想检查一下这个网址是否被Markdown链接包裹住:也就是说,是否有“文本”的格式。
我在这个检查上遇到了问题。我使用了一个正则表达式 - link_exp - 来搜索,但结果并不是我预期的,我有点搞不清楚状况。

这可能是我没注意到的简单问题。

下面是代码和link_exp正则表达式的解释:

import re

text = '''
[Vocoder](http://en.wikipedia.org/wiki/Vocoder )
[Turing]( http://en.wikipedia.org/wiki/Alan_Turing)
[Autotune](http://en.wikipedia.org/wiki/Autotune)
http://en.wikipedia.org/wiki/The_Voder
'''

urls = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', text) #find all urls
for url in urls:
    url = re.escape(url)
    link_exp = re.compile('\[.*\]\(\s*{0}\s*\)'.format(url) ) # expression with url wrapped in link syntax.     
    search = re.search(link_exp, text)
    if search != None:
        print url

# expression should translate to:
# \[ - literal [
# .* - any character or no character 
# \] - literal ]
# \( - literal (
# \s* - whitespaces or no whitespace 
# {0} - the url
# \s* - whitespaces or no whitespace 
# \) - literal )
# NOTE: I am including whitespaces to encompass cases like [foo]( http://www.foo.sexy   )  

我得到的输出只有:

http\:\/\/en\.wikipedia\.org\/wiki\/Vocoder

这意味着这个表达式只找到了在闭合括号前有空格的链接。
这并不是我想要的,我还想考虑没有空格的链接情况。

你觉得你能帮我解决这个问题吗?
谢谢!

1 个回答

9

这里的问题在于你用来提取网址的正则表达式,它把)也包含在网址里了。这就意味着你在寻找闭合括号的时候会多找一次。除了第一个网址以外,其他的都会出现这个问题(因为空格帮你解决了这个问题)。

我不太清楚你网址正则表达式的每一部分具体想干什么,但其中有一段是这样写的:[$-_@.&+],它包含了从$(ASCII 36)到_(ASCII 137)的一系列字符,这里面有很多你可能并不想要的字符,包括)

与其先找网址,然后再检查它们是否在链接里,为什么不一次性同时做这两件事呢?这样你的网址正则表达式可以更简单,因为额外的限制条件让它不太可能匹配到其他东西:

# Anything that isn't a square closing bracket
name_regex = "[^]]+"
# http:// or https:// followed by anything but a closing paren
url_regex = "http[s]?://[^)]+"

markup_regex = '\[({0})]\(\s*({1})\s*\)'.format(name_regex, url_regex)

for match in re.findall(markup_regex, text):
    print match

结果:

('Vocoder', 'http://en.wikipedia.org/wiki/Vocoder ')
('Turing', 'http://en.wikipedia.org/wiki/Alan_Turing')
('Autotune', 'http://en.wikipedia.org/wiki/Autotune')

如果你需要更严格一点,可能还可以改进一下网址的正则表达式。

撰写回答