透過用戶代理偵測瀏覽器

針對不同的瀏覽器給予不同的網頁或服務,通常不是好主意:網路的原意,是要讓所有人都能訪問,無論他們使用何種瀏覽器或何種設備。你的網站可以透過基於(瀏覽器)功能可用性的漸進增強法開發,而不是特別指定某種瀏覽器。

不過瀏覽器與標準並不是完美的,有些特殊情況依舊需要偵測瀏覽器。透過用戶代理(user agent)去偵測瀏覽器看似簡單,要做好卻頗為困難。這份文件會盡可能引導你正確處理這種事。

因為很重要所以再說一次:實行用戶代理嗅探(User Agent sniffing)通常不是好主意。你幾乎能找出更好、更通用(broadly compatible)的方法解決問題!

使用瀏覽器偵測前應當考慮什麼

在考慮透過用戶代理字串,去偵測使用瀏覽器時,首先要盡可能避免這種用法。先從認清為什麼要這麼做開始。

你正針對某瀏覽器的特定錯誤奮戰著?
去專業論壇閱讀或提問:你不太可能是第一個碰上問題的人。另外,去找專家、或只是與你有不同觀點的人問問看,也會對你的除錯思路有所幫助。如果問題看來頗為罕見,你應該去檢查這個錯誤是不是透過缺陷跟蹤管理系統(bug tracking system:MozillaWebKitOpera)報告到瀏覽器供應商。瀏覽器供應商很重視錯誤報告,相關分析也可能提示該錯誤的其他解決辦法。
你正試圖檢查某個特定功能是否存在?
你的網站需要用到某些瀏覽器不支援的功能,並給這些用戶功能更少,但你知道能正常顯示的網站。這類使用用戶代理偵測的理由非常糟糕,因為大多數的瀏覽器,最終都有可能支援該功能。在這種情況下,你應當盡可能避免用戶代理嗅探,並改用功能偵測。
你希望給不同的瀏覽器不同的 HTML?
這種作法通常不太好,不過有時候卻是必要的。在此種情況下,你首先要分析是否真該這麼做。你能藉由加入某些無語意的 <div><span> 元素避免嗎?與難以完成的用戶代理偵測比起來,HTML 整潔性的稍稍降低變得相當值得。另外,請重新構思你的設計:你能藉由漸進增強或是流動排版(fluid layouts)來消除用戶代理偵測的需求嗎?

避免用戶代理偵測

如果你想免用戶代理偵測,針對個別情況會有一些選項!

功能偵測
功能偵測使你無須弄清是哪種瀏覽器在渲染你的網頁,只須檢查需要的具體功能是否能用。如果不能用,就採取備用方案。不過,在極少數真需探測瀏覽器的情況下,絕對不要用功能偵測判斷。因為其他瀏覽器可能會用其他方法導入,從而令衍生的錯誤,變得相當難以追蹤與修復。
漸進增強(Progressive Enhancement)
此設計技術與網站開發的「層次」有關:它運用下而上的途徑、從簡單的層次開始,透過一連串的層次,漸漸增強網站的能力。
優雅降級(Graceful degradation)
這種由上而下的途徑,是先在建造網站時,就用上所有需要的功能,再調整到令舊版瀏覽器也能執行。這種途徑與漸進增強相比,難度更高、效率也更糟,不過在某些情況下也可能更管用。

你想找到用戶代理的哪個資訊

因為用戶代理字串的差異處並沒有統一,這方面會頗為棘手。

瀏覽器名稱

當別人說要「偵測瀏覽器」的時候,他們通常要的是「偵測排版引擎」:你真的要偵測到用戶在使用 Firefox 抑或相對應的 SeaMonkey,或偵測到在使用 Chrome 抑或相對應的 Chromium 嗎?還是說只要偵測瀏覽器用的是 Gecko 或是 WebKit 排版引擎?如果你要的是後者,請直接看後面的章節。

雖然有 Internet Explorer 這個明顯的例外,多數瀏覽器通常會把瀏覽器名字與版本用成 BrowserName/VersionNumber瀏覽器名/版本名)格式。然而,因為用戶代理不是只有瀏覽器名提供這種格式,你不能找到瀏覽器的名字,你只能檢查該名字是否為你要尋找的目標。也請注意瀏覽器還會「造假」:例如 Chrome 就會同時宣稱自己是 Chrome 與 Safari。因此,如果要找出 Safari 瀏覽器,你就要在找出 Safari 字串的同時,排除掉 Chrome 字串。此外,Chromium 也常常宣稱自己是 Chrome、而 Seamonkey 有時也會宣稱自己是 Firefox。

另請注意,不要針對 BrowserName 使用簡單的正規表達式,因為用戶代理可能有不是 Keyword/Value 的字串。例如 Safari 與 Chrome 在字串內就包含了 like Gecko(類似 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 token,另一個則是偏向用戶友好的 Version/xyz token
Opera

OPR/xyz [1]

Opera/xyz [2]

 

[1] Opera 15+ (Blink-based engine)

[2] Opera 12- (Presto-based engine)

Internet Explorer ; MSIE xyz;   Internet Explorer 並不使用 BrowserName/VersionNumber 格式

當然,這裡不保證沒有其他瀏覽器,騎劫其他瀏覽器的可能,例如過去的 Chrome 就騎劫過 Safari。這也是為什麼透過用戶代理字串來探測瀏覽器是靠不住的,它也只能用在探測版本號(不太可能有騎劫過去版本號的情形)。

瀏覽器版本

瀏覽器版本通常,但不是每次,都把數值放在用戶代理字串的 BrowserName/VersionNumber token。把版本號放在 MSIE 之後的 Internet Explorer、還有加了 Version/VersionNumber token 的第十代以後 Opera 版本就是明顯的例子。

再次強調,因為無法確保尋找的瀏覽器會包含有效的數字,請確認你針對的瀏覽器,選取了正確的 token。

排版引擎

如同前述,多數情況下,找尋排版引擎(rendering engine)更為恰當。這能讓少有人知的瀏覽器,不致遭到排除在外。使用某一種排版引擎的瀏覽器,共享相同的網頁瀏覽:這種「一處有效、處處有效」的假設,是很公平的。

目前有五大主流的排版引擎:Trident, Gecko, Presto, Blink 與 WebKit。因為排版引擎嗅探頗為常見,許多用戶代理也會加入其他的排版引擎,以觸發探測。所以在偵測排版引擎的時候,當心別錯誤觸發。

  絕對有  
Gecko Gecko/xyz  
WebKit AppleWebKit/xyz 請注意 WebKit 瀏覽器會加上「like Gecko」字串。如果探測不加留意,就會錯誤觸發針對 Gecko 的情形。
Presto Opera/xyz 注意:Presto 在 Opera15 以後不再使用(請參見 Blink)
Trident Trident/xyz Internet Explorer 把這個 token 放在 User Agent String 的 comment(註解)部份
Blink Chrome/xyz  

排版引擎版本

除了 Gecko 這個著名的例外,多數排版引擎版本的 token 通常會是 RenderingEngine/VersionNumber(排版引擎/版本號)。Gecko 把版本號放在用戶代理內,位於 rv: 字串後的註解部份。但在 Gecko 14(攜帶版)或 Gecko 17(桌面版)以後,版本號也出現在 Gecko/version token 裡面(之前的版本則是寫建置日期、固定的日期則呼叫 GeckoTrail)。

作業系統

大多數的用戶代理都會表明自己固定字符串在個作業系統上運行(儘管如 Firefox OS 這種以網路為中心的平台並沒有這樣做),不過格式的差異卻頗大。它是個固定字串,位於用戶代理註解部份的兩個分號間。對每個瀏覽器而言。這些字串是特定的。這些字串給出了作業系統、通常也給出他們的版本以及在哪個設備上運作(32位元或64位元、抑或 Mac 的 Intel/PPC)。

如同其他個案,這些字串可能在未來會有所變動,one should use them only in conjunction for the detection of already released browsers. A technological survey must be in place to adapt the script when new browser versions are coming out.

手機、平板、桌機

最常實行用戶代理嗅探的理由,是判別瀏覽器是在哪個設備執行。這麼做的目的是提供不同類型的 HTML 內容給不同類型的上網設備。

  • 絕對不要假設某個瀏覽器或排版引擎,只在某種類型的設備執行。更不要對不同的瀏覽器或排版引擎,給予不同的預設值。
  • 也絕對不要用 OS token 來定義該瀏覽器在手機、平板、抑或桌機上執行。作業系統可能在不只一種設備運作。例如,Android 可以在手機、也可以在平板上運作。

以下表格概括了主要的瀏覽器製造者,如何表明它們的瀏覽器在手機上運作:

主要瀏覽器的用戶代理字串
瀏覽器 規則 示例
Mozilla (Gecko, Firefox) 註解內的 MobileTablet token Mozilla/5.0 (Android; Mobile; rv:13.0) Gecko/13.0 Firefox/13.0
WebKit-based (Android, Safari) 註解外的 Mobile Safari token 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 token 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 token (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」了。針對這種情形,你應該提供桌面版網站。另外,因為最近桌面設備的觸控螢幕越來越多,為了提供最佳習慣,網站應該支援觸控輸入。

文件標籤與貢獻者

 此頁面的貢獻者: jwhitlock, iigmir
 最近更新: jwhitlock,