浏览器的嗅探主要基于Window
对象的Navigator
属性对浏览器的类型、名称、厂商以及运行环境等作出判断,满足不同生产环境的需求。
常见的微信浏览器环境
的判断:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
</head>
<body>
<script type="text/javascript">
var ua = navigator.userAgent.toLowerCase();
var isWeixin = ua.indexOf('micromessenger') != -1;
var isAndroid = ua.indexOf('android') != -1;
var isIos = (ua.indexOf('iphone') != -1) || (ua.indexOf('ipad') != -1);
if (!isWeixin) {
document.head.innerHTML = '<title>抱歉,出错了</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0"><link rel="stylesheet" type="text/css" href="https://res.wx.qq.com/open/libs/weui/0.4.1/weui.css">';
document.body.innerHTML = '<div class="weui_msg"><div class="weui_icon_area"><i class="weui_icon_info weui_icon_msg"></i></div><div class="weui_text_area"><h4 class="weui_msg_title">请在微信客户端打开链接</h4></div></div>';
}
</script>
</body>
</html>
以上代码js部分基本可以直接截取出作为微信浏览器运行环境下的判断,并提供了错误页内容。
值得一提的是,我在微信windows版本中测试其内置浏览器识别结果是
Chrome
,并不是微信环境MicroMessageer
。
Navigator对象
可以直接在浏览器命令行下使用window.navigator
查看其包含的各种属性内容(取常用属性解释):
- appName
返回浏览器的名称。在IE
中,就是“Microsoft Internet Explorer”
;在FireFox以及其他浏览器
中,就是“Netscape”
。 - appVersion
返回浏览器的平台和版本信息(通常以数字开始)。 - platform
返回运行浏览器的操作系统平台。 - onLine
返回指明系统是否处于脱机模式的布尔值。 - userAgent!!!
返回由客户机发送服务器的user-agent
头部的值。
userAgent 属性是一个只读的字符串,声明了浏览器用于 HTTP 请求的用户代理头的值。
一般来讲,它是在 navigator.appCodeName
的值之后加上斜线
和 navigator.appVersion
的值构成的。
例如:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)。
注:用户代理头:user-agent header。
总结的浏览器嗅探插件
;
var _BROWSER = (function() {
function detect() {
// start browser detect
var nVer = navigator.appVersion,
nAgt = navigator.userAgent,
browser = navigator.appName,
version = '' + parseFloat(navigator.appVersion),
majorVersion, nameOffset, verOffset, ix, network = 'unknown';
// Opera
if ((verOffset = nAgt.indexOf('Opera')) != -1) {
browser = 'Opera';
version = nAgt.substring(verOffset + 6);
if ((verOffset = nAgt.indexOf('Version')) != -1) {
version = nAgt.substring(verOffset + 8);
}
}
// Opera Next
if ((verOffset = nAgt.indexOf('OPR')) != -1) {
browser = 'Opera';
version = nAgt.substring(verOffset + 4);
}
// MSIE
if ((verOffset = nAgt.indexOf('MSIE')) != -1) {
browser = 'Microsoft Internet Explorer';
version = nAgt.substring(verOffset + 5);
}
// Chrome
if ((verOffset = nAgt.indexOf('Chrome')) != -1) {
browser = 'Chrome';
version = nAgt.substring(verOffset + 7);
}
// Safari
if ((verOffset = nAgt.indexOf('Safari')) != -1) {
browser = 'Safari';
version = nAgt.substring(verOffset + 7);
if ((verOffset = nAgt.indexOf('Version')) != -1) {
version = nAgt.substring(verOffset + 8);
}
}
// Firefox
if ((verOffset = nAgt.indexOf('Firefox')) != -1) {
browser = 'Firefox';
version = nAgt.substring(verOffset + 8);
}
// MSIE 11+
if (nAgt.indexOf('Trident/') != -1) {
browser = 'Microsoft Internet Explorer 11+';
version = nAgt.substring(nAgt.indexOf('rv:') + 3);
}
// WeiXin
if (nAgt.toLowerCase().indexOf('micromessenger') != -1) {
browser = 'WeiXin';
if (nAgt.indexOf('NetType/WIFI') != -1) {
network = 'WIFI';
} else if (nAgt.indexOf('NetType/2G') != -1) {
network = '2G';
} else if (nAgt.indexOf('NetType/3G+') != -1) {
network = '3G+';
} else if (nAgt.indexOf('NetType/4G') != -1) {
network = '4G';
}
verOffset = nAgt.lastIndexOf('/')
version = nAgt.substring(verOffset + 1);
// if (browser.toLowerCase() == browser.toUpperCase()) {
// browser = navigator.appName;
// }
}
// Other browsers
else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) {
browser = nAgt.substring(nameOffset, verOffset);
version = nAgt.substring(verOffset + 1);
if (browser.toLowerCase() == browser.toUpperCase()) {
browser = navigator.appName;
}
}
// trim the version string
if ((ix = version.indexOf(';')) != -1) version = version.substring(0, ix);
if ((ix = version.indexOf(' ')) != -1) version = version.substring(0, ix);
if ((ix = version.indexOf(')')) != -1) version = version.substring(0, ix);
majorVersion = parseInt('' + version, 10);
if (isNaN(majorVersion)) {
version = '' + parseFloat(navigator.appVersion);
majorVersion = parseInt(navigator.appVersion, 10);
}
// mobile version
var mobile = /Mobile|mini|Fennec|Android|iP(ad|od|hone)/.test(nVer);
// start system detect
var os = '';
var clientStrings = [{
s: 'Windows 10',
r: /(Windows 10.0|Windows NT 10.0)/
}, {
s: 'Windows 8.1',
r: /(Windows 8.1|Windows NT 6.3)/
}, {
s: 'Windows 8',
r: /(Windows 8|Windows NT 6.2)/
}, {
s: 'Windows 7',
r: /(Windows 7|Windows NT 6.1)/
}, {
s: 'Windows Vista',
r: /Windows NT 6.0/
}, {
s: 'Windows Server 2003',
r: /Windows NT 5.2/
}, {
s: 'Windows XP',
r: /(Windows NT 5.1|Windows XP)/
}, {
s: 'Windows 2000',
r: /(Windows NT 5.0|Windows 2000)/
}, {
s: 'Windows ME',
r: /(Win 9x 4.90|Windows ME)/
}, {
s: 'Windows 98',
r: /(Windows 98|Win98)/
}, {
s: 'Windows 95',
r: /(Windows 95|Win95|Windows_95)/
}, {
s: 'Windows NT 4.0',
r: /(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/
}, {
s: 'Windows CE',
r: /Windows CE/
}, {
s: 'Windows 3.11',
r: /Win16/
}, {
s: 'Android',
r: /Android/
}, {
s: 'Open BSD',
r: /OpenBSD/
}, {
s: 'Sun OS',
r: /SunOS/
}, {
s: 'Linux',
r: /(Linux|X11)/
}, {
s: 'iOS',
r: /(iPhone|iPad|iPod)/
}, {
s: 'Mac OS X',
r: /Mac OS X/
}, {
s: 'Mac OS',
r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/
}, {
s: 'QNX',
r: /QNX/
}, {
s: 'UNIX',
r: /UNIX/
}, {
s: 'BeOS',
r: /BeOS/
}, {
s: 'OS/2',
r: /OS\/2/
}, {
s: 'Search Bot',
r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/
}];
for (var id in clientStrings) {
var cs = clientStrings[id];
if (cs.r.test(nAgt)) {
os = cs.s;
break;
}
}
var osVersion = '';
if (/Windows/.test(os)) {
osVersion = /Windows (.*)/.exec(os)[1];
os = 'Windows';
}
switch (os) {
case 'Mac OS X':
osVersion = /Mac OS X (10[\.\_\d]+)/.exec(nAgt)[1];
break;
case 'Android':
osVersion = /Android ([\.\_\d]+)/.exec(nAgt)[1];
break;
case 'iOS':
osVersion = /OS (\d+)_(\d+)_?(\d+)?/.exec(nVer);
osVersion = osVersion[1] + '.' + osVersion[2] + '.' + (osVersion[3] | 0);
break;
}
//detect data
var params = {};
params.os = os; //操作系统
params.osVersion = osVersion ? osVersion : 'unknown'; //操作系统版本
params.mobile = mobile; //是否移动端访问
params.browser = browser; //浏览器
params.browserVersion = version; //浏览器版本
params.browserMajorVersion = majorVersion; //浏览器major版本
//输出对象
return params;
}
return {
detect: detect
}
})();
借鉴了https://segmentfault.com/q/10…,但其代码有严重漏洞,尤其在检测是否在微信环境居然以网络类型为条件,坑死我了。在此将其封装为插件。
调用方法
BROSWER.detect()
返回结果示例
{
"os":"Windows",
"osVersion":"7",
"mobile":false,
"browser":"Chrome",
"browserVersion":"59.0.3071.115",
"browserMajorVersion":59
}