用户代理检测与浏览器Ua详细分析
前言:用户代理字符串与用户代理检测
“用户代理字符串”(User Agent,下文简称“Ua”)是浏览器用来标识自身信息的一串字符
现如今,Ua一般包含有浏览器品牌、版本、内核、所在操作系统环境等信息
它也有着“悠久”而混乱的历史
若您对这段“黑历史”感兴趣
推荐阅读Hejin.Wong《用户代理字符串简史》一文,本文不再赘述
而“用户代理检测”则是通过检测Ua来确定实际使用的浏览器及其内核等信息
本文将从浏览器内核和浏览器本身的角度出发
通过亲测用户代理字符串,梳理各主流浏览器(本文仅限桌面端)内核、版本等信息
以及分享通过JavaScript进行用户代理检测的方法
注:本文代码基于[美]Nicholas C.Zakas《JavaScript高级程序设计(第3版)》,并已根据现实情况进行优化
先看结论/可用代码
通过在JavaScript中引用以下代码
即可在需要的时候方便的测出用户所用浏览器的用户代理字符串、浏览器品牌、版本、内核等信息
var client=function(){ var engine={ //呈现引擎 trident:0, gecko:0, webkit:0, khtml:0, presto:0, ver:null //具体的版本号 }; var browser={ //浏览器 ie:0, firefox:0, safari:0, konq:0, opera:0, chrome:0, ver:null //具体的版本号 }; var system={ //操作系统 win:false, mac:false, x11:false }; var ua=navigator.userAgent; if(/AppleWebKit\/(\S+)/.test(ua)){ //匹配Webkit内核浏览器(Chrome、Safari、新Opera) engine.ver=RegExp["$1"]; engine.webkit=parseFloat(engine.ver); if(/OPR\/(\S+)/.test(ua)){ //确定是不是引用了Webkit内核的Opera browser.ver=RegExp["$1"]; browser.opera=parseFloat(browser.ver); }else if(/Chrome\/(\S+)/.test(ua)){ //确定是不是Chrome browser.ver=RegExp["$1"]; browser.chrome=parseFloat(browser.ver); }else if(/Version\/(\S+)/.test(ua)){ //确定是不是高版本(3+)的Safari browser.ver=RegExp["$1"]; browser.safari=parseFloat(browser.ver); }else{ //近似地确定低版本Safafi版本号 var SafariVersion=1; if(engine.webkit<100){ SafariVersion=1; }else if(engine.webkit<312){ SafariVersion=1.2; }else if(engine.webkit<412){ SafariVersion=1.3; }else{ SafariVersion=2; } browser.safari=browser.ver=SafariVersion; } }else if(window.opera){ //只匹配拥有Presto内核的老版本Opera 5+(12.15-) engine.ver=browser.ver=window.opera.version(); engine.presto=browser.opera=parseFloat(engine.ver); }else if(/Opera[\/\s](\S+)/.test(ua)){ //匹配不支持window.opera的Opera 5-或伪装的Opera engine.ver=browser.ver=RegExp["$1"]; engine.presto=browser.opera=parseFloat(engine.ver); }else if(/KHTML\/(\S+)/.test(ua)||/Konqueror\/([^;]+)/.test(ua)){ engine.ver=browser.ver=RegExp["$1"]; engine.khtml=browser.konq=parseFloat(engine.ver); }else if(/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)){ //判断是不是基于Gecko内核 engine.ver=RegExp["$1"]; engine.gecko=parseFloat(engine.ver); if(/Firefox\/(\S+)/.test(ua)){ //确定是不是Firefox browser.ver=RegExp["$1"]; browser.firefox=parseFloat(browser.ver); } }else if(/Trident\/([\d\.]+)/.test(ua)){ //确定是否是Trident内核的浏览器(IE8+) engine.ver=RegExp["$1"]; engine.trident=parseFloat(engine.ver); if(/rv\:([\d\.]+)/.test(ua)||/MSIE ([^;]+)/.test(ua)){ //匹配IE8-11+ browser.ver=RegExp["$1"]; browser.ie=parseFloat(browser.ver); } }else if(/MSIE ([^;]+)/.test(ua)){ //匹配IE6、IE7 browser.ver=RegExp["$1"]; browser.ie=parseFloat(browser.ver); engine.ver=browser.ie-4.0; //模拟IE6、IE7中的Trident值 engine.trident=parseFloat(engine.ver); } var p=navigator.platform; //判断操作系统 system.win=p.indexOf("Win")==0; system.mac=p.indexOf("Mac")==0; system.x11=(p.indexOf("X11")==0)||(p.indexOf("Linux")==0); if(system.win){ if(/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)){ if(RegExp["$1"]=="NT"){ system.win = ({ "5.0" : "2000", "5.1" : "XP", "6.0" : "Vista", "6.1" : "7", "6.2" : "8", "6.3" : "8.1", "10" : "10" })[RegExp["$2"]] || "NT"; }else if(RegExp["$1"]=="9x"){ system.win="ME"; }else{ system.win=RegExp["$1"]; } } } return { ua:ua, //用户浏览器Ua原文 engine:engine, //包含着用户浏览器引擎(内核)信息 browser:browser,//包括用户浏览器品牌与版本信息 system:system //用户所用操作系统及版本信息 }; }();
[2015/01/16注:以上代码测试并吸收了本文评论中@luobotang的建议,感谢反馈]
以上代码封装了一个命名为client的函数对象
实际开发中,引用了上述代码后,可以如下面示例代码所示,灵活运用client对象中的信息
if(client.engine.webkit){ //如果是基于Webkit内核的浏览器 if(client.browser.chrome){ //若是Google Chrome浏览器 //执行针对Chrome的代码 } else if {client.browser.safari}{ //执行针对Safari的代码 } } else if (client.engine.gecko){ //若是基于Cecko内核的浏览器 if(client.browser.firefox){ //执行针对Firefox的代码 } else { //执行针对其他基于Gecko内核的浏览器的代码 } }
下文将会使用以下代码alert出Ua等信息作为测试参考并提供截图(点击截图可放大查看)
若您需要亲测任何浏览器的信息,可将以下代码粘贴于上文第一段代码(client对象)后并在浏览器中运行
alert(client.ua); var browserName=""; //保存当前使用的浏览器品牌信息 var browserVer=0; //保存当前使用的浏览器版本信息 for(var i in client.browser){ if(client.browser[i]){ browserName=i; browserVer=client.browser[i]; break; } } var useEngine=""; //保存当前浏览器引擎(内核)名称 var engineVer=0; //保存当前使用的浏览器引擎版本 for(var i in client.engine){ if(client.engine[i]){ useEngine=i; engineVer=client.engine[i]; break; } } var useSystem=""; //保存当前操作系统信息 for(var i in client.system){ if(client.system[i]){ i== "win"?useSystem = "Windows "+client.system[i]:useSystem=i; break; } } alert( "当前使用的浏览器:"+browserName + "\n浏览器版本:"+browserVer + "\n浏览器内核:"+useEngine + "\n内核版本:"+engineVer + "\n当前操作系统:"+useSystem);
浏览器市场份额现状
首先通过数据了解一下目前浏览器市场份额现状
根据“百度统计|流量研究院”的数据
下图/表是2014年全年国内浏览器市场份额情况
![](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_browserZh.png)
浏览器名称 | 市场份额 |
---|---|
.Internet Explorer | 50.03% |
.Google Chrome | 27.73% |
.搜狗高速浏览器 | 4.77% |
.猎豹浏览器 | 2.46% |
.QQ浏览器 | 2.19% |
.2345浏览器 | 1.67% |
.其它 | 11.15% |
由此可以看出,在国内,IE浏览器占据了“大半江山”
紧随其后的是Google Chrome浏览器
排在第3、4、5、6位的均是国产壳浏览器
再看一下2014年11月全球浏览器市场份额情况(数据来自“浏览迷”)
浏览器名称 | 市场份额 |
---|---|
.Internet Explorer | 58.94% |
.Google Chrome | 20.57% |
.Firefox | 13.26% |
.Safari | 5.9% |
.Opera | 0.88% |
.其它 | 0.45% |
![](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_browserWd.png)
从全世界的范围上看,IE浏览器的市场份额更加可观,达到近6成
这些数据对于分析浏览器内核、生产兼容性强的前端项目具有重要的参考意义
Mozilla Firefox
Mozilla Firefox(火狐)是我个人最为崇敬的浏览器品牌
相比较而言,火狐浏览器性能优越、坚持标准、勇于尝试(......好了,真心的,这可不是植入广告)
它更拥有独立的呈现引擎(内核)Gecko /ˈgekəʊ/
以下是我亲测整理的火狐浏览器各主要版本Ua及通过Ua解析出的信息(点击缩略图可放大查看)
![firefox1Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_fireFox1Ua_s.jpg)
![firefox1](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_fireFox1_s.jpg)
Mozilla/5.0 (Windows: U; Windows NT 5.1; zh-CN; rv:1.7.5) Gecko/20041124 Firefox/1.0
![firefox3.6Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_fireFox3.6Ua_s.jpg)
![firefox3.6](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_fireFox3.6_s.jpg)
Mozilla/5.0 (Windows: U; Windows NT 6.0; zh-CN; rv:1.9.2.18) Gecko/20110614 Firefox/3.6.18
![firefox8Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_fireFox8Ua_s.jpg)
![firefox8](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_fireFox8_s.jpg)
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0.1) Gecko/20100101 Firefox/8.0.1
![firefox36Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_fireFox36Ua_s.jpg)
![firefox36](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_fireFox36_s.jpg)
Mozilla/5.0 (Windows NT 6.3; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
通过如上亲测和书本介绍可知,火狐浏览器的Ua具有如下特征
- 相对稳定,从第一个版本至今变化不大;
- 有正确标识版本、内核、所在操作系统等基本信息;
- 一直是以“Mozilla 5.0”开头,今后估计也不会变化;
- 从Firefox 4后,“Gecko版本号”固定为“Gecko/20100101”,基本失去作用;
- 末尾“Firefox/”后内容为浏览器真实版本号;
- “rv:”后内容为Gecko内核版本号;
- 高版本的Firefox浏览器“Gecko”内核版本号与浏览器版本号相同。
从用户代理检测的难度上说,得益于火狐浏览器一直坚持规矩
分析起来是最简单的
运用如下JavaScript代码,配合正则表达式
即可轻松的将火狐浏览器的相关信息赋给相应对象
/*以下代码作用为判断与分析火狐浏览器Ua信息*/ //... else if(/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)){ //判断是不是基于Gecko内核 engine.ver=RegExp["$1"]; engine.gecko=parseFloat(engine.ver); if(/Firefox\/(\S+)/.test(ua)){ //确定是不是Firefox browser.ver=RegExp["$1"]; browser.firefox=parseFloat(browser.ver); } } //...
具体代码本文第二部分“先看结论/可用代码”已详细给出,下同
Microsoft Internet Explorer
大名鼎鼎的IE浏览器可能也是一众前端程序员的噩梦
虽然它版本迭代缓慢、Bug频出、还有各种“怪癖”特性
但它倚仗Windows操作系统的垄断地位,无论全球还是国内,从市场占有率上看一直是老大
IE浏览器也有自己的内核Trident /ˈtraɪdnt/
同样根据“百度统计|流量研究院”的数据,看一下2014年国内浏览器按版本区分的市场份额占比情况
![](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_browserIE.png)
浏览器版本 | 市场份额 |
---|---|
.IE8 | 32.04% |
.Google Chrome | 27.73% |
.IE6 | 7.37% |
.IE9 | 7.14% |
.搜狗高速浏览器 | 4.77% |
.IE7 | 3.48% |
.猎豹浏览器 | 2.46% |
.QQ浏览器 | 2.19% |
.2345浏览器 | 1.67% |
.其它 | 11.15% |
什么?IE10、IE11居然还没排上号?
从数据上看,确实如此,老版本的IE(6/7/8/9)寿命是相当的长
这迫使前端开发必须考虑旧版本IE浏览器并为它的各个版本逐一DeBug和适配
下面通过亲测,比较一下各版本IE浏览器Ua的差异
![IE6Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE6Ua_s.jpg)
![IE6](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE6_s.jpg)
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
![IE7Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE7Ua_s.jpg)
![IE7](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE7_s.jpg)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1)
![IE8Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE8Ua_s.jpg)
![IE8](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE8_s.jpg)
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
![IE9Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE9Ua_s.jpg)
![IE9](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE9_s.jpg)
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; WOW64; Trident/5.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.30729)
![IE10Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE10Ua_s.jpg)
![IE10](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE10_s.jpg)
Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
![IE11Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE11Ua_s.jpg)
![IE11](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE11_s.jpg)
Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko
虽然稍显凌乱,但观察一下就能发现,IE6-10均有通过“MSIE”字段正确标识出当前IE版本
但IE11(和接下来可能的IE12、13...)的Ua简直乱入啊
目的很明显,IE11试图将自己伪装成Gecko内核的浏览器(比如火狐),欺骗嗅探代码
这继续刷新着Ua本来就混乱的历史,真是惹人嫌......
通过如上亲测和书本介绍可知,IE浏览器的Ua具有如下特征
- IE6-10通过“MSIE”字段正确地标识自身版本信息;
- IE11通过“rv”字段标识自身版本信息;
- IE8及之后的版本添加了呈现引擎(Trident)的版本号,且Trident版本号都是IE版本号减4;
- 有正确标识所在操作系统信息;
- IE11含有迷惑性字段“like Gecko”。
新增的Trident记号是为了让开发人员知道IE是不是在兼容模式下运行
如下例所示,若是运行在兼容模式下的IE8,则“MSIE”版本号会变成7,但Trident及其版本号还会留在Ua中
![IE8dUa](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE8dUa_s.jpg)
![IE8d](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_IE8d_s.jpg)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0)
综上比较,可以通过如下代码进行针对IE的用户代理检测
/*以下代码作用为判断与分析IE浏览器Ua信息*/ //... else if(/Trident\/([\d\.]+)/.test(ua)){ //确定是否是Trident内核的浏览器(IE8+) engine.ver=RegExp["$1"]; engine.trident=parseFloat(engine.ver); if(/rv\:([\d\.]+)/.test(ua)||/MSIE ([^;]+)/.test(ua)){ //匹配IE8-11+ browser.ver=RegExp["$1"]; browser.ie=parseFloat(browser.ver); } }else if(/MSIE ([^;]+)/.test(ua)){ //匹配IE6、IE7 browser.ver=RegExp["$1"]; browser.ie=parseFloat(browser.ver); engine.ver=browser.ie-4.0; //模拟IE6、IE7中的Trident值 engine.trident=parseFloat(engine.ver); } //...
值得注意的是,以上代码会根据“Trident内核版本号=IE版本号-4”的规律
将IE6的“Trident”内核版本标记为“2.0”,将IE7的“Trident”内核版本标记为“3.0”,以此统一“Trident”标记
Google Chrome
从市场份额上看,无论是世界范围内还是国内,PC端Google Chrome都是仅次于IE的浏览器
不过这可能也与大多数国产套壳浏览器均使用Chrome的WebKit内核有关
先看一下Google Chrome各主要版本Ua情况
![chrome1Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_chrome1Ua_s.jpg)
![chrome1](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_chrome1_s.jpg)
Mozilla/5.0 (Windows: U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.48 Safari/525.19
![chrome10Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_chrome10Ua_s.jpg)
![chrome10](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_chrome10_s.jpg)
Mozilla/5.0 (Windows: U; Windows NT 6.0; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.205 Safari/534.16
![chrome27Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_chrome27Ua_s.jpg)
![chrome27](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_chrome27_s.jpg)
Mozilla/5.0 (Windows: U; Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36
![chrome39Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_chrome39Ua_s.jpg)
![chrome39](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_chrome39_s.jpg)
Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
通过如上亲测和书本介绍可知,Chrome浏览器的Ua具有如下特征
- 使用“AppleWebKit”字段正确标识所用内核为“WebKit”及其版本号;
- “Chrome/”及其后数值正确标识了浏览器品牌及版本信息;
- 一直是以“Mozilla 5.0”开头,今后估计也不会变化;
- 有正确标识所在操作系统信息;
- 均含有迷惑性字段“(KHTML, like Gecko)”;
- 末尾“Safari/”字段视图将自己伪装成Safari,WebKit版本与Safari版本看起来似乎始终保持一致。
Chrome使用的呈现引擎(内核)是WebKit
但是,在Chrome 28之后,谷歌宣布将使用Blink引擎
不过Blink引擎也是基于WebKit的,关于更改引擎的变化,截至目前仍然没有在Ua中表现出来
综上,可以使用如下JavaScript代码配合正则表达式进行针对Chrome浏览器的用户代理检测
/*以下代码作用为判断与分析Chrome浏览器Ua信息*/ if(/AppleWebKit\/(\S+)/.test(ua)){ //匹配Webkit内核浏览器(Chrome、Safari、新Opera) engine.ver=RegExp["$1"]; engine.webkit=parseFloat(engine.ver); if(/OPR\/(\S+)/.test(ua)){ //确定是不是引用了Webkit内核的Opera //... }else if(/Chrome\/(\S+)/.test(ua)){ //确定是不是Chrome browser.ver=RegExp["$1"]; browser.chrome=parseFloat(browser.ver); }else if(/Version\/(\S+)/.test(ua)){ //确定是不是高版本(3+)的Safari //... } //...
Apple Safari
苹果Safari浏览器作为Mac OS系统的官方浏览器,自然也有可观的用户数
该浏览器也是基于WebKit内核
因为楼主还是大学生一枚,暂时买不起MacBook,安装黑苹果的过程又让我累觉不爱......
所以关于Safari的Ua没能测试得如其它浏览器般详细
根据书本介绍,Safari 3.0之前的Ua类似如下所示
Mozilla/5.0 (Macintosh; U; PPC Mac OS X;en) AppleWebKit/124 (KHTML, like Gecko) Safari/125.1
用了自己的电脑安装了个Safari for Windows,借了同学一个MacBook做了如下亲测
![safari5.1Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_safari5.1Ua_s.jpg)
![safari5.1](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_safari5.1_s.jpg)
Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/534.57.2 (KHTML,like Gecko) Version/5.1.7 Safari/534.57.2
![safari6Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_safari6Ua_s.jpg)
![safari6](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_safari6_s.jpg)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/536.30.1 (KHTML, like Gecko) Version/6.0.5 Safari/536.30.1
根据书本介绍和如上亲测,Safari浏览器的Ua具有如下特征
- 使用“AppleWebKit”字段正确标识所用内核为“WebKit”及其版本号;
- “Safari”标识了浏览器品牌信息;
(并不像Chrome浏览器一样即包含“Chrome”字段又包含迷惑性“Safari”字段) - Safari 3.0以上版本通过“Version字段正确标识浏览器版本信息(这只在Safari中存在);
- 一直是以“Mozilla 5.0”开头,今后估计也不会变化;
- 有正确标识所在操作系统信息;
- 均含有迷惑性字段“(KHTML, like Gecko)”;
综上,使用如下代码配合正则表达式可以进行针对Safari浏览器的用户代理检测
/*以下代码作用为判断与分析Safari浏览器Ua信息*/ if(/AppleWebKit\/(\S+)/.test(ua)){ //匹配Webkit内核浏览器(Chrome、Safari、新Opera) engine.ver=RegExp["$1"]; engine.webkit=parseFloat(engine.ver); //... }else if(/Version\/(\S+)/.test(ua)){ //确定是不是高版本(3+)的Safari browser.ver=RegExp["$1"]; browser.safari=parseFloat(browser.ver); }else{ //近似地确定低版本Safafi版本号 var SafariVersion=1; if(engine.webkit<100){ SafariVersion=1; }else if(engine.webkit<312){ SafariVersion=1.2; }else if(engine.webkit<412){ SafariVersion=1.3; }else{ SafariVersion=2; } browser.safari=browser.ver=SafariVersion; } //...
其中,因为低版本Safari 2-不包含标识浏览器版本号的“version”属性(不过如今低版本Safari用户数应该极少了)
故只能使用一些if语句做近似判断
Opera
Opera(欧朋)浏览器也算得上是浏览器界的一朵奇葩了
在Opera 12.16之前,它有着自己的内核Presto /'prestəʊ/
而之后,Opera改用Google Chrome的Blink内核(同样基于WebKit)
几近沦为一款套壳浏览器
虽然根据上文数据,Opera浏览器在国内的市场份额几乎可以忽略不计(被归入了“其它”范畴)
但据说其在欧洲市场还是有相当的人气,而且有着不同寻常的过去(自有内核)
所以本文还是将Opera单独分析
![opera9.6Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_opera9.6Ua_s.jpg)
![opera9.6](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_opera9.6_s.jpg)
Opera/9.64 (Windows NT 6.0; U; Edition IBIS; zh-cn) Presto/2.1.1
![opera12Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_opera12Ua_s.jpg)
![opera12](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_opera12_s.jpg)
Opera/9.80 (Windows NT 6.1; Win64; x64) Presto/2.12.388 Version/12.15
![opera26Ua](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_opera26Ua_s.jpg)
![opera26](https://images.cnblogs.com/cnblogs_com/hykun/607566/o_opera26_s.jpg)
Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60
从以上测试和书本介绍可以知道,在Opera 9之前,其默认的用户代理字符串是所有现代浏览器中最合理的
没有任何伪装,且正确地标识了自身及其版本号
可是,因为因特网上不少浏览器嗅探代码只钟情于报告Mozilla产品名的那些Ua或只对IE和Gecko感兴趣
Opera没有伪装的Ua可能令某些站点的兼容性出现问题
于是,Opera就开始变奇葩了......
Opera 9以后,出现了两种修改用户代理字符串的方式
第一种方式是,针对某些站点,将自身表示为另外一个浏览器,只不过在末尾追加Opera品牌和版本信息,如下为例
Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50
第二种方式是,针对某些站点,直接隐瞒身份,Ua与其它浏览器返回的相同
注意,这些奇葩行为都是针对某些站点的,这令用户代理检测识别Opera难上加难
不过,通过以上亲测,还是可以总结出正常情况下Opera的Ua的一些特点
- Opera 9.8之前,Ua开头的“Opera/”字段正确标识出了浏览器品牌和版本信息;
- Opera 9.8-12.15中,Ua开头固定为“Opera/9.8,但有通过“Version”字段正确标识版本信息;
- Opera 12.15之前,一直有通过Presto字段正确地标识Presto内核及其版本信息;
- Opera 12.16后,因为使用了Blink(WebKit)内核,
出现“AppleWebKit”字段正确标识内核及内核版本信息,
同时出现“Chrome”、“Safari”、“(KHTML, like Gecko)”伪装字段; - 使用了Blink(Webkit)内核后,Ua末尾通过“OPR”字段标识浏览器品牌及版本信息;
- 一直有正确标识所在操作系统信息。
此外,Opera 5+独家支持通过window.opera探测浏览器版本等信息
尽管无法通过用户代理检测获得隐瞒身份状态下的Opera信息
但还是可以根据以上规律,使用以下代码检测正常情况下Opera的Ua信息
/*以下代码作用为判断与分析Opera浏览器Ua信息*/ if(/AppleWebKit\/(\S+)/.test(ua)){ //匹配Webkit内核浏览器(Chrome、Safari、新Opera) engine.ver=RegExp["$1"]; engine.webkit=parseFloat(engine.ver); //... }else if(window.opera){ //只匹配拥有Presto内核的老版本Opera 5+(12.15-) engine.ver=browser.ver=window.opera.version(); engine.presto=browser.opera=parseFloat(engine.ver); }else if(/Opera[\/\s](\S+)/.test(ua)){ //匹配不支持window.opera的Opera 5-或伪装的Opera engine.ver=browser.ver=RegExp["$1"]; engine.presto=browser.opera=parseFloat(engine.ver); } //...
呈现引擎(浏览器内核)
上文从浏览器的角度出发,分析了几大世界知名浏览器的Ua
下面就从浏览器内核的角度,做一个简单地整理
内核 | 浏览器 |
---|---|
Webkit | Google Chrome (Blink) |
Apple Safari | |
Opera 12.16+ (Blink) | |
Trident | Microsoft Internet Explorer |
Gecko | Mozilla Firefox |
Presto | Opera 12.15- |
国产浏览器
国产浏览器全部都是套壳浏览器,都离不开上述内核
因为在国内,国产浏览器用户数庞大,开发前端项目的过程中也不得不考虑国产浏览器所用的内核情况
下面将通过测试分析各主流国产浏览器Ua及内核情况(点击缩略图可放大查看)
![]() | |||
---|---|---|---|
![]() |
![]() |
Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; QQBrowser/8.0.2959.400; rv:11.0) like Gecko |
Trident (调用系统IE内核) |
![]() |
|||
---|---|---|---|
![]() |
![]() |
Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/38.0.2125.122 BIDUBrowser/7.0 Safari/537.36 |
Blink (WebKit) |
![]() |
|||
---|---|---|---|
![]() |
![]() |
Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36 |
高速模式内核 |
WebKit | |||
![]() |
Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36(KHTML, like Gecko UBrowser/4.0.3214.0) Chrome/36.0.1985.143 Safari/537.36 Edge/12.0 |
兼容模式内核 | |
Trident (调用系统IE内核) |
![]() |
|||
---|---|---|---|
![]() |
![]() |
Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36 SE 2.X MetaSr 1.0 |
WebKit |
![]() |
|||
---|---|---|---|
![]() |
![]() |
Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36 LBBROWSER |
WebKit |
![]() |
|||
---|---|---|---|
![]() |
![]() |
Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 |
高速模式内核 |
WebKit | |||
![]() |
Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko |
兼容模式内核 | |
Trident (调用系统IE内核) |
|||
![]() |
![]() |
Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 |
Blink (WebKit) |
![]() |
|||
---|---|---|---|
![]() |
![]() |
Mozilla/5.0 (Windows NT 6.2; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko |
高速模式内核 |
Trident | |||
![]() |
Mozilla/5.0 (Windows NT 6.2; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko |
兼容模式内核 | |
Trident (调用系统IE内核) |
|||
![]() |
![]() |
Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/31.0.1650.69 Safari/537.36 2345chrome v2.5.0.3895 |
WebKit |
通过以上测试实践,可以得出一些关于国产浏览器内核及Ua的结论
- 国产浏览器内核不是WebKit就是Trident(调用系统IE内核);
- 使用WebKit内核的国产浏览器最新版本的内核基本能保持接近Chrome最新版本内核;
- 部分国产浏览器没有在Ua中标注自身信息
使得开发者难以通过用户代理检测判断用户使用的国产浏览器类型
若使用上文中的代码检测国产浏览器品牌,则不是返回Chrome就是返回IE
这是因为只有一部分国产浏览器有在Ua中正确标注自身信息,难以准确检测
不过其实也基本没必要检测到国产浏览器具体品牌,检测其是什么内核比品牌重要吧
感慨一下,国产浏览器什么时候才能拥有自己的内核啊......
判断操作系统
在本文“先看结论/可用代码”部分中,还有一部分代码是用于检测Ua中包含的操作系统信息
根据常识,我们知道当前流行的操作系统有Windows XP/Vista/7/8/8.1/10、Mac OS、Unix等
可以通过类似以下代码检测用户当前使用的操作系统
/*以下代码作用为检测用户当前使用的操作系统平台*/ //... var p=navigator.platform; //判断操作系统 system.win=p.indexOf("Win")==0; system.mac=p.indexOf("Mac")==0; system.x11=(p.indexOf("X11")==0)||(p.indexOf("Linux")==0); //...
之所以是使用navigator.platform是因为这样要比检测用户代理字符串更加简单
navigator.platform属性可能的值包括“Win32”、“Win64”、“MacPPC”、“MacIntel”、“X11”和"Linux i686"等
还好这些值在不同浏览器中都是一致的,使得检测平台变得简单
若用户使用的是Windows平台,还可以通过Ua检测其版本
需要注意的是,在Ua中,Windows的版本并不直观,用来表示版本的数字其实是当前Windows的内核版本
当前主流Windows版本及其内核对照表如下
版本 | 内核版本 |
---|---|
Windows XP | 5.1 |
Windows Vista | 6.0 |
Windows 7 | 6.1 |
Windows 8 | 6.2 |
Windows 8.1 | 6.3 |
Windows 10 技术预览版 | 6.4 |
Windows 10 (Build 9880+) | 10 |
故可以通过类似以下代码检测用户所在Windows平台的版本
/*以下代码作用为检测用户使用的Windows版本*/ if(system.win){ if(/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)){ if(RegExp["$1"]=="NT"){ system.win = ({ "5.0" : "2000", "5.1" : "XP", "6.0" : "Vista", "6.1" : "7", "6.2" : "8", "6.3" : "8.1", "10" : "10" })[RegExp["$2"]] || "NT"; }else if(RegExp["$1"]=="9x"){ system.win="ME"; }else{ system.win=RegExp["$1"]; } } }
[2015/01/16注:以上代码测试并吸收了本文评论中@luobotang的建议,感谢反馈]
检测用户操作系统应该是统计作用大于功能作用吧!
随笔感想
本文略长,不知有没有人看到这里了呢?
看书本介绍关于Ua的知识,感觉略微过时了,想着自己整理一下
虚拟机搞呀搞,也没想到倒饬了这么久才搞定,具体是做了几天自己都忘了,此外排版综合症又发作了......
其实也不知道做这件事情有没有意义,只是喜欢就做做
不过强调一下,楼主只是大学菜鸟一只,本文所整理的内容虽多为实践,但也可能有纰漏
若路过的大牛发现本文有什么问题,欢迎您不吝留言指正哦!我会及时修改的!