从字符串中提取 URL

Posted

技术标签:

【中文标题】从字符串中提取 URL【英文标题】:Extract URL from string 【发布时间】:2011-05-22 09:24:03 【问题描述】:

我正在尝试找到一种可靠的解决方案来从字符串中提取 url。我有一个网站,用户可以在其中回答问题,并在来源框中输入他们的信息来源,我允许他们输入网址。我想提取该网址并使其成为超链接。类似于 Yahoo Answers 的做法。

有谁知道可以做到这一点的可靠解决方案吗?

我发现的所有解决方案都适用于某些 URL,但不适用于其他 URL。

谢谢

【问题讨论】:

【参考方案1】:

John Gruber 拥有spent a fair amount of time 完善了“一个正则表达式来统治所有这些”以进行链接检测。使用preg_replace() 如其他答案中所述,使用以下正则表达式应该是检测链接的最准确(如果不是最准确)方法之一:

(?i)\b((?:[a-z][\w-]+:(?:/1,3|[a-z0-9%])|www\d0,3[.]|[a-z0-9.\-]+[.][a-z]2,4/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\];:'".,<>?«»“”‘’]))

如果你只想匹配 HTTP/HTTPS:

(?i)\b((?:https?://|www\d0,3[.]|[a-z0-9.\-]+[.][a-z]2,4/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\];:'".,<>?«»“”‘’]))

【讨论】:

正是我想要的!谢谢。 对于任何希望将所有子模式转换为非捕获并且正斜杠转义的人:\b(?:(?:[az][\w-]+:(?: \/1,3|[a-z0-9%])|www\d0,3[.]|[a-z0-9.\-]+[.][az]2, 4\/)(?:[^\s()]+|((?:[^\s()]+|(?:([^\s()]+)) )*))+(?:((?:[^\s()]+|(?:([^\s()]+)))*)|[^\s`!( )[];:'".,?«»“”''])) TLD 可能有超过 4 个字符,请参阅:iana.org/domains/root/db 我们如何在 preg 中使用这个正则表达式?我的意思是,因为它有 "' 代码不能正常工作,比如:preg_match('(?i)\b......]))', $str) - 所有代码似乎都被注释了。 不工作。 Preg_match 和 preg_match_all 每次都失败,即使在删除单引号/双引号后也是如此【参考方案2】:
$string = preg_replace('/https?:\/\/[^\s"<>]+/', '<a href="$0" target="_blank">$0</a>', $string);

它只匹配 http/https,但这确实是您想要转换为链接的唯一协议。如果你想要其他人,你可以这样改变它:

$string = preg_replace('/(https?|ssh|ftp):\/\/[^\s"]+/', '<a href="$0" target="_blank">$0</a>', $string);

【讨论】:

您可能还想排除 &lt; 或在匹配的字符串上应用 htmlspecialchars 以避免代码注入。 很好,但是如果您查看表达式,它允许除空格和" 之外的任何内容。我相信这消除了任何 HTML 注入。 Bron:不,您使用的匹配值不仅作为属性值,还作为元素文本内容。【参考方案3】:

url 有很多边缘情况。像 url 可以包含括号或不包含协议等。这就是为什么正则表达式是不够的。

我创建了一个可以处理大量边缘情况的 php 库:Url highlight。

您可以从字符串中提取网址或直接突出显示它们。 示例:

<?php

use VStelmakh\UrlHighlight\UrlHighlight;

$urlHighlight = new UrlHighlight();

// Extract urls
$urlHighlight->getUrls("This is example http://example.com.");
// return: ['http://example.com']

// Make urls as hyperlinks
$urlHighlight->highlightUrls('Hello, http://example.com.');
// return: 'Hello, <a href="http://example.com">http://example.com</a>.'

更多详情请见readme。对于覆盖的 url 案例,请参阅test。

【讨论】:

【参考方案4】:

雅虎!当链接写得正确并与其他文本分开时,Answers 可以很好地识别链接,但它不能很好地分离尾随标点符号。例如The links are @987654321@, @987654322@, and @987654323@. 将在前两个中包含逗号,在第三个中包含句点。

但如果这是可以接受的,那么像这样的模式应该这样做:

\<http:[^ ]+\>

看起来***的解析器更好。是开源的吗?

【讨论】:

更聪明,但仍不完美。错过了 ssh+svn 之类的东西。【参考方案5】:

这段代码对我有用。

function makeLink($string)

/*** make sure there is an http:// on all URLs ***/
$string = preg_replace("/([^\w\/])(www\.[a-z0-9\-]+\.[a-z0-9\-]+)/i", "$1http://$2",$string);
/*** make all URLs links ***/
$string = preg_replace("/([\w]+:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/i","<a target=\"_blank\" href=\"$1\">$1</a>",$string);
/*** make all emails hot links ***/
$string = preg_replace("/([\w-?&;#~=\.\/]+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]2,3|[0-9]1,3)(\]?))/i","<a href=\"mailto:$1\">$1</a>",$string);

return $string;

【讨论】:

为什么将 tld 限制为 3 个字符?看看:iana.org/domains/root/db

以上是关于从字符串中提取 URL的主要内容,如果未能解决你的问题,请参考以下文章

java 从一个URL中提取特定子字符串保存

从 url 'path' 中提取的 input_url 解析字符串 'name'

从给定的字符串中提取 url [重复]

从 url 查询字符串参数中提取单独的值

从 Bigquery 中的 URL 中提取字符串

如何使用正则表达式从字符串中提取第 n 个 URL?