php使用正则表达式验证网址链接

之前折腾了一个短网址程序,过程挺顺利的,唯一就是在验证网址这一步卡了壳,花费了整个过程的一大半时间,最终经过一番搜索、折腾和测试,才算找到一个完美的解决方案。

在短网址程序中,验证网址无疑是很重要的。且不说各种安全问题,就是一些「浑水摸鱼」的网址占据大量的短网址都非常让人头疼。

提到验证网址,我相信大多数人第一时间反应出来的都是正则表达式,的确,这很科学,但何奈自己正则太渣,平时想要匹配一段复杂的 HTML 都要反复调试半天,更何况我连网址的结构都不能完全梳理清楚,所以还是绕过它,咱能不用就别自己找不自在。

esc_url_raw()

想了想,平时的开发中,验证网址都是直接调的 WordPress 核心给的函数,所以考虑直接把 WordPress 的 esc_url_raw() 函数搬过来,省时又省力。

事实证明我实在是太天真了。复制的过程中我发现它牵连了太多其它的模块,一个模块勾搭一点,想要完全搬过来实在是太过庞大,到最后我都分不清楚哪是哪了,你到底跟几个模块有关系啊?照这样搞下去,还不如直接基于 WordPress 算了。

再想想,其实这个函数的本意是「过滤」网址,尽可能的把不合法的网站变成合法的:没有协议?咱给它添上协议;不合法字符?直接干掉它,别脏了眼;浏览器或服务器根本没法解析?我管你那个?

它只是在把网址变得不出现根本错误就没事,别让你这一个小小的网址把我整个程序都给搞乱了就行,虽然在 WordPress 的环境中,大多数情况这样就够了,但在我们的短网址程序中,这显然不够严格。

filter_var()

自己的想法还没能运行一次,就已经胎死腹中了,没办法,只好去求助万能的搜索引擎大人了。找了半天,看着 Stack Overflow 上的各路大神的一个个长篇大论(其实我现在也好像在长篇大论……),最终决定选择大多数人推荐的 filter_var() 函数试试,其实我以前也听说过这个东西,不过一直没什么机会实际使用下,也可以趁现在好好研究研究。

filter_var() 是 PHP 自带的一个函数,顾名思义,用来验证(过滤)变量,印象中应该不止可以验证 URL,什么邮箱之类的也都玩得转。

如果要用它验证网址,只需要这样:

if ( filter_var( $url, FILTER_VALIDATE_URL ) !== false )
 echo '可以,这很网址。'; // 验证成功
else
 echo '这是什么鬼?'; // 验证失败,返回 FALSE。
非常的简单,不过要注意,失败时返回 FALSE 并不意味着你可以直接用 if ( !filter_var( ... ) ) 这样的形式来 草率的判定网址不合法,因为它成功时会返回过滤的内容,而不是 TRUE,如果内容是 '0' 那你怎么办?虽然我们验证网址不可能出现这种情况,但这种习惯还是不要养成的为好,我年轻的时候就曾自作聪明的修改例子代码,在 strpos() 函数上栽跟头喽(其实我现在还经常自作聪明,并且为其付出代价,然后继续自作聪明)。

OK,经过一番测试,感觉上是没什么大问题了,所以把代码交了出去。过一会,别人小小测试一下,发现类似百度和谷歌的搜索结果的网址无法验证通过,又是一波紧急研究。

结论是 filter_var() 会认定所有带有中文的网址不合法,虽然可以通过转义中文部分的方法强行通过验证,但我之前已经为了避免重复所以取消了所有 URL 的转义啊,这想想感觉会弄得好混乱。而且过会又发现,即使是在没有中文的情况下,它对锚点(就是网址中「#」后边的那一堆)链接的支持还有些迷之问题,所以果断抛弃之。

Happy End

好,重头戏来了。

无奈,只好继续去搜索解法,偶然间看到了一个网址,进去之后感觉进入了天堂一样,相见恨晚,里边简直有我现在所急需的一切。

如何正确的使用正则表达式验证网址链接

这个页面的作者搜集了很多不同的正则表达式,并用它们对一系列网址进行测试,有的网址需要验证通过,也有恰恰相反的。

最终,只有一位叫 Diego Perini 的选手通过了比赛,完美的达到了所有要求,他的正则表达式足足有 502 个字符,打眼一瞧非常的吓人,反正我是完全看不懂……

为了方便使用,我把它的正则表达式封装成了一个 PHP 函数,想要使用的话,直接调用就行了:

/**
 * 检测网址是否合法
 *
 * @link https://www.bgbk.org/regex-url/
 * @link https://gist.github.com/dperini/729294
 *
 * @param string $url 需要检测的网址。
 * @return bool 是否为一个合法的网址。
 */
function is_url( $url ) {
 if ( !trim( $url ) )
  return false;

 if ( strlen( $url ) < 10 )
  return false;

 $pattern = '_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS';

 $result = preg_match( $pattern, $url );
 $result = (bool) $result;

 return $result;
}
就像这样:

if ( is_url( $url ) )
 echo '可以,这很网址。'; // 验证成功
else
 echo '这是什么鬼?'; // 验证失败
虽然我对正则表达式理解不多,但它看长度就显然是巨耗费性能的,所以我先对网址进行了一些简单的预判断,希望可以减少服务器的压力。

另外,如果你想了解它的原理,或者想在 JavaScript 中使用这个正则表达式的话,可以参考作者在 GitHub 上的一个页面,里边有原版的 JavaScript 版本,并且附有大量注释,方便你学习和使用!

除此之外,你可以点击下载一份所有测试的 URLs 列表,可以亲自尝试各种正则表达式,或者验证你的方法,如果找到了更好的办法,一定要在评论中分享给大家哦!

附赠资料

最后附赠一个也是偶然发现的页面,里边用非常清晰的方式详细的介绍了网址的构成规则,感兴趣的同学可以点击此处去参观参观。

如何正确的使用正则表达式验证网址链接

在 javaScript 中,用 window.location. 加上演示模型里提到的属性名,就可以获取到当前页面网址的那一部分啦,比如 window.location.protocol,一般就会返回「http:」或「https:」。

当然,上边的网址只是展示了网址基本的构成元素,如果你想了解的更多,比如网址每个部分不能出现的字符啊、需要转义的文本啊,以及各种约定俗称的规则和注意事项,都可以在这里找到,非常完整哦!

URI 是 Web上可用的每种资源 - HTML文档、图像、视频片段、程序等 - 由一个通用资源标志符(Uniform Resource Identifier, 简称"URI")进行定位。 对象分组:

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
12            3  4       

测试代码如下:

<?php
$search = '~^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?~i';
$url = 'http://www.jb51.net/pub/ietf/uri/#Gonn';
$url = trim($url);
preg_match_all($search, $url ,$rr);
printf("<p>输出URL数据为:</p><pre>%s</pre>\n",var_export( $rr ,TRUE));
 
/*
各分组如下
      $1 = http:
      $2 = http
      $3 = //www.111cn.net
      $4 = www.111cn.net
      $5 = /pub/ietf/uri/
      $6 = <undefined>
      $7 = <undefined>
      $8 = #Gonn
      $9 = Gonn
*/
?>

上面的正则表达式可以获取URL中的任何一部分,下面的代码则简单一些:

<?php
// 从 URL 中取得主机名
preg_match("/^(http:\/\/)?([^\/]+)/i", "http://www.jb51.net/index.html", $matches);
$host = $matches[2];
// 从主机名中取得后面两段
preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
echo "domain name is: {$matches[0]}\n";
?>

时间: 2024-11-08 19:52:49

php使用正则表达式验证网址链接的相关文章

三款正则表达式验证网址

(http://)?代表匹配http://0或1次, ([w.]+)匹配www.111cn.net /[w- ./?%&=]*)?匹配后面子串0或1次 ^(http(s)?://)?(www.)?[w-]+.w{2,4}(/)?$   <script type="text/网页特效 "> function isurl(str){ var regurl = /(http://)?([w.]+)(/[w- ./?%&=]*)?/gi; var result =

js正则表达式验证大全(收集)_正则表达式

引用网址  http://hi.baidu.com/quiteuniverse/blog/item/9f3f043d46ad1e07bba16716.html 以下函数调用方式:    function check() { var bb = document.getElementById("txt_id").value;//txt_id为文本框的ID alert(ismobile(bb));//ismobile 代表以下任何一个函数名称 } HTML代码:   <input ty

IOS用正则表达式验证textfield输入的内容是否合法

iphone 4.0以后就开始支持正则表达式的使用了,在ios4.0中正则表达式的使用是使用NSRegularExpression类来调用.   1. 下面一个简单的使用正则表达式的一个例子:NSRegularExpression 类 -(void)parseString{ //组装一个字符串,需要把里面的网址解析出来 NSString *urlString=@"sfdsfhttp://www.baidu.com";   //NSRegularExpression类里面调用表达的方法需

js正则表达式验证URL函数代码(方便多个正则对比)_正则表达式

推荐大家收藏的一段代码,方便同时测试多个正则,查看不同的检测结果,结合chrome完美 核心代码 <script> /** * 正则表达式判断网址是否有效 */ (function(){ "use strict"; var urlDict=[ //Bad Case 'www.baidu.com', //常规网址,未带协议头的地址 'w.baidu.com', //常规网址,短子域名 'baidu.com', //常规网址,仅有主域名 '测试.com', //非常规合法网址,

日常收集整理正则表达式验证大全_正则表达式

常用正则表达式大全!(例如:匹配中文.匹配html) 匹配中文字符的正则表达式: [u4e00-u9fa5] 评注:匹配中文还真是个头疼的事,有了这个表达式就好办了 匹配双字节字符(包括汉字在内):[^x00-xff] 评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1) 匹配空白行的正则表达式:ns*r 评注:可以用来删除空白行 匹配HTML标记的正则表达式:<(S*?)[^>]*>.*?|<.*? /> 评注:网上流传的版本太糟糕,上面这个也仅仅能

Java常用正则表达式验证工具类RegexUtils.java_java

正则表达式常常用来验证各种表单,Java 表单注册常用正则表达式验证工具类,常用正则表达式大集合. 1. 电话号码 2. 邮编 3. QQ 4. E-mail 5. 手机号码 6. URL 7. 是否为数字 8. 是否为中文 9. 身份证 10. 域名 11. IP .... 常用验证应有尽有! 这的确是您从事 web 开发,服务器端表单验证之良品!你,值得拥有 ^_^ /* * Copyright 2012-2013 The Haohui Network Corporation */ pack

NowSnap网址链接预览功能推出

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 NowSnap的网址预览功能今日正式推出!NowSnap网址链接预览服务由网站历史库提供系统支持. NowSnap目前已经公布的预览功能包括:网址链接预览.图片链接预览; NowSnap目前正在测试的预览功能包括:多媒体链接预览.股票信息链接预览.基金信息链接预览等等 网址预览功能是NowSnap为广大站长量身定做的预览服务,本服务运营方期望

锚文本链接与网址链接的区别

  在谈锚文本链接和网址链接区别前,先说一下什么是锚文本链接和网址链接.锚文本链接简单的说就是我们在自己的关键词加上超链接,点击这个关键词,直接进入我们的网站;网址链接就是在别人的网站留下我们的网址.点击这个网址能进入我们的网站;还有一种就是我们留下网址,但是不能点击进入我们的网站.这种网址链接我们不讨论.我们谈论第一种网址链接和锚文本的区别. 在优化上说到锚文本链接和网址链接的区别,不外乎就是说对网站反链和关键词排名的区别.下面简单说下对这两方面的区别: 一. 对反链的区别 我们做seo经常关

网址链接与锚文本链接的主要区别

  在谈锚文本链接和网址链接区别前,先说一下什么是锚文本链接和网址链接.锚文本链接就是给我们自己的关键词加上超链接,点击这个关键词,直接进入我们的网站;网址链接就是在别人的网站留下我们的网址,点击这个网址能进入我们的网站;还有一种就是我们留下网址,但是不能点击进入我们的网站,这种网址链接我们不讨论.下面安利纽崔莱站长给大家分析下锚文本链接与网址链接的区别. 在优化上说到锚文本链接和网址链接的区别,不外乎就是说对网站反链和关键词排名的区别.下面简单说下对这两方面的区别: 一. 对反链的区别 我们做