【问题标题】:How to extract markdown links with a regex?如何使用正则表达式提取降价链接?
【发布时间】:2021-08-28 14:56:30
【问题描述】:

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

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

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

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

【问题讨论】:

  • 令人困惑。你能提供一个完整的minimal reproducible example吗?
  • 没有办法处理。请记住,https://www.silly.com/abc)))) 是一个完全有效的 URL。用户必须将它们编码为 %29。甚至 Typora 也不处理嵌入的右括号。
  • @TimRoberts 这里没有,只是为了清楚。这是模棱两可的。期间。
  • 在这种情况下,唯一的方法是使用堆栈并存储开括号的数量。但正如@TimRoberts 指出的那样,它可能会在其他情况下引起问题。
  • 众所周知,HTML 不是一种正则语言,因此不能被正则表达式解析——所以你可能需要使用像 beautifulsoup 这样的模块。

标签: python regex re


【解决方案1】:

我认为您需要区分什么是 markdown 中的有效链接,以及(可选)什么是有效的 url。 例如,markdown 中的有效链接也可以是相对路径,并且 url 可能有也可能没有 'http(s)' 或 'www' 部分。

只需使用link_url = "http[s]?://.+" 甚至link_url = ".*",您的代码就可以运行。它将解决 url 以括号结尾的问题,并且仅意味着您依赖 markdown 结构 []() 来查找 links 。 验证 url 是一个完全不同的讨论:How do you validate a URL with a regular expression in 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)

请注意,我还调整了 link_name,以防止 Markdown 文本中某处出现单个“[”的问题。

【讨论】:

    【解决方案2】:

    对于这些类型的 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)
    

    a demo on 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
    

    注意:这种方法的问题是它失败了,例如像这样的网址

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-17
      • 2014-03-06
      • 2011-05-31
      • 2021-05-29
      • 1970-01-01
      • 2023-02-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多