--- title: 使用用户代理字段进行浏览器检测 slug: Web/HTTP/Browser_detection_using_the_user_agent tags: - Browser detection - Browser detection using the user agent - user agent translation_of: Web/HTTP/Browser_detection_using_the_user_agent ---
但浏览器和标准并不完美,仍然需要检测浏览器的一些边缘情况。使用用户代理检测浏览器看起来很简单,但是做得很好,实际上是一个非常困难的问题。本文档将指导您尽可能正确地进行此操作。
值得重申的是:使用用户代理嗅探很少会成为一个好主意。你几乎总能发现一个更好的、更广泛兼容的方式来解决你的问题。
当你考虑使用用户代理字段来检测用户正在使用哪种浏览器的时候,第一步是试着回避它。从想明白你为什么要这样做开始。
如果你想要尝试避免使用用户代理检测,在某些情形下有些可供选择的方法。
由于用户代理字串的不同部分缺乏统一性,这是一个较难对付的问题。
当人们说他们想要进行“浏览器检测”的时候,他们实际上经常想要进行的是“渲染引擎检测”。你实际上想要检测使用的是火狐(Firefox)还是与之对应的海猴(SeaMonkey),或者使用的是Chrome还是与之对应的Chromium?或者你实际上只不过想看浏览器是否正在使用Gecko还是WebKit渲染引擎?如果这正是你需要的,请参阅后面的部分。
除了IE浏览器这个显著的例外,大部分的浏览器以浏览器名/版本号的格式设置浏览器名和版本。但是由于浏览器名不是用户代理字符串中唯一一个以这种格式命名的信息,你不能发现浏览器名,你只能检测是否这是你正在寻找的名字。但是要注意到,一些浏览器在说谎:例如Chrome的用户代理字符串中既会包含Chrome又会包含Safari。所以为了检测Safari浏览器,你不得不检测其中是否有Safari字符串同时没有Chrome字符串,Chromium也经常汇报它自己是Chrome浏览器,海猴有时也汇报它自己是火狐浏览器。
也要注意不要对浏览器名使用简单的正则表达式,用户代理字符串中也包含不属于键值对形式的字符串。例如在Safari和Chrome中包含有“like Gecko”一样的字符串。
必须包含 | 禁止包含 | ||
---|---|---|---|
Firefox | Firefox/xyz | Seamonkey/xyz | |
Seamonkey | Seamonkey/xyz | ||
Chrome | Chrome/xyz | Chromium/xyz | |
Chromium | Chromium/xyz | ||
Safari | Safari/xyz | Chrome/xyz or Chromium/xyz | Safari 有两个版本号,一个技术性较强,格式是Safari/xyz,一个对用户友好一点,格式是Version/xyz |
Opera |
OPR/xyz [1] Opera/xyz [2] |
[1] Opera 15+ (基于Blink的引擎) [2] Opera 12- (基于Presto的引擎) |
|
Internet Explorer | ; MSIE xyz; | IE浏览器的名字并没有使用BrowserName/VersionNumber的格式 |
当然,这里并没有保证其它浏览器不劫持上述字符串(像在过去,Chrome劫持了Safari的字符串)。这就是为什么使用用户代理字段进行浏览器检测是不可信的,并且做这个检测也仅仅应该是为了检测版本号(劫持过去的版本号这种事情很少发生)。
浏览器版本号通常但并不总是出现在用户代理字符串的浏览器名/版本号记号的值的位置。IE浏览器(该浏览器放置版本号刚好在MSIE记号之后)以及在版本10之后的Opera(新增了版本/版本号标记)就是例子。
此处再一次强调,由于并没有保证其它标记会包含有效的数字,请确保选取你正在寻找的浏览器的正确的标记。
正如早先提及到的,在大多数情况下,寻找渲染引擎是一个更好的方式。这将有助于保留鲜为人知的浏览器。使用共同的渲染引擎的浏览器将以相同的方式显示页面:这经常是一个公平的假设:一处有效,处处有效。
现在市面上有5个主流的渲染引擎:Trident,Gecko,Presto,Blink和WebKit。由于嗅探渲染引擎名是很普遍的,大量的用户代理在其字段中增加其它的渲染引擎名来触发检测。因此当检测渲染引擎的时候,一件很重要的事情,就是要避免“假阳性”(注:false-positives,指一个特性可通过检测,但实际在该浏览器下并不可靠或不可用)情况的发生。
必须包含 | ||
---|---|---|
Gecko | Gecko/xyz | |
WebKit | AppleWebKit/xyz | 请注意,WebKit浏览器包含了'like Gecko'字符串,如果不加以注意,可能会触发检测Gecko的false positive。 |
Presto | Opera/xyz | 注: 在Opera浏览器在15及以上的版本中,已经不再使用Presto(参见'Blink')。 |
Trident | Trident/xyz | IE浏览器将此字符串放在User Agent字符串的注释部分。 |
Blink | Chrome/xyz |
除了Gecko这个显著的例外,大部分的渲染引擎将版本号放置在渲染引擎/版本号标记中。 该引擎将Gecko版本号放置在用户代理的注释部分,在rv字符串之后。在手机版Gecko14以及桌面版Gecko17之后,该引擎也在Gecko/version标记处放置版本号的值(先前的版本中此处放置的是构建日期,然后固定的日期调用GeckoTrail)。
大多数的用户代理字符串也给出了用户使用的操作系统(尽管像Firefox OS这样的网络为中心的操作系统没有给出),但是给出的形式却多种多样。在用户代理的注释部分以夹在两个分号之间的固定字符串形式给出。对于每一个浏览器,这些字符串是特定的。这些字符串在显示操作系统的同时,也经常显示它的版本和其依赖的硬件信息(32位还是64位,或者是Mac平台的intel/PPC).
正如所有情形一样,这些字符串在将来也可能会改变,我们应该仅仅与已经发布的浏览器一起使用它们。当新的浏览器版本发布的时候,一份修改脚本以适应新版本的技术调查必须出现。
执行用户代理嗅探的一个最普遍的原因是查明浏览器是在何种硬件设备上运行的。而这么做的目的是对不同类型的设备提供不同的HTML页面。
下面这张表格总结了主要浏览器开发商声明他们的浏览器运行在手机设备上的方式:
浏览器 | 规则 | 示例 |
---|---|---|
Mozilla (Gecko, Firefox) | 注释中的 Mobile或Tablet标记 | Mozilla/5.0 (Android; Mobile; rv:13.0) Gecko/13.0 Firefox/13.0 |
WebKit-based (Android, Safari) | 注释外的Mobile Safari标记 | Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 |
Blink-based (Chromium, Google Chrome, Opera 15+) | 注释外的Mobile Safari标记 | Mozilla/5.0 (Linux; Android 4.4.2); Nexus 5 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Mobile Safari/537.36 OPR/20.0.1396.72047 |
Presto-based (Opera 12-) |
注释中的Opera Mobi/xyz标记(Opera 12-) |
Opera/9.80 (Android 2.3.3; Linux; Opera Mobi/ADR-1111101157; U; es-ES) Presto/2.9.201 Version/11.50 |
Internet Explorer | 注释中的IEMobile/xyz标记 | Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0) |
总之,我们建议检测移动设备的时候,在用户代理字符串中寻找“Mobi”字符串。
如果设备屏幕足够大,它就不会被用“Mobi”标记,你应该提供给用户你的桌面版网页(由于越来越多的桌面设备开始配有触摸屏,作为一个最佳体验,不管怎样,应该在该网页中提供触碰输入)