浏览器检测

10

检测用户浏览器的最佳/最简单/最准确的方法是什么?

易于扩展和实现是一个优点。

使用的技术越少越好。

解决方案可以是服务器端,客户端或两者都有。然而,结果最终需要在服务器上呈现。

解决方案可以是框架不可知的。

该解决方案仅用于报告目的。


3
不算是一个答案,但你可能会想阅读http://www.webaim.org/blog/user-agent-string-history/。如果没有其他的,它真的很有趣。 - dsm
12个回答

12

在服务器上,你几乎只能使用浏览器提供的UserAgent字符串(这是充满问题的,请阅读有关UserAgent字符串历史的文章)。

在客户端(即Javascript中),你有更多的选择。但最好的选择是实际上不要担心它是哪个浏览器。只需检查所需特性是否存在即可。

例如,你可能想要使用setCapture函数,这只有MSIE提供:

if (element.setCapture) element.setCapture()

与其先确定浏览器类型,再推断其能力,我们更好的做法是在使用功能前检查其是否支持——毕竟谁知道未来哪些浏览器会支持哪些功能呢?如果Safari决定支持setCapture,你难道想要回去更新你的脚本吗?


我非常喜欢(并从中学到了很多东西)那篇有关用户代理字符串历史的博客文章。 - billmalarky
很棒的回答。虽然许多人仍然依赖条件注释或浏览器嗅探,但如果您只是寻找功能检测,对于一个前瞻性的网络来说,这总是最好的选择。随着Web标准的进步和浏览器在旧版本规范上采用新功能,即使依赖特定的浏览器,也可能导致您的网站错误地确定该网站能够处理所需的功能。功能检测是确定您的网站现在和将来是否可用的唯一方法。感谢分享简单而准确的答案。 - tobint

6

JQuery浏览器插件将在客户端为您完成此操作。

JQuery浏览器插件是什么?

JQuery浏览器插件是jQuery的一个附加组件,它可以轻松地唯一标识您的访问者的浏览器。

它有什么作用?

它为您提供了一个包含有关所使用的浏览器的所有信息的javascript对象。它还添加了CSS浏览器选择器,这意味着您可以为特定的浏览器、浏览器版本、布局、布局版本甚至操作系统样式元素或编写函数。JQuery浏览器插件的示例图片。

该插件使$.browser可用,如果您确实需要服务器端,则可以通过AJAX调用将其重新提交到服务器。

alert($.browser.name);  // Alerts Firefox for me

插件的有效性取决于它所测试的浏览器。上面列出的插件中有一份已识别浏览器的列表,但总会有新的浏览器(比如Google Chrome..)悄悄出现,需要重新编写识别规则。话虽如此,这个插件似乎经常更新。

2
当使用JavaScript时:不要使用浏览器检测 编写代码以测试浏览器展示的给定情况,否则你只会为非常小的人群编写代码。最好使用"typeof foo == 'undefined'"和需要它们的特定于浏览器的技巧。
jQuery在其代码库中经常这样做(如果你查看代码,你会发现它实现了不同浏览器技术的行为)。
从长远来看,这是更好的选择。

如果你想要更好的性能,执行检查可能会很昂贵。有些情况下,提前知道使用哪些技术比使用错误检查并每次遇到错误时更改方向更好。 - Adam Davis
1
这个问题并不是关于为什么或者为什么不使用某种特定技术的,而只是关于如何最好地实现他选择的技术。你所知道的是,他可能并不想检测浏览器来塑造网站,而是想记录浏览器统计信息。 - Captain Toad

1

由于我刚刚在一个(现已删除的问题)中发布了这个,并且它仍然在我的剪贴板中,所以我将重新发布。 注意:这是一个服务器端 PHP 解决方案

我目前使用以下代码来实现此功能。 这不是一个详尽的解决方案,但应该很容易实现更多的浏览器。 我不知道 user-agents.org(感谢 PConroy),“有一天”我会遍历它并查看是否可以更新和添加到我的列表中。

define("BROWSER_OPERA","Opera");
define("BROWSER_IE","IE");
define("BROWSER_OMNIWEB","Omniweb");
define("BROWSER_KONQUEROR","Konqueror");
define("BROWSER_SAFARI","Safari");
define("BROWSER_MOZILLA","Mozilla");
define("BROWSER_OTHER","other");

$aBrowsers = array
(
  array("regexp" => "@Opera(/| )([0-9].[0-9]{1,2})@", "browser" => BROWSER_OPERA, "index" => 2),
  array("regexp" => "@MSIE ([0-9].[0-9]{1,2})@", "browser" => BROWSER_IE, "index" => 1),
  array("regexp" => "@OmniWeb/([0-9].[0-9]{1,2})@", "browser" => BROWSER_OMNIWEB, "index" => 1),
  array("regexp" => "@(Konqueror/)(.*)(;)@", "browser" => BROWSER_KONQUEROR, "index" => 2),
  array("regexp" => "@Safari/([0-9]*)@", "browser" => BROWSER_SAFARI, "index" => 1),
  array("regexp" => "@Mozilla/([0-9].[0-9]{1,2})@", "browser" => BROWSER_MOZILLA, "index" => 1)
);

foreach($aBrowsers as $aBrowser)
{
  if (preg_match($aBrowser["regexp"], $_SERVER["HTTP_USER_AGENT"], $aBrowserVersion))
  {
    define("BROWSER_AGENT",$aBrowser["browser"]);
    define("BROWSER_VERSION",$aBrowserVersion[$aBrowser["index"]]);
    break;
  }
}

1
谢谢您的转发。显然,被删除的问题并不是很好。 - Jrgns
这个问题本身因为某些原因得到了几个踩,提问者可能已经决定不再冒险损失他们的声望值。当你认真思考一个答案时,这确实会很烦人! - ConroyP
它开始下降,我意识到问题的格式可以更好,所以我将其删除了。对于答案的丢失感到抱歉... - Jrgns
这就是为什么浏览器检测不好的原因。你上面的代码无法检测到目前处于alpha版本的Opera 10。这是为什么特性检测更优秀的完美例子。参考信息:Opera/10.00 (Windows NT 5.2; U; en) Presto/2.2.2 - fearphage
这个问题显然很容易通过更新相应的正则表达式来解决。@Opera(/| )([0-9]{1,2}.[0-9]{1,2})@ 应该可以解决问题。特性检测可能不会过时,但也需要维护。此外,我正在使用它来创建干净的CSS文件(所以在我的脚本中除了特性检测之外)。 - Twan

0

这是我使用的C#代码,希望能对您有所帮助。

StringBuilder strb = new StringBuilder();
strb.AppendFormat ( "User Agent: {0}{1}", Request.ServerVariables["http_user_agent"].ToString(), Environment.NewLine );
strb.AppendFormat ( "Browser: {0}{1}", Request.Browser.Browser.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Version: {0}{1}", Request.Browser.Version.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Major Version: {0}{1}", Request.Browser.MajorVersion.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Minor Version: {0}{1}", Request.Browser.MinorVersion.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Platform: {0}{1}", Request.Browser.Platform.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "ECMA Script version: {0}{1}", Request.Browser.EcmaScriptVersion.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Type: {0}{1}", Request.Browser.Type.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "-------------------------------------------------------------------------------{0}",  Environment.NewLine );
strb.AppendFormat ( "ActiveX Controls: {0}{1}", Request.Browser.ActiveXControls.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Background Sounds: {0}{1}", Request.Browser.BackgroundSounds.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "AOL: {0}{1}", Request.Browser.AOL.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Beta: {0}{1}", Request.Browser.Beta.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "CDF: {0}{1}", Request.Browser.CDF.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "ClrVersion: {0}{1}", Request.Browser.ClrVersion.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Cookies: {0}{1}", Request.Browser.Cookies.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Crawler: {0}{1}", Request.Browser.Crawler.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Frames: {0}{1}", Request.Browser.Frames.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Tables: {0}{1}", Request.Browser.Tables.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "JavaApplets: {0}{1}", Request.Browser.JavaApplets.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "JavaScript: {0}{1}", Request.Browser.JavaScript.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "MSDomVersion: {0}{1}", Request.Browser.MSDomVersion.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "TagWriter: {0}{1}", Request.Browser.TagWriter.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "VBScript: {0}{1}", Request.Browser.VBScript.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "W3CDomVersion: {0}{1}", Request.Browser.W3CDomVersion.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Win16: {0}{1}", Request.Browser.Win16.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "Win32: {0}{1}", Request.Browser.Win32.ToString ( ), Environment.NewLine );
strb.AppendFormat ( "-------------------------------------------------------------------------------{0}", Environment.NewLine );
strb.AppendFormat ( "MachineName: {0}{1}", Environment.MachineName, Environment.NewLine );
strb.AppendFormat ( "OSVersion: {0}{1}", Environment.OSVersion, Environment.NewLine );
strb.AppendFormat ( "ProcessorCount: {0}{1}", Environment.ProcessorCount, Environment.NewLine );
strb.AppendFormat ( "UserName: {0}{1}", Environment.UserName, Environment.NewLine );
strb.AppendFormat ( "Version: {0}{1}", Environment.Version, Environment.NewLine );
strb.AppendFormat ( "UserInteractive: {0}{1}", Environment.UserInteractive, Environment.NewLine );
strb.AppendFormat ( "UserDomainName: {0}{1}", Environment.UserDomainName, Environment.NewLine );

0

0

不要使用浏览器检测:

  • 在最好的情况下,浏览器检测也不能保证100%的可靠性,但事情比这更糟:
  • 有许多浏览器变体(MSIE定制等)
  • 浏览器可以伪造其身份(Opera实际上已经内置了此功能)
  • 网关隐藏或混淆浏览器的身份
  • 自定义和网关供应商在USER_AGENT中编写自己的垃圾

最好在客户端脚本中进行特征检测。您希望仅需要浏览器检测来解决特定浏览器和版本中的错误。


1
这个问题并不是关于为什么或者为什么不使用某种特定技术的,而只是关于如何最好地实现他选择的技术。你所知道的是,他可能并不想检测浏览器来塑造网站,而是想记录浏览器统计信息。 - Captain Toad

0

编辑:下面的解决方案不建议使用。请尝试使用这个链接代替:http://whichbrowser.net/

这个方法曾经对我有用,但现在看代码,我完全不知道怎么回事了。请使用上面提供的链接代替 :-/

<script type="text/javascript">
    // <![CDATA[
    var BrowserCheck = Class.create({
        initialize: function () {
            var userAgent = navigator.userAgent.toLowerCase();
            this.version = (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1];
            this.safari = /webkit/.test(userAgent) && !/chrome/.test(userAgent);
            this.opera = /opera/.test(userAgent);
            this.msie = /msie/.test(userAgent) && !/opera/.test(userAgent);
            this.mozilla = /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent);
            this.chrome = /chrome/.test(userAgent);
        }
    });    
    // ]]>
</script>

不要忘记你需要初始化它才能使用,所以把这段代码放进去:
var UserBrowser = new BrowserCheck();

然后像这样检查浏览器类型和版本:(例如,Internet Explorer 8)

if ((UserBrowser.msie == true) && (UserBrowser.version == 8))

希望这对你有用,就像对我们一样,但请记住,没有浏览器检测是百分之百可靠的!


在IE9中,我通过控制台得到了“类未定义”的错误。 - mrswadge
@mrswadge 是的,我也遇到了同样的问题。很抱歉。请尝试使用这个链接代替:http://whichbrowser.net/ - Chuck Le Butt
@mrswadge 看起来是使用了Prototype库。我不知道为什么它曾经对我有效过。 - Chuck Le Butt
是的,我也看到了。没问题,我会检查http://whichbrowser.net链接。感谢您的帮助。 - mrswadge

0

正如许多人所说,浏览器检测可能会出现很大的问题...但是为了Code Golf的利益。

这是一种非常快速的检测IE的方法。

<script>
  if('\v'=='v'){
    alert('I am IE');
  } else {
    alert('NOT IE');
  }
</script>

这其实相当不错,因为它可以识别IE而不会在Opera上出现问题。

如果您知道为什么在IE中有效,那就更加赚了。;-)


0

我最初提出这个问题是因为我想记录人们用于访问我的网站的浏览器和操作系统。是的,用户代理字符串不能被信任,是的,你不应该使用浏览器检测来确定在JS中运行什么代码,但我希望尽可能准确地统计。

我做了以下事情。

我使用JavaScript和PHP的组合来记录统计数据。 JavaScript用于确定浏览器和操作系统(因为这可能是最准确的),而PHP用于记录它:

JavaScript来自Quirksmode,PHP相当明显。 我使用MooTools JS框架。

将以下内容添加到BrowserDetect脚本中:

window.addEvent('domready', function() {
    if (BrowserDetect) {
        var q_data = 'ajax=true&browser=' + BrowserDetect.browser + '&version=' + BrowserDetect.version + '&os=' + BrowserDetect.OS;
        var query = 'record_browser.php'
        var req = new Request.JSON({url: query, onComplete: setSelectWithJSON, data: q_data}).post();
    }
});

这可确定用户的浏览器、浏览器版本和操作系统,并将其发送到record_browser.php脚本。如果存在,record_browser.php脚本将添加信息,以及PHP session_id和当前的user_id

MySQL 表格:

CREATE TABLE `browser_detects` (
  `id` int(11) NOT NULL auto_increment,
  `session` varchar(255) NOT NULL default '',
  `user_id` int(11) NOT NULL default '0',
  `browser` varchar(255) NOT NULL default '',
  `version` varchar(255) NOT NULL default '',
  `os` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `sessionUnique` (`session`)
)

PHP 代码:

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $session = session_id();
    $user_id = isset($user_id) ? $user_id ? 0;
    $browser = isset($_POST['browser']) ? $_POST['browser'] ? '';
    $version = isset($_POST['version']) ? $_POST['version'] ? '';
    $os = isset($_POST['os']) ? $_POST['os'] ? '';
    $q = $conn->prepare('INSERT INTO browser_detects (`session`, `user`, `browser`, `version`, `os`) VALUES (:session :user, :browser, :version, :os)');
    $q->execute(array(
                    ':session' => $session,
                    ':user' => $user_id,
                    ':browser' => $browser,
                    ':version' => $version,
                    ':os' => $os
                ));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接