用指向 URL 的链接替换文本中的 URL

Posted

技术标签:

【中文标题】用指向 URL 的链接替换文本中的 URL【英文标题】:replace URLs in text with links to URLs 【发布时间】:2010-12-16 04:47:16 【问题描述】:

我想使用 Python 将正文中的所有 URL 替换为指向这些 URL 的链接,就像 Gmail 所做的那样。 这可以在单行正则表达式中完成吗?

编辑:我的正文只是指纯文本 - 没有 html

【问题讨论】:

虽然有人会假设您正在创建 HTML,因为纯文本没有链接与 URL 的特殊符号。因此,您会将纯文本中的http://blah.com/page/ref/something?param=foo 转换为<a href="http://blah.com/page/ref/something?param=foo">http://blah.com/page/ref/something?param=foo</a>,是吗? 是的,它将被插入到 HTML 文档中 到目前为止的答案都集中在匹配 URL 上。换成链接怎么样? 【参考方案1】:

我四处寻找,尝试了这些解决方案,但对它们的可读性或功能不满意,所以我推出了以下内容:

_urlfinderregex = re.compile(r'http([^\.\s]+\.[^\.\s]*)+[^\.\s]2,')

def linkify(text, maxlinklength):
    def replacewithlink(matchobj):
        url = matchobj.group(0)
        text = unicode(url)
        if text.startswith('http://'):
            text = text.replace('http://', '', 1)
        elif text.startswith('https://'):
            text = text.replace('https://', '', 1)

        if text.startswith('www.'):
            text = text.replace('www.', '', 1)

        if len(text) > maxlinklength:
            halflength = maxlinklength / 2
            text = text[0:halflength] + '...' + text[len(text) - halflength:]

        return '<a class="comurl" href="' + url + '" target="_blank" rel="nofollow">' + text + '<img class="imglink" src="/images/linkout.png"></a>'

    if text != None and text != '':
        return _urlfinderregex.sub(replacewithlink, text)
    else:
        return ''

您需要获取链接输出图像,但这很容易。这专门针对用户提交的文本,例如我认为通常是人们正在处理的 cmets。

【讨论】:

我也环顾四周,包括一些实现了自己的链接功能的框架,我发现这个对于非复杂目的来说是最易读的。 这是迄今为止我在 *** 上找到的最好的基于正则表达式的文本-->HTML 脚本。它甚至比公认的答案要好得多。对于 Python 3.x,我只需要将行 text = unicode(URL) 更改为 text = str(URL);并删除链接输出图像。【参考方案2】:
/\w+:\/\/[^\s]+/

【讨论】:

【参考方案3】:

Gmail 在 URL 方面更加开放,但也不总是正确的。例如它将把 www.a.b 和 http://a.b 变成一个超链接,但它经常因为包装文本和不常见(但有效)的 URL 字符而失败。

请参阅appendix A. A. Collected BNF for URI for syntax,并使用它来构建一个合理的正则表达式,该表达式还将考虑 URL 周围的内容。建议您考虑 URL 最终可能出现的几种情况。

【讨论】:

【参考方案4】:

您可以使用 DOM/HTML 解析库(请参阅 html5lib )加载文档,获取所有文本节点,将它们与正则表达式匹配,然后用正则表达式替换文本节点,并使用围绕它的锚点替换 URI PCRE 如:

/(https?:[;\/?\\@&=+$,\[\]A-Za-z0-9\-_\.\!\~\*\'\(\)%][\;\/\?\:\@\&\=\+\$\,\[\]A-Za-z0-9\-_\.\!\~\*\'\(\)%#]*|[KZ]:\\*.*\w+)/g

我很确定你可以通过搜索找到某种实用工具来做到这一点,但我想不出任何东西。

编辑:尝试在此处使用答案:How do I get python-markdown to additionally "urlify" links when formatting plain text?

import re

urlfinder = re.compile("([0-9]1,3\\.[0-9]1,3\\.[0-9]1,3\\.[0-9]1,3|((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+):[0-9]*)?/[-A-Za-z0-9_\\$\\.\\+\\!\\*\\(\\),;:@&=\\?/~\\#\\%]*[^]'\\.>\\),\\\"]")

def urlify2(value):
    return urlfinder.sub(r'<a href="\1">\1</a>', value)

在字符串上调用 urlify2,如果您不处理 DOM 对象,我认为就是这样。

【讨论】:

那么,什么是不允许的 url? 顺便说一句,如果链接已经在锚标签的 href 属性中怎么办? 当您在文本节点内时,请确保父节点或祖先节点不是锚。 @Amarghosh - 编码器的正则表达式规定了“url”是什么,当然我同意你的观点,很难制作一个兼容所有类型的 url 但即使是最基本的也将支持95% 的网址。 正则表达式应该是:"([0-9]1,3\\.[0-9]1,3\\.[0-9]1,3\\.[0-9]1,3|((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+(:[0-9]*)?/[-A-Za-z0-9_\\$\\.\\+\\!\\*\\(\\),;:@&amp;=\\?/~\\#\\%]*[^]'\\.&gt;\\),\\\"]",这个不能编译。【参考方案5】:

当您说“正文”时,您是指纯文本文件还是 HTML 文档中的正文?如果你想要 HTML 文档,你会想要使用Beautiful Soup 来解析它;然后,搜索正文并插入标签。

匹配实际 URL 可能最好使用 urlparse 模块完成。完整讨论:How do you validate a URL with a regular expression in Python?

【讨论】:

以上是关于用指向 URL 的链接替换文本中的 URL的主要内容,如果未能解决你的问题,请参考以下文章

Java:用可点击的 HTML 链接替换文本 URL

谷歌和雅虎如何替换浏览器状态栏中的 URL?

如何将一列文本 URL 转换为 Excel 中的活动超链接?

将指向外部 URL 的超文本链接点击重新路由到 Electron 应用程序以外的另一个浏览器

正则替换URL地址为链接地址

html 如果URL为“utm_source” - DTR没有值,请修改包含动态文本替换的所有按钮链接