【问题标题】:Extracting URL and anchor text from Markdown using Python使用 Python 从 Markdown 中提取 URL 和锚文本
【发布时间】:2015-08-24 10:14:46
【问题描述】:

我正在尝试从 Markdown 中提取锚文本和相关 URL。我见过this 的问题。不幸的是,answer 似乎没有完全回答我想要的。

在 Markdown 中,插入链接有两种方式:

示例 1:

[anchor text](http://my.url)

示例 2:

[anchor text][2]

   [1]: http://my.url

我的脚本是这样的(注意我使用的是regex,而不是re):

import regex
body_markdown = "This is an [inline link](http://google.com). This is a [non inline link][4]\r\n\r\n  [1]: http://yahoo.com"

rex = """(?|(?<txt>(?<url>(?:ht|f)tps?://\S+(?<=\P{P})))|\(([^)]+)\)\[(\g<url>)\])"""
pattern = regex.compile(rex)
matches = regex.findall(pattern, body_markdown, overlapped=True)
for m in matches:
    print m

这会产生输出:

('http://google.com', 'http://google.com')
('http://yahoo.com', 'http://yahoo.com')

我的预期输出是:

('inline link', 'http://google.com')
('non inline link', 'http://yahoo.com')

如何从 Markdown 中正确捕获锚文本?

【问题讨论】:

    标签: python regex markdown


    【解决方案1】:

    如何从 Markdown 中正确捕获锚文本?

    将其解析为结构化格式(例如 html),然后使用适当的工具提取链接标签和地址。

    import markdown
    from lxml import etree
    
    body_markdown = "This is an [inline link](http://google.com). This is a [non inline link][1]\r\n\r\n  [1]: http://yahoo.com"
    
    doc = etree.fromstring(markdown.markdown(body_markdown))
    for link in doc.xpath('//a'):
      print link.text, link.get('href')
    

    这让我很感动:

    inline link http://google.com
    non inline link http://yahoo.com
    

    另一种方法是编写自己的 Markdown 解析器,这似乎是集中精力的错误地方。

    【讨论】:

      【解决方案2】:

      修改@mreinhardt 解决方案以返回所有对(text, link) 的列表(而不是字典):

      import re
          
      INLINE_LINK_RE = re.compile(r'\[([^\]]+)\]\(([^)]+)\)')
      FOOTNOTE_LINK_TEXT_RE = re.compile(r'\[([^\]]+)\]\[(\d+)\]')
      FOOTNOTE_LINK_URL_RE = re.compile(r'\[(\d+)\]:\s+(\S+)')
      
      
      def find_md_links(md):
          """ Return dict of links in markdown """
      
          links = list(INLINE_LINK_RE.findall(md))
          footnote_links = dict(FOOTNOTE_LINK_TEXT_RE.findall(md))
          footnote_urls = dict(FOOTNOTE_LINK_URL_RE.findall(md))
      
          for key in footnote_links.keys():
              links.append((footnote_links[key], footnote_urls[footnote_links[key]]))
      
          return links
          
      

      我在 python3 中使用repeated 链接进行测试:

      [h](http://google.com) and [h](https://goog.e.com)
      

      【讨论】:

        【解决方案3】:

        您可以使用几个简单的re 模式来做到这一点:

        import re
        
        INLINE_LINK_RE = re.compile(r'\[([^\]]+)\]\(([^)]+)\)')
        FOOTNOTE_LINK_TEXT_RE = re.compile(r'\[([^\]]+)\]\[(\d+)\]')
        FOOTNOTE_LINK_URL_RE = re.compile(r'\[(\d+)\]:\s+(\S+)')
        
        
        def find_md_links(md):
            """ Return dict of links in markdown """
        
            links = dict(INLINE_LINK_RE.findall(md))
            footnote_links = dict(FOOTNOTE_LINK_TEXT_RE.findall(md))
            footnote_urls = dict(FOOTNOTE_LINK_URL_RE.findall(md))
        
            for key, value in footnote_links.iteritems():
                footnote_links[key] = footnote_urls[value]
            links.update(footnote_links)
        
            return links
        

        然后你可以像这样使用它:

        >>> body_markdown = """
        ... This is an [inline link](http://google.com).
        ... This is a [footnote link][1].
        ...
        ... [1]: http://yahoo.com
        ... """
        >>> links = find_md_links(body_markdown)
        >>> links
        {'footnote link': 'http://yahoo.com', 'inline link': 'http://google.com'}
        >>> links.values()
        ['http://yahoo.com', 'http://google.com']
        

        【讨论】:

        • 这会因常见的 Markdown 结构而失败,例如 This is a [footnote link][].\n\n[footnote link]: http://google.com/'
        • 有趣,感谢@larsks 指出这一点,因为它没有在最初的问题陈述中说明。这很容易解决,但如果有很多特殊情况(我不太了解降价),那么使用适当的解析器确实会更好。如果这个简单的任务是他唯一需要做的事情,那么使用一个似乎有很多开销。
        • 这个body_markdown = """this is [foo](http://hola.com). And [bla](#hols).[foo](http://hoo)""" 失败了。结果只有最后一个foo:links {'foo': 'http://hoo', 'bla': '#hols'}。也许将 dict 更改为在某处列出可以解决问题?
        • @mreinhardt 你能帮帮我吗?我认为您的解决方案可以很容易地修改以适应我的 question 使用 re 模块。提前致谢。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-19
        • 1970-01-01
        • 2018-01-22
        • 1970-01-01
        • 2011-10-03
        相关资源
        最近更新 更多