javascript模仿QQ、微博动态识别网址转换为超链接

JavaScript模仿QQ微博中自动识别网址,将其转换为超链接,以“网页链接”的形式展现,可以点击直接打开。

需求:

项目中在做分享动态时要做一个支持分享网址链接直接点击打开的功能。

方案原型:

将输入的完整网址,在发表动态后,显示时,将原网址链接转换为超链接。

要求:

必须为完整网址,如:

网址不完整不能直接打开,如:

  • baidu.com;
  • yq.aliyun.com/articles/163180?spm=5176.blogshare163180.0.0.0sZT1B

扩展:

展示动态时,自动抓取网址链接网页的标题,抓取到后超链接 显示对应的标题,而不是 “网页链接”,若抓取不到,默认显示 “网页链接”。

边界问题:

识别网址时正确区分网址和非网址链接的文字,根据要求我们必须要求网址以 http:// 或者https:// 开头,但网址结尾部分与文字的区分识别有些难度,主要是以下几点:
1. 中文域名的网址, 如: .中国 .公司 .网络
2. 网址中有中文, 如: http://52debug.net/pub/#g=1&p=推荐-所有成果
3. 网址参数是否正确结束,如:给大家推荐一篇文章,http://52debug.net/pub/#g=1&p=推荐-所有成果 这篇文章真的很精彩!
4. 超长网址的处理,如: https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=monline_4_dg&wd=.%E4%B8%AD%E5%9B%BD&oq=%25E5%258F%2591%25E5%258A%25A8%25E6%2580%2581%25E5%25A6%2582%25E4%25BD%2595%25E5%258C%25BA%25E5%2588%2586%25E7%25BD%2591%25E5%259D%2580%25E5%2592%258C%25E5%2585%25B6%25E4%25BB%2596%25E6%2596%2587%25E5%25AD%2597&rsv_pq=b732ea4400005764&rsv_t=b9c1Jn2RVdEK2W5qgmMmQIrGZA1GCyzAYAHZjZemjrte2U9CwZWdJK1ongeVhpfZHINH&rqlang=cn&rsv_enter=1&inputT=9291&rsv_sug3=110&rsv_sug1=77&rsv_sug7=101&bs=%E5%8F%91%E5%8A%A8%E6%80%81%E5%A6%82%E4%BD%95%E5%8C%BA%E5%88%86%E7%BD%91%E5%9D%80%E5%92%8C%E5%85%B6%E4%BB%96%E6%96%87%E5%AD%97

网址识别分析:

关于网址的识别,按最长串匹配的原则,可以构造一个有穷状态自动机,用于识别网址。
1. 匹配 http://|https:// ,匹配成功执行 2,否则 9
2. 匹配 **.(合法域名后缀),匹配成功执行 3, 否则 9
3. 匹配 请求路径 (/*){0,n},匹配成功执行 4,否则 7
4. 匹配 参数起始标识 ?(&)?,匹配成功执行 5,否则 7
5. 匹配 请求参数 (.)=(.),匹配成功执行 6, 否则 7
6. 匹配 参数分隔符 &,匹配成功执行 5, 否则 7
7. 匹配 网址与非网址部分的文字间隔识别符,可以是 中英文逗号,分号,空格,回车等,匹配成功则 8,否则 9
8. 成功匹配出网址,将其展示为超链接。
9. 识别网址失败,不能识别的网址。

上面这个识别规则是比较严谨些的规则,可以防止http://sfadsfsd 这样类似的假链接。但考虑的可能也并不是很全面,实现起来稍微有些复杂。参考了下QQ对于网址的识别过滤规则,试了下,QQ并没有像上述过程一样去严格识别网址,也没有去支持识别中文域名或者网址参数为中文的情况,而仅仅是识别出http:// 之后,遇到空格回车等空白字符或者中文字符后就取从http:// 到空白或中文的内容作为网址,转换为链接。而项目中确实不用考虑的太复杂,因此本着简单实现的想法,就采用了以下简化的识别规则:
1. 匹配 http://|https:// ,匹配成功执行 2,否则 4
2. 匹配任意ASCII码表中非空白字符, 直到匹配到 空格,回车,换行符,制表符等空白字符或者非ASCII码字符(如中文等),成功则3,否则 4
3. 成功匹配出网址,将其展示为超链接。
4. 识别网址失败,不能识别的网址。

具体实现见代码部分。

关于代码:

新建js文件粘贴该代码。在页面中引入该js,即可通过js调用var newstr = transUrl(str);来获取转换后的内容字符串。


;(function(window, document) {
    var matchUrl = function(str) {
        var Match = function(str, index, lastIndex) {
            this.str = str; //匹配到的url
            this.index = index; //匹配到的字符串在原字符串中的起始位置
            this.lastIndex = lastIndex; //匹配到的字符串在原字符串中的终止位置
        };
        /**
         * 匹配http://|https://
         */
        var regexp1 = new RegExp('(http:\/\/|https:\/\/)', 'g');
        var matchArray = new Array();
        var matchStr;
        while ((matchStr = regexp1.exec(str)) != null) {
            matchArray.push(new Match(matchStr[0], matchStr.index, regexp1.lastIndex));
            /*console.log(match)
            console.log(regexp1.lastIndex - match.index)*/
        }
        /**
         * 匹配网址分隔符,空白字符或非单字节字符及特殊标点符号,;`·"|'做分隔
         */
        var regexp2 = /\s|[^\u0000-\u00FF]|[,;`·"|']/g;
        for (var i = 0; i < matchArray.length; i++) {
            //考虑内容结束但没有分隔符的情况
            var endIndex = matchArray[i + 1] ? matchArray[i + 1].index : str.length;
            var substr = str.substring(matchArray[i].lastIndex, endIndex);
            if ((matchStr = regexp2.exec(substr)) != null) { //匹配到分隔符
                if (regexp2.lastIndex > 1) { //提取网址
                    matchArray[i].lastIndex += regexp2.lastIndex - 1;
                    matchArray[i].str = str.substring(matchArray[i].index, matchArray[i].lastIndex);
                } else { //考虑"http:// "这样的情况
                    matchArray.splice(i, 1);
                }
            } else if (endIndex == str.length) { //考虑内容末尾无空白符的情况
                if (matchArray[i].lastIndex < endIndex) { //提取网址
                    matchArray[i].lastIndex = endIndex;
                    matchArray[i].str = str.substring(matchArray[i].index, endIndex);
                } else { //考虑内容末尾无空白符,但也没有实际网址的情况,如:"http://"
                    matchArray.splice(i, 1);
                }
            } //考虑内容并未到结尾,无空白符的情况,如:http://baidu.comhttp://sina.com,这种情况识别为一个网址
            else if (matchArray[i + 1] && (endIndex == matchArray[i + 1].index)) {
                matchArray.splice(i + 1, 1);
                i = i - 1;
            } else { //其他情况
                matchArray.splice(i, 1);
            }
            //console.log(matchStr);
            regexp2.lastIndex = 0;
        }
        return matchArray;
    }
    var transUrl = function(str) {
        var matchArray = matchUrl(str);
        var newstr = "";
        for(var i=0; i <= matchArray.length; i++){
            var beginIndex = i==0 ? 0 : matchArray[i-1].lastIndex;
            var endIndex = i == matchArray.length ? str.length : matchArray[i].index;
            var stri = str.substring(beginIndex, endIndex);
            var urli = "";
            if(i < matchArray.length){
                urli = " <a href=\"" + matchArray[i].str + "\" style=\"color: #005eac !important;\" target=\"_blank\">网页链接</a> ";
            }
            newstr += stri + urli;
        }
        //console.log(newstr)
        return newstr;
    }
    window.transUrl = transUrl;
}(window, document));
时间: 2024-09-01 06:51:19

javascript模仿QQ、微博动态识别网址转换为超链接的相关文章

php中将网址转换为超链接的函数_php技巧

复制代码 代码如下: function showtext($text){ $search = array('|(http://[^ ]+)|', '|(https://[^ ]+)|', '|(www.[^ ]+)|'); $replace = array('<a href="$1" target="_blank">$1</a>', '<a href="$1" target="_blank">

ole剪贴板-【模仿QQ发送消息问题,richedit控件内图片内容识别问题】

问题描述 [模仿QQ发送消息问题,richedit控件内图片内容识别问题] 发送框使用richedit控件,为了支持复制粘贴混合格式(图片+文字)实现了ole剪贴板的callback接口.但没有自己实现copy和paste方法.使用的是控件的默认拷贝粘贴方法. 现在可以正常拷贝各种格式粘贴到richedit控件内. 但要发送控件内的内容时产生了问题,我获取到richedit里面的ole对象后,无法识别ole对象类型(通常是位图,但使用位图格式获取对象的数据却失败),只能发送文字. 有没有办法将获

php-如何模仿QQ在聊天主界面外显示鼠标移到微博页中某个网名时所显示的个人资料对话框?

问题描述 如何模仿QQ在聊天主界面外显示鼠标移到微博页中某个网名时所显示的个人资料对话框? 我在QQ聊天工具中打开微博页面,将鼠标移到某个好友的头像上,就会在聊天主窗口外,显示一个个人资料对话框,而不是在网页中显示.请问这种的实现思路是怎样的?用C#写的聊天工具,和php做的网站能做到这样吗? 解决方案 应该是可以的,用鼠标移到某个好友头像上时,触发事件取得好友的ID,然后用弹出式窗口来显示这个人的资料对话框即可

JS自定义功能函数实现动态添加网址参数修改网址参数值

本文自定义JS功能函数可动态添加网址参数,修改网址参数值,具体实现如下,感兴趣的朋友可以参考下,希望对大家有所帮助   无论是前端开发还是后台设计,很多时候开发人员都需要获取当前或目标网址的相关信息.这个已有现成的内置对象属性可以直接调用了(下面是获取当前页面的参考代码) 复制代码 代码如下: <script type="text/javascript"> thisURL = document.URL; thisHREF = document.location.href;

分享到新浪与QQ微博代码

分享到新浪与QQ微博代码 新浪 <script type="text/网页特效" charset="utf-8"> (function(){   var _w = 16 , _h = 16;   var param = {     url:location.href,     type:'3',     count:'', /**是否显示分享数,1显示(可选)*/     appkey:'1929229597', /**您申请的应用appkey,显示分享

WPS演示模仿QQ相册图片翻页怎么使用

  WPS演示模仿QQ相册图片翻页怎么使用 1.准备好相片,要求图片的宽高保持相同,高度宽度记录下来,这样播放时不会因为相片大小不一而显得不美观. 2.运行WPS演示,单击菜单栏--文件--页面设置,将页面的宽高设置得与图片相同.将第一张幻灯片所有内容全部删除,得到空白的幻灯片. 3.在幻灯片预览窗格中进行复制粘贴操作,得到多张幻灯片. 4.在每张幻灯片中插入相片,右击图片,选择设置对象格式,从弹出的对话框中将图片的水平和垂直位置都设置为0.这样,图片将恰好充满整个幻灯片页面. 5.在第一张幻灯

新浪微博如何删除个人微博动态?

  进入微博个人主页,找到想要删除的动态,将鼠标光标移至单条动态上,右下角显示"删除"字样,点击并确定即可. 友情提示:只能删除自己的微博动态,无法删除他人的微博动态,如果不想显示动态,您可选择设置动态权限.

动态磁盘无损转换为基本磁盘教程

  在Win7系统上或许我们可以很轻松地将一个基本磁盘转换成动态磁盘,但将动态磁盘转换成基本磁盘却不是一件容易的事.我们用Windows的磁盘管理器只能转换一个空的动态磁盘返回基本.如果一个动态磁盘上有分区或动态卷存在,则"转换到基本磁盘"选项是灰色的禁用状态,即无法转换. 在下面的情况下需要将转换动态磁盘或动态硬盘到基本硬盘: 一.Vista/Windows7/Win2008的系统安装程序不允许在动态磁盘上安装Windows系统.换句话说,在动态磁盘是无法安装Windows 7/Vi

android-安卓仿QQ好友动态是的head是如何实现的

问题描述 安卓仿QQ好友动态是的head是如何实现的 或者新浪微博个人主页是如何实现的如图 求demo 解决方案 这个界面应该没啥难度吧,你把你觉得没法理解或者困难的地方说下 解决方案二: 标题那里背景色 设置为 透明 然后 图片和标题用 framelayout 就好了 解决方案三: true? //让actionbar悬浮于布局上 //让actionbar透明,色值你可以改一下 <item name=""android:background"">#33