ShowMeBug 中如何科學的識別用戶瀏覽器?

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"經常有用戶在 ShowMeBug 在線面試過程中,使用一些奇怪的瀏覽器來打開鏈接進行視頻面試,然後出現一些音視頻卡頓等問題。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"多次排查後發現產品的音視頻功能一但使用了瀏覽器的 WebRTC 特性,就會對瀏覽器的要求特別高,如不在正常的瀏覽器支持範圍內,就容易出現問題。所以我們在檢測這個問題時,通常有兩種方法識別出瀏覽器的型號和版本。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第一種方法:使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"modernizr","attrs":{}}],"attrs":{}},{"type":"text","text":" 來進行 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"feature detection","attrs":{}}],"attrs":{}},{"type":"text","text":", 通過探測這些 API 是否存在,來判讀是否可以使用 WebRTC,畢竟 WebRTC 是有瀏覽器 API 組成。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不過,這種方法不夠嚴謹,WebRTC 是一項很新的技術,今年 1 月份才正式成爲官方標準,但目前只支持部份瀏覽器,穩定性也還需要進一步加強。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"The World Wide Web Consortium (W3C) and the Internet Engineering Task Force (IETF) announced today that Web Real-Time Communications (WebRTC), which powers myriad services, is now an official standard, bringing audio and video communications anywhere on the Web.","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"今年 1 月,W3C 和 IETF 宣佈,爲無數服務提供支持的 WebRTC 現已成爲官方標準。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"———— 2021.01.26","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.w3.org/2021/01/pressrelease-webrtc-rec.html","title":"","type":null},"content":[{"type":"text","text":"網絡實時通信 (WebRTC) 改變了通信格局;成爲萬維網聯盟 (W3C) 建議書和多個互聯網工程任務組 (IETF) 標準","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"顯然,feature detection 不符合我們的應用場景,目前不滿足我們的需求,所以此方法 pass。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第二種方法,也是我們目前採用的,業內比較通用的辦法就是檢測 User-Agent。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"curl http://202.38.95.46:12001/ -H \"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) HEICORE/49.1.2623.213 Safari/537.36\"\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"User-Agent 是什麼","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶不能直接去互聯網上獲取信息,需要一個軟件作爲載體去代表用戶的行爲,這個軟件就是 User-Agent (用戶代理),瀏覽器就是一種典型的 User-Agent 。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶使用不同的軟件去用統一的協議去做相同的事情。這也是定義在 http 請求裏的,每一條 http 請求一定會攜帶 User-Agent 頭 。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"網站的服務者可以通過 User-Agent 頭來判斷用戶使用了什麼瀏覽器,當然也可以根據 User-Agent 的內容來提供差異化的服務。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"標準語法和歷史","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原本 User-Agent 瀏覽器的語法是很清晰的","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"User-Agent: / ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent","title":"","type":null},"content":[{"type":"text","text":"User-Agent - HTTP | MDN","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲可以根據 User-Agent 的內容來提供差異化的服務,所以當年在瀏覽器大戰時期,瀏覽器的實現各不相同。當年 Mozilla (Firefox 的前身)瀏覽器最強的,很多網站都只對 Mozilla 提供高質量的服務,後來有人把自己僞裝成了 Mozilla (沒錯,就是 IE 先開始的)。從此 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Mozilla/5.0","attrs":{}}],"attrs":{}},{"type":"text","text":" 就變成了 User-Agent 的第一段。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://webaim.org/blog/user-agent-string-history/","title":"","type":null},"content":[{"type":"text","text":"History of the browser user-agent string","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"後來的瀏覽就在這上面不斷擴充,就像今天這樣:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Linux / Firefox","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Mac OS / Safari","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Safari/605.1.15","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Chromium OS / Chrome","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"Mozilla/5.0 (X11; CrOS x86_64 13904.16.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.25 Safari/537.36","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Windows / Edge","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4482.0 Safari/537.36 Edg/92.0.874.0","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這就變成了去識別 User-Agent 變得很困難,目前的識別基本上都是使用正則表達式,配合自己的 User-Agent 庫來判斷。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這方面的庫有很多,對比很多後,這個庫是比較全的 ","attrs":{}},{"type":"link","attrs":{"href":"https://www.npmjs.com/package/ua-parser-js","title":"","type":null},"content":[{"type":"text","text":"ua-parser-js","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"目前幾乎所有的網站識別瀏覽器都是 User-Agent 來判斷,有兩個接口:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前端有瀏覽器接口:","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"window.navigator.userAgent","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"後端可以通過瀏覽器的 http request header 來拿到 User-Agent","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如何使用 User-Agent在移動端因爲算力的問題,在有些老舊的處理器上也會出現卡頓的情況,不過,我們可以在瀏覽器裏跑一下 Benchmark 來判斷算力是否夠用,移動端的 User-Agent 會攜帶處理器信息(可以去查數據庫來判斷)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以說,目前所進行的操作是:","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"檢測用戶瀏覽器 ——> 給予提示,並在文檔頁顯示支持性列表","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最後,要通過定義的規則生成這樣一個表格:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/11/1112132c5ccd5d3246c8be19d152806d.png","alt":"browser-list","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了降低未來的維護成本要使用一套數據源,既可以檢測,又可以在文檔頁生成列表","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"ua-parser-js","attrs":{}}],"attrs":{}},{"type":"text","text":" 的返回結果的數據結構比較科學,直接複用這一數據結構","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"interface Result {\n ua: string;\n browser: {\n name: string | undefined;\n version: string | undefined;\n };\n device: {\n model: string | undefined;\n type: string | undefined;\n vendor: string | undefined;\n };\n engine: {\n name: string | undefined;\n version: string | undefined;\n };\n os: {\n name: string | undefined;\n version: string | undefined;\n };\n cpu: {\n architecture: string | undefined;\n };\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這樣我們可以定義三條規則:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"daily_list","attrs":{}}],"attrs":{}},{"type":"text","text":" (某個測試版的瀏覽器)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"white_list","attrs":{}}],"attrs":{}},{"type":"text","text":" (測試過沒有問題的瀏覽器)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"black_list","attrs":{}}],"attrs":{}},{"type":"text","text":" (已知有問題的瀏覽器)","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"// 存在優先級關係: daily_list > white_list > black_list\n//\n// https://www.npmjs.com/package/ua-parser-js\n// @params: ua-parser-js.result\n// @params: { : }\n// @return: string(list_name)\nfunction browserDetect(ua, list) {\n const { daily_list, white_list, black_list } = list\n if (checkList(ua, daily_list)) return 'daily_list'\n if (checkList(ua, white_list)) return 'white_list'\n if (checkList(ua, black_list)) return 'black_list'\n return ''\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基於這種數據結構,加入一種簡單的語法。支持版本號判斷,加入這個幾種符號的支持:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":">","attrs":{}}],"attrs":{}},{"type":"text","text":", ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"≥","attrs":{}}],"attrs":{}},{"type":"text","text":", ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"=","attrs":{}}],"attrs":{}},{"type":"text","text":", ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"= 85.0.0.0\"\n - browser:\n name: \"Firefox\"\n version: \">= 85.0.0.0\"\n - browser:\n name: \"Edge\"\n version: \">= 45.0.0.0\"\n device:\n type: \"mobile\"\n os:\n name: \"Android\"\n version: \">= 10.0\"\n\nblack_list:\n # 老版本的 Edge 不支持\n - browser:\n name: \"Edge\"\n version: \"< 80.0.0.0\"\n os:\n name: \"Windows\"\n\n # 手機微信內置瀏覽器\n - browser:\n name: \"WeChat\"\n device:\n type: \"mobile\"\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用我們產品的用戶,上至自己編譯瀏覽器自己用的極客,下至用微信內置瀏覽器的小白, 所以要在 beta 版、dev 版、canary 開發版、nightly 版等各種版本中給予提示,檢測 WebRTC 不穩定,就可能會有問題。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"曾經有人用了開發版的瀏覽器,面試中出現音視頻不穩定,直到他更新了的版本之後才恢復正常。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於開發版瀏覽器並不會在 ua 裏面攜帶 dev 的標識,只能通過版本號來判斷。可以使用 caniuse-lite 的數據庫,取出最新穩定版的的版本號,然後進行版本號比對。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是 caniuse-lite 的數據庫有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"1.3M","attrs":{}}],"attrs":{}},{"type":"text","text":" 如果直接使用,會打包整個數據庫。這個體積的增加了太多,需要優化一下,所以採用把查詢結果打包成文件的辦法,實際上真正有用的數據非常的少。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"創建一個生成器,可以動態創建這個文件 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"latest_browser_list_generator.js","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"#!/usr/bin/env node\n\nconst browserslist = require('browserslist')\nconst fs = require('fs')\n\nconst list = {\n 'firefox': true,\n 'chrome': true,\n 'edge': true,\n}\n\nconst latest = browserslist(\"last 1 version\").filter(i => list[i.split(' ')[0]])\nfs.writeFileSync('latest_browser_list.js', `export default ${JSON.stringify(latest)}`)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"之後定期執行這兩個就可以了","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"npx browserslist@latest --update-db","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"node latest_browser_list_generator.js","attrs":{}}],"attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當然,這個可以用 GitHub action 或 GitLab CI 來每週執行一次","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"除此之外,360 瀏覽器的檢測方法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"360 瀏覽器隱藏了自己的 UA 。360 瀏覽器只有在訪問自己的網站(比如:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"360.cn","attrs":{}}],"attrs":{}},{"type":"text","text":")是纔會在 UA 裏攜帶 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"QIHU 360SE","attrs":{}}],"attrs":{}},{"type":"text","text":" (360 安全瀏覽器)或 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"QIHU 360EE","attrs":{}}],"attrs":{}},{"type":"text","text":" (360 極速瀏覽器)字段","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.v2ex.com/t/425627","title":"","type":null},"content":[{"type":"text","text":"360 安全瀏覽器和 360 極速瀏覽器的判斷","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對待國內瀏覽器(這個可以檢測到 360)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://github.com/mumuy/browser","title":"","type":null},"content":[{"type":"text","text":"GitHub - mumuy/browser: Useragent analysis tool.瀏覽器分析判斷工具 - 用戶代理、操作系統信息","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不過這個庫的作者並沒有提供可以直接使用包,只能把核心代碼提取出來。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":" // https://github.com/mumuy/browser/blob/4a50ee18cc76a5013dea3596bb33fbab9ed584c3/Browser.js#L111-L143\n if (_window.chrome) {\n let chrome_version = u.replace(/^.*Chrome\\/([\\d]+).*$/, '$1')\n if (_window.chrome.adblock2345 || _window.chrome.common2345) {\n match['2345Explorer'] = true\n } else if (\n _mime('type', 'application/360softmgrplugin') ||\n _mime('type', 'application/mozilla-npqihooquicklogin')\n ) {\n is360 = true\n } else if (chrome_version > 36 && _window.showModalDialog) {\n is360 = true\n } else if (chrome_version > 45) {\n is360 = _mime('type', 'application/vnd.chromium.remoting-viewer')\n if (!is360 && chrome_version >= 69) {\n is360 = _mime('type', 'application/hwepass2001.installepass2001') || _mime('type', 'application/asx')\n }\n }\n }\n\n // 修正\n if (match['Mobile']) {\n match['Mobile'] = !(u.indexOf('iPad') > -1)\n } else if (is360) {\n if (_mime('type', 'application/gameplugin')) {\n match['360SE'] = true\n } else if (\n _navigator &&\n typeof _navigator['connection'] !== 'undefined' &&\n typeof _navigator['connection']['saveData'] == 'undefined'\n ) {\n match['360SE'] = true\n } else {\n match['360EE'] = true\n }\n }\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不過這裏要注意:","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"navigator.mimeTypes","attrs":{}}],"attrs":{}},{"type":"text","text":" 已經從 Web 標準中移除(也許未來的某天這個方法就沒法用了)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://developer.mozilla.org/en-US/docs/Web/API/Navigator/mimeTypes","title":"","type":null},"content":[{"type":"text","text":"Navigator.mimeTypes - Web APIs | MDN","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"判斷 360 的版本,是做了一個版本的對應關係","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"// https://github.com/mumuy/browser/blob/4a50ee18cc76a5013dea3596bb33fbab9ed584c3/Browser.js#L283-L292\nfunction get360SEVersion(u) {\n let hash = { '86': '13.0', '78': '12.0', '69': '11.0', '63': '10.0', '55': '9.1', '45': '8.1', '42': '8.0', '31': '7.0', '21': '6.3' }\n let chrome_version = u.replace(/^.*Chrome\\/([\\d]+).*$/, '$1')\n return hash[chrome_version] || ''\n}\nfunction get360EEVersion(u) {\n let hash = { '86': '13.0', '78': '12.0', '69': '11.0', '63': '9.5', '55': '9.0', '50': '8.7', '30': '7.5' }\n let chrome_version = u.replace(/^.*Chrome\\/([\\d]+).*$/, '$1')\n return hash[chrome_version] || ''\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"最後","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"雖然我們分享瞭如何科學識別檢測用戶瀏覽器的方法,但是爲了網絡環境的健康,爲了不重蹈瀏覽器大戰時的覆轍,呼籲大家不要針對特定瀏覽器提供差異化內容。","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章