首页 > 解决方案 > 如何使用正则表达式提取降价链接?

问题描述

我目前有用于解析降价文本的 Python 代码,以便提取降价链接的方括号内的内容以及超链接。

import re

# Extract []() style links
link_name = "[^]]+"
link_url = "http[s]?://[^)]+"
markup_regex = f'\[({link_name})]\(\s*({link_url})\s*\)'

for match in re.findall(markup_regex, '[a link](https://www.wiki.com/atopic_(subtopic))'):
    name = match[0]
    url = match[1]
    print(url)
    # url will be https://wiki.com/atopic_(subtopic

这将无法获取正确的链接,因为它匹配第一个括号,而不是最后一个。

我怎样才能使正则表达式尊重直到最后一个括号?

标签: pythonregexre

解决方案


对于这些类型的 url,您需要一种只有较新regex模块支持的递归方法:

import regex as re

data = """
It's very easy to make some words **bold** and other words *italic* with Markdown. 
You can even [link to Google!](http://google.com)
[a link](https://www.wiki.com/atopic_(subtopic))
"""

pattern = re.compile(r'\[([^][]+)\](\(((?:[^()]+|(?2))+)\))')

for match in pattern.finditer(data):
    description, _, url = match.groups()
    print(f"{description}: {url}")

这产生

link to Google!: http://google.com
a link: https://www.wiki.com/atopic_(subtopic)

在 regex101.com 上查看演示


这个神秘的小美女归结为

\[([^][]+)\]           # capture anything between "[" and "]" into group 1
(\(                    # open group 2 and match "("
    ((?:[^()]+|(?2))+) # match anything not "(" nor ")" or recurse group 2
                       # capture the content into group 3 (the url)
\))                    # match ")" and close group 2

注意:这种方法的问题是它对于例如像这样的 url 失败了

[some nasty description](https://google.com/()
#                                          ^^^

这在 Markdown 中肯定是完全有效的。如果您遇到任何此类 url,请改用适当的解析器。


推荐阅读