用指向 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_\\$\\.\\+\\!\\*\\(\\),;:@&=\\?/~\\#\\%]*[^]'\\.>\\),\\\"]"
,这个不能编译。【参考方案5】:
当您说“正文”时,您是指纯文本文件还是 HTML 文档中的正文?如果你想要 HTML 文档,你会想要使用Beautiful Soup 来解析它;然后,搜索正文并插入标签。
匹配实际 URL 可能最好使用 urlparse 模块完成。完整讨论:How do you validate a URL with a regular expression in Python?
【讨论】:
以上是关于用指向 URL 的链接替换文本中的 URL的主要内容,如果未能解决你的问题,请参考以下文章
如何将一列文本 URL 转换为 Excel 中的活动超链接?