用户代理字符串检测技术【2】

4. 识别Windows操作系统

在Windows平台下,还可以从用户代理字符串中进一步取得具体的操作系统信息。在Windows XP之前,Windows有两种版本,分别针对家庭用户和商业用户。针对家庭用户的版本分别是Windows 95、98和Windows ME。而针对商业用户的版本则一直叫做Window NT,最后由于市场原因改名为Windows 2000。这两个产品线后来又合并成一个由Windows NT发展而来的公共的代码基,代表产品就是Windows XP。随后,微软在Windows XP基础上又构建了Windows Vista。

只有了解这些信息,才能搞清楚用户代理字符串中Windows操作系统的具体版本。下表列出了不同浏览器在表示不同的Windows操作系统时给出的不同字符串。

Windows版本IE 4+GeckoOpera < 7Opera 7+WebKit95"Windows 95""Win95""Windows 95""Windows 95"n/a98"Windows 98""Win98""Windows 98""Windows 98"n/aNT 4.0"Windows NT""WinNT4.0""Windows NT 4.0""Windows NT 4.0"n/a2000"Windows NT 5.0""Windows NT 5.0""Windows 2000""Windows NT 5.0"n/aME"Win 9x 4.90""Win 9x 4.90""Windows ME""Win 9x 4.90"n/aXP"Windows NT 5.1""Windows NT 5.1""Windows XP""Windows NT 5.1""Windows NT 5.1"Vista"Windows NT 6.0""Windows NT 6.0"n/a"Windows NT 6.0""Windows NT 6.0"7"Windows NT 6.1""Windows NT 6.1"n/a"Windows NT 6.1""Windows NT 6.1"

由于用户代理字符串中的Windows操作系统版本表示方法各异,因此检测代码并不十分直观。好在,从Windows 2000开始,表示操作系统的字符串大部分都还相同,只有版本号有变化。为了检测不同的Windows操作系统,必须要使用正则表达式。由于使用Opera 7之前版本的用户已经不多了,因此我们可以忽略这部分浏览器。

第一步就是匹配Windows 95和Windows 98这两个字符串。对这两个字符串,只有Gecko与其他浏览器不同,即没有"dows",而且"Win"与版本号之间没有空格。要匹配这个模式,可以使用下面这个简单的正则表达式。
/Win(?:dows )?([^do]{2})/

这个正则表达式中的捕获组会返回操作系统的版本。由于版本可能是任何两个字符编码(例如95、98、9x、NT、ME及XP),因此要使用两个非空格字符。
Gecko在表示Windows NT时会在末尾添加"4.0",与其查找实际的字符串,不如像下面这样查找小数值更合适。
/Win(?:dows )?([^do]{2})(\d+\.\d+)?/

这样,正则表达式中就包含了第二个捕获组,用于取得NT的版本号。由于该版本号对于Windows 95和Windows 98而言是不存在的,所以必须设置为可选。这个模式与Opera表示Windows NT的字符串之间唯一的区别,就是"NT"与"4.0"之间的空格,这在模式中很容易添加。
/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/

经过一番修改之后,这个正则表达式也可以成功地匹配Windows ME、Windows XP和Windows Vista的字符串了。具体来说,第一个捕获组将会匹配95、98、9x、NT、ME或XP。第二个捕获组则只针对Windows ME及所有Windows NT的变体。这个信息可以作为具体的操作系统信息保存在system.win属性中,如下所示。
if (system.win){
    if (/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)){
        if (RegExp["$1"] == "NT"){
            switch(RegExp["$2"]){
                case "5.0":
                    system.win = "2000";
                    break;
                case "5.1":
                    system.win = "XP";
                    break;
                case "6.0":
                    system.win = "Vista";
                    break;
                case "6.1":
                    system.win = "7";
                    break;
                default:
                    system.win = "NT";
                    break;                
            }                            
        } else if (RegExp["$1"] == "9x"){
            system.win = "ME";
        } else {
            system.win = RegExp["$1"];
        }
    }
}

如果system.win的值为true,那么就使用这个正则表达式从用户代理字符串中提取具体的信息。鉴于Windows将来的某个版本也许不能使用这个方法来检测,所以第一步应该先检测用户代理字符串是否与这个模式匹配。

在模式匹配的情况下,第一个捕获组中可能会包含"95"、"98"、"9x"或"NT"。如果这个值是"NT",可以将system.win设置为相应操作系统的字符串;如果是"9x",那么system.win就要设置成"ME";如果是其他值,则将所捕获的值直接赋给system.win。有了这些检测平台的代码后,我们就可以编写如下代码。
if (client.system.win){
    if (client.system.win == "XP") {
        //说明是XP
    } else if (client.system.win == "Vista"){
        //说明是Vista
    }
}

由于非空字符串会转换为布尔值true,因此可以将client.system.win作为布尔值用在if语句中。而在需要更多有关操作系统的信息时,则可以使用其中保存的字符串值。

5. 识别移动设备

2006年到2007年,移动设备中Web浏览器的应用呈爆炸性增长。四大主要浏览器都推出了手机版和在其他设备中运行的版本。要检测相应的设备,第一步是为要检测的所有移动设备添加属性,如下所示。
var client = function(){

    var engine = {

        //呈现引擎
        ie: 0,
        gecko: 0,
        webkit: 0,
        khtml: 0,
        opera: 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,

        //移动设备iphone: false,ipod: false,ipad: false,ios: false,android: false,nokiaN: false,winMobile: false};

    //在此检测呈现引擎、平台和设备

    return {
        engine: engine,
        browser: browser,
        system: system
    };

}();

然后,通常简单地检测字符串"iPhone"、"iPod"和"iPad",就可以分别设置相应属性的值了。
system.iphone = ua.indexOf("iPhone") > -1;
system.ipod = ua.indexOf("iPod") > -1;
system.ipod = ua.indexOf("iPad") > -1;

除了知道iOS设备,最好还能知道iOS的版本号。在iOS 3之前,用户代理字符串中只包含"CPU like Mac OS",后来iPhone中又改成"CPU iPhone OS 3_0 like Mac OS X",iPad中又改成"CPU OS 3_2 like Mac OS X"。也就是说,检测iOS需要正则表达式反映这些变化。
//检测iOS版本
if (system.mac && ua.indexOf("Mobile") > -1){
    if (/CPU (?:iPhone )?OS (\d+_\d+)/.test(ua)){
        system.ios = parseFloat(RegExp.$1.replace("_", "."));
    } else {
        system.ios = 2; //不能真正检测出来,所以只能猜测
    } 
}

检查系统是不是Mac OS、字符串中是否存在"Mobile",可以保证无论是什么版本,system.ios中都不会是0。然后,再使用正则表达式确定是否存在iOS的版本号。如果有,将system.ios设置为表示版本号的浮点值;否则,将版本设置为2。(因为没有办法确定到底是什么版本,所以设置为更早的版本比较稳妥。)

检测Android操作系统也很简单,也就是搜索字符串"Android"并取得紧随其后的版本号。
//检测Android版本
if (/Android (\d+\.\d+)/.test(ua)){ 
    system.android = parseFloat(RegExp.$1);
}

由于所有版本的Android都有版本值,因此这个正则表达式可以精确地检测所有版本,并将system.android设置为正确的值。
诺基亚N系列手机使用的也是WebKit,其用户代理字符串与其他基于WebKit的手机很相似,例如:
Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaN95/11.0.026; Profile MIDP-2.0
     Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413

虽然诺基亚N系列手机在用户代理字符串中声称使用的是"Safari",但实际上并不是Safari,尽管确实是基于WebKit引擎。只要像下面检测一下用户代理字符串中是否存在"NokiaN",就足以确定是不是该系列的手机了。
system.nokiaN = ua.indexOf("NokiaN") > -1;

在了解这些设备信息的基础上,就可以通过下列代码来确定用户使用的是什么设备中的WebKit来访问网页:
if (client.engine.webkit){
    if (client.system. iOS){
        //iOS手机的内容
    } else if (client.system.android){
        //Android手机的内容
    } else if (client.system.nokiaN){
        //诺基亚手机的内容
    }
}

最后一种主要的移动设备平台是Windows Mobile(也称为Windows CE),用于Pocket PC和Smartphone中。由于从技术上说这些平台都属于Windows平台,因此Windows平台和操作系统都会返回正确的值。对于Windows Mobile 5.0及以前版本,这两种设备的用户代理字符串非常相似,如下所示:
Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; 240x320)
Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; Smartphone; 176x220)

第一个来自Pocket PC中的移动Internet Explorer 4.01,第二个来自Smartphone中的同一个浏览器。当Windows操作系统检测脚本检测这两个字符串时,system.win将被设置为"CE",因此在检测Windows Mobile时可以使用这个值:
system.winMobile = (system.win == "CE");

不建议测试字符串中的"PPC"或"Smartphone",因为在Windows Mobile 5.0以后版本的浏览器中,这些记号已经被移除了。不过,一般情况下,只知道某个设备使用的是Windows Mobile也就足够了。
Windows Phone 7的用户代理字符串稍有改进,基本格式如下:
Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0)
    Asus;Galaxy6 

其中,Windows操作符的标识符与已往完全不同,因此在这个用户代理中client.system.win等于"Ph"。从中可以取得有关系统的更多信息:
//windows mobile
if (system.win == "CE"){
    system.winMobile = system.win;
} else if (system.win == "Ph"){
    if(/Windows Phone OS (\d+.\d+)/.test(ua)){;
        system.win = "Phone";
        system.winMobile = parseFloat(RegExp["$1"]);
    }
}

如果system.win的值是"CE",就说明是老版本的Windows Mobile,因此system.winMobile会被设置为相同的值(只能知道这个信息)。如果system.win的值是"Ph",那么这个设备就可能是Windows Phone 7或更新版本。因此就用正则表达式来测试格式并提取版本号,将system.win的值重置为"Phone",而将system.winMobile设置为版本号。

6. 识别游戏系统

除了移动设备之外,视频游戏系统中的Web浏览器也开始日益普及。任天堂Wii和Playstation 3或者内置Web浏览器,或者提供了浏览器下载。Wii中的浏览器实际上是定制版的Opera,是专门为Wii Remote设计的。Playstation的浏览器是自己开发的,没有基于前面提到的任何呈现引擎。这两个浏览器中的用户代理字符串如下所示:
Opera/9.10 (Nintendo Wii;U; ; 1621; en)
Mozilla/5.0 (PLAYSTATION 3; 2.00)

第一个字符串来自运行在Wii中的Opera,它忠实地继承了Opera最初的用户代理字符串格式(Wii上的Opera不具备隐瞒身份的能力)。第二个字符串来自Playstation3,虽然它为了兼容性而将自己标识为Mozilla 5.0,但并没有给出太多信息。而且,设备名称居然全部使用了大写字母,让人觉得很奇怪;强烈希望将来的版本能够改变这种情况。
在检测这些设备以前,我们必须先为client.system中添加适当的属性,如下所示:
var client = function(){

    var engine = {

        //呈现引擎
        ie: 0,
        gecko: 0,
        webkit: 0,
        khtml: 0,
        opera: 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,

        //移动设备
        iphone: false,
        ipod: false,
        ipad: false,
        ios: false,
        android: false,
        nokiaN: false,
        winMobile: false,
        //游戏系统wii: false,ps: false
    };

    //在此检测呈现引擎、平台和设备

    return {
        engine: engine,
        browser: browser,
        system: system
    };

}();

检测前述游戏系统的代码如下:
system.wii = ua.indexOf("Wii") > -1;
system.ps = /playstation/i.test(ua);

对于Wii,只要检测字符串"Wii"就够了,而其他代码将发现这是一个Opera浏览器,并将正确的版本号保存在client.browser.opera中。对于Playstation,我们则使用正则表达式来以不区分大小写的方式测试用户代理字符串。 

想要了解更多Java基础知识,可以点击评论区链接和小编一起学习java吧,此视频教程为初学者而著,零基础入门篇!给同学们带来全新的Java300集课程啦!java零基础小白自学Java必备优质教程_手把手图解学习Java,让学习成为一种享受_哔哩哔哩_bilibili

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值