用户代理在Javascript中解析

时间:2014-06-24 00:00:57

标签: javascript parsing

我需要从用户代理字符串中提取操作系统的名称和浏览器的名称。

用户代理示例:

Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.9) Gecko/20100825 Ubuntu/9.10 (karmic) Firefox/3.6.9

如何才能获得操作系统(示例"Linux i686""Firefox 3.6.9")?

以下是我的小提琴link中的代码,如下所示:

function getBrowserAndOS(userAgent, elements) {
  var browserList = {
      'Chrome': [/Chrome\/(\S+)/],
      'Firefox': [/Firefox\/(\S+)/],
      'MSIE': [/MSIE (\S+);/],
      'Opera': [
        /Opera\/.*?Version\/(\S+)/,
        /Opera\/(\S+)/
      ],
      'Safari': [/Version\/(\S+).*?Safari\//]
    },
    re, m, browser, version;


  var osList = {
      'Windows': [/Windows\/(\S+)/],
      'Linux': [/Linux\/(\S+)/]
    },
    re2, m2, os;

  if (userAgent === undefined)
    userAgent = navigator.userAgent;

  if (elements === undefined)
    elements = 2;
  else if (elements === 0)
    elements = 1337;

  for (browser in browserList) {
    while (re = browserList[browser].shift()) {
      if (m = userAgent.match(re)) {
        version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,' + --elements + '}')))[0];
        //version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,}')))[0];
        //return browser + ' ' + version;
        console.log(browser + ' ' + version);
      }
    }
  }


  for (os in osList) {
    while (re2 = osList[os].shift()) {
      if (m2 = userAgent.match(re2)) {
        //version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,' + --elements + '}')))[0];
        //version = (m[1].match(new RegExp('[^.]+(?:\.[^.]+){0,}')))[0];
        //return browser + ' ' + version;
        console.log(os);
      }

    }
  }

  return null;
}

console.log(getBrowserAndOS(navigator.userAgent, 2));

我只需要提取操作系统名称和浏览器名称及其各自的版本。如何解析它以获得那些字符串?

4 个答案:

答案 0 :(得分:1)

您是否计划根据用户代理(UA)字符串中的“嗅探”浏览器控制您网站的行为?

请不要;改为使用特征检测。

实施不当(非未来)用户代理嗅探已被证明是每次新版Internet Explorer发布时遇到的最大兼容性问题。因此,多年来围绕用户代理字符串的逻辑变得越来越复杂;兼容模式的引入意味着浏览器现在有多个UA字符串,并且在多年滥用后,该字符串的遗留可扩展性已被弃用。

默认情况下,Windows 8.1上的Internet Explorer 11发送以下用户代理字符串:

Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko

这个字符串是故意设计的,可以使大多数UA字符串嗅探逻辑将其解释为Gecko或WebKit。这个设计选择非常谨慎 - IE团队测试了许多UA字符串变体,以找出哪些会导致大多数网站为IE11用户“正常工作”。

以下two links实际上会对您有所帮助。您可能还想查看我的大部分评论的original source

答案 1 :(得分:1)

这是用于识别操作系统的本机JavaScript解决方案,但无论何时引入新操作系统,都需要手动更新:

function getOs (userAgent) {

     //Converts the user-agent to a lower case string
     var userAgent = userAgent.toLowerCase();

     //Fallback in case the operating system can't be identified
     var os = "Unknown OS Platform";

     //Corresponding arrays of user-agent strings and operating systems
     match = ["windows nt 10","windows nt 6.3","windows nt 6.2","windows nt 6.1","windows nt 6.0","windows nt 5.2","windows nt 5.1","windows xp","windows nt 5.0","windows me","win98","win95","win16","macintosh","mac os x","mac_powerpc","android","linux","ubuntu","iphone","ipod","ipad","blackberry","webos"];
     result = ["Windows 10","Windows 8.1","Windows 8","Windows 7","Windows Vista","Windows Server 2003/XP x64","Windows XP","Windows XP","Windows 2000","Windows ME","Windows 98","Windows 95","Windows 3.11","Mac OS X","Mac OS X","Mac OS 9","Android","Linux","Ubuntu","iPhone","iPod","iPad","BlackBerry","Mobile"];

     //For each item in match array
     for (var i = 0; i < match.length; i++) {

              //If the string is contained within the user-agent then set the os 
              if (userAgent.indexOf(match[i]) !== -1) {
                   os = result[i];
                   break;
              }

     }

     //Return the determined os
     return os;
}

答案 2 :(得分:0)

我不建议你自己这样做。我使用像Platform.js这样的解析器,其工作原理如下:

<script src="platform.js"></script>
<script>
var os = platform.os;
var browser = platform.name + ' ' + platform.version;
</script>

答案 3 :(得分:0)

Useragent不是一组用于询问诸如“你是什么?”之类的定性问题的元数据,它们实际上仅对诸如“你是Linux吗?”或“ Firefox的哪个版本”之类的是/否问题有用。是吗?”。

让我说明一下,这是一个将用户代理转换成可爱的json可序列化对象的脚本:

parseUA = (() => {
    //useragent strings are just a set of phrases each optionally followed by a set of properties encapsulated in paretheses
    const part = /\s*([^\s/]+)(\/(\S+)|)(\s+\(([^)]+)\)|)/g;
    //these properties are delimited by semicolons
    const delim = /;\s*/;
    //the properties may be simple key-value pairs if;
    const single = [
        //it is a single comma separation,
        /^([^,]+),\s*([^,]+)$/,
        //it is a single space separation,
        /^(\S+)\s+(\S+)$/,
        //it is a single colon separation,
        /^([^:]+):([^:]+)$/,
        //it is a single slash separation
        /^([^/]+)\/([^/]+)$/,
        //or is a special string
        /^(.NET CLR|Windows)\s+(.+)$/
    ];
    //otherwise it is unparsable because everyone does it differently, looking at you iPhone
    const many = / +/;
    //oh yeah, bots like to use links
    const link = /^\+(.+)$/;

    const inner = (properties, property) => {
        let tmp;

        if (tmp = property.match(link)) {
            properties.link = tmp[1];
        }
        else if (tmp = single.reduce((match, regex) => (match || property.match(regex)), null)) {
            properties[tmp[1]] = tmp[2];
        }
        else if (many.test(property)) {
            if (!properties.properties)
                properties.properties = [];
            properties.properties.push(property);
        }
        else {
            properties[property] = true;
        }

        return properties;
    };

    return (input) => {
        const output = {};
        for (let match; match = part.exec(input); '') {
            output[match[1]] = {
                ...(match[5] && match[5].split(delim).reduce(inner, {})),
                ...(match[3] && {version:match[3]})
            };
        }
        return output;
    };
})();
//parseUA('user agent string here');

使用此方法,我们可以转换出以下用户代理:

`Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)`

{
    "Mozilla": {
        "compatible": true,
        "MSIE": "7.0",
        "Windows": "NT 6.0",
        "WOW64": true,
        "Trident": "4.0",
        "SLCC1": true,
        ".NET CLR": "3.0.30729",
        ".NET4.0C": true,
        ".NET4.0E": true,
        "version": "4.0"
    }
}

`Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S8500-BOUYGUES/S8500AGJF1; U; Bada/1.0; fr-fr) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.0 Mobile WVGA SMM-MMS/1.2.0 NexPlayer/3.0 profile/MIDP-2.1 configuration/CLDC-1.1 OPN-B`

{
    "Mozilla": {
        "SAMSUNG": true,
        "SAMSUNG-GT-S8500-BOUYGUES": "S8500AGJF1",
        "U": true,
        "Bada": "1.0",
        "fr-fr": true,
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "533.1"
    },
    "Dolfin": {
        "version": "2.0"
    },
    "Mobile": {},
    "WVGA": {},
    "SMM-MMS": {
        "version": "1.2.0"
    },
    "NexPlayer": {
        "version": "3.0"
    },
    "profile": {
        "version": "MIDP-2.1"
    },
    "configuration": {
        "version": "CLDC-1.1"
    },
    "OPN-B": {}
}

`Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Comodo_Dragon/4.1.1.11 Chrome/4.1.249.1042 Safari/532.5`

{
    "Mozilla": {
        "Windows": "NT 5.1",
        "U": true,
        "en-US": true,
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "532.5"
    },
    "Comodo_Dragon": {
        "version": "4.1.1.11"
    },
    "Chrome": {
        "version": "4.1.249.1042"
    },
    "Safari": {
        "version": "532.5"
    }
}

`Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36`

{
    "Mozilla": {
        "X11": true,
        "Fedora": true,
        "Linux": "x86_64",
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "537.36"
    },
    "Chrome": {
        "version": "73.0.3683.86"
    },
    "Safari": {
        "version": "537.36"
    }
}

`Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0`

{
    "Mozilla": {
        "X11": true,
        "Fedora": true,
        "Linux": "x86_64",
        "rv": "66.0",
        "version": "5.0"
    },
    "Gecko": {
        "version": "20100101"
    },
    "Firefox": {
        "version": "66.0"
    }
}

`Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36`

{
    "Mozilla": {
        "X11": true,
        "Linux": "x86_64",
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "537.36"
    },
    "Chrome": {
        "version": "73.0.3683.103"
    },
    "Safari": {
        "version": "537.36"
    }
}

`Mozilla/5.0 (Linux; Android 6.0.1; SM-G920V Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36`

{
    "Mozilla": {
        "Linux": true,
        "Android": "6.0.1",
        "SM-G920V": "Build/MMB29K",
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "537.36"
    },
    "Chrome": {
        "version": "52.0.2743.98"
    },
    "Mobile": {},
    "Safari": {
        "version": "537.36"
    }
}

`Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1 (compatible; AdsBot-Google-Mobile; +http://www.google.com/mobile/adsbot.html)`

{
    "Mozilla": {
        "iPhone": true,
        "properties": [
            "CPU iPhone OS 9_1 like Mac OS X"
        ],
        "version": "5.0"
    },
    "AppleWebKit": {
        "KHTML": "like Gecko",
        "version": "601.1.46"
    },
    "Version": {
        "version": "9.0"
    },
    "Mobile": {
        "version": "13B143"
    },
    "Safari": {
        "compatible": true,
        "AdsBot-Google-Mobile": true,
        "link": "http://www.google.com/mobile/adsbot.html",
        "version": "601.1"
    }
}

如果您将扩展为人类,那么您可以轻松地读取以下操作系统版本:Mozilla.Windows = NT 6.0Mozilla.Bada = 1.0Mozilla.Fedora && Mozilla.Linux = x86_64
但是您看到问题了吗?他们都没有说OS = "Windows"OS = "Samsung Bada"等。

要问您想要的问题,您需要对所有可能的值有所了解,就像上面@Peter Wetherall所尝试的那样,或者说“我只在乎这些少数的浏览器/操作系统”,例如您有什么问题。

如果可以,并且您不是要使用信息来更改代码的工作方式(按照@Sophit不应这样做),而只是想显示有关浏览器的内容,我会使用上面的parseUA()与手动检查Mozilla.Windows || Mozilla.Linux || //et cetera的组合,与尝试通过正则表达式对原始useragent字符串进行幸运操作相比,这种方法更容易出错(这会导致误报:请参见浏览器Comodo_Dragon说:“ Chrome”)。