Javascript 中的用户代理解析
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24376418/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
User Agent parsing in Javascript
提问by jeewan
I need to extract the Operating System's name and the browser's name from the user agent string.
我需要从用户代理字符串中提取操作系统的名称和浏览器的名称。
Sample of user agent:
用户代理示例:
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.9) Gecko/20100825 Ubuntu/9.10 (karmic) Firefox/3.6.9
How can I get just the operating system (example "Linux i686"
and "Firefox 3.6.9"
)?
我如何才能获得操作系统(示例"Linux i686"
和"Firefox 3.6.9"
)?
Here is my codes in fiddle linkwhich is as follows:
这是我在小提琴链接中的代码,如下所示:
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));
I just need to extract the OS name and the browser name with their respective versions. How can I parse it to get those string?
我只需要提取操作系统名称和浏览器名称及其各自的版本。我如何解析它以获取这些字符串?
回答by Evan Hahn
I wouldn't recommend doing this yourself. I'd use a parser like Platform.js, which works like this:
我不建议自己这样做。我会使用像Platform.js这样的解析器,它的工作原理是这样的:
<script src="platform.js"></script>
<script>
var os = platform.os;
var browser = platform.name + ' ' + platform.version;
</script>
回答by Hashbrown
Useragents aren't a set of metadata useful for asking qualitative questions such as "what are you?", they're really only useful for yes/no questions like "are you linux?", or "what version of Firefox are you?".
Useragents 不是用于询问诸如“你是什么?”之类的定性问题的一组元数据,它们实际上仅对“你是 linux 吗?”或“你是什么版本的 Firefox?”等是/否问题有用吗? ”。
Let me illustrate, here's a script that converts useragents to lovely json-serialisable objects:
让我来说明一下,这是一个将用户代理转换为可爱的 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');
Using this, we can convert out the following useragents:
使用它,我们可以转换出以下用户代理:
`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"
}
}
If you expand that you'll see, that as a human, you can easily read out the Operating System versions: Mozilla.Windows = NT 6.0
, Mozilla.Bada = 1.0
, Mozilla.Fedora && Mozilla.Linux = x86_64
.
But do you see the issue? None of them say OS = "Windows"
, OS = "Samsung Bada"
, et cetera.
如果您展开它,您会看到,作为人类,您可以轻松地读出操作系统版本:Mozilla.Windows = NT 6.0
、Mozilla.Bada = 1.0
、Mozilla.Fedora && Mozilla.Linux = x86_64
。
但是你看到问题了吗?他们都没有说OS = "Windows"
,OS = "Samsung Bada"
等等。
To ask the questions you want to you will need to be privy to all the possible values, kind of like what @Peter Wetherall
attempted above, or say "I only care about these handful of browsers/OS's", like what you have in your question.
要问你想要的问题,你需要了解所有可能的值,有点像@Peter Wetherall
上面尝试的那样,或者说“我只关心这些少数浏览器/操作系统”,就像你在问题中所说的那样。
If that's okay, and you're not using the information to change how the code works (which shouldn't be done as per @Sophit
), just wanting to display stuff about the browser, I'd use the above parseUA()
in combination with manually checking Mozilla.Windows || Mozilla.Linux || //et cetera
which will be less error-prone than trying to get lucky with regex's over the raw useragent string (which will lead to false positives: see the browser Comodo_Dragon says "Chrome" in it).
如果没问题,并且您没有使用这些信息来更改代码的工作方式(不应按照 执行@Sophit
),只是想显示有关浏览器的内容,我会将上述内容parseUA()
与手动检查Mozilla.Windows || Mozilla.Linux || //et cetera
哪个与尝试在原始用户代理字符串上使用正则表达式(这将导致误报:请参阅浏览器 Comodo_Dragon 在其中显示“Chrome”)相比,更不容易出错。
回答by Sophit
Were you planning to control your website's behavior based on the browser “sniffed” from the User-Agent (UA) string?
您是否打算根据从用户代理 (UA) 字符串“嗅探”到的浏览器来控制您网站的行为?
Please don't; use feature detection instead.
请不要;改用特征检测。
Poorly implemented (non-futureproof) User-Agent sniffing has proven to be the top compatibility problem encountered each time a new version of Internet Explorer ships. As a consequence, the logic around the user-agent string has grown increasingly complicated over the years; the introduction of Compatibility Modes has meant that the browser now has more than one UA string, and legacy extensibility of the string was deprecated after years of abuse.
实践证明,每次发布新版本的 Internet Explorer 时,用户代理嗅探都被证明是最严重的兼容性问题。因此,多年来围绕用户代理字符串的逻辑变得越来越复杂;兼容模式的引入意味着浏览器现在拥有不止一个 UA 字符串,并且该字符串的传统可扩展性在多年滥用后已被弃用。
By default, Internet Explorer 11 on Windows 8.1 sends the following User-Agent string:
默认情况下,Windows 8.1 上的 Internet Explorer 11 发送以下用户代理字符串:
Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko
This string is deliberately designed to cause most UA-string sniffing logic to interpret it either Gecko or WebKit. This design choice was a careful one—the IE team tested many UA string variants to find out which would cause the majority of sites to “just work” for IE11 users.
这个字符串被故意设计成导致大多数 UA 字符串嗅探逻辑来解释它,无论是 Gecko 还是 WebKit。这种设计选择是谨慎的——IE 团队测试了许多 UA 字符串变体,以找出哪些会导致大多数网站对 IE11 用户“正常工作”。
Here are twolinksthat will actually help you. You may also want to view the original sourceof much of my comment.
回答by Peter
This is a native JavaScript solution for identifying the OS, however would need to be manually updated whenever a new OS is introduced:
这是用于识别操作系统的原生 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;
}