「Go 工具箱」解析 http 中的 user-agent,就用這個包:user_agent

大家好,我是漁夫子。「Go 學堂」新推出 “Go 工具箱” 系列,意在給大家分享使用 go 語言編寫的、實用的、好玩的工具。

今天給大家推薦一個解析 HTTP 請求頭中 user-agent 字段的庫:user_agent 。目前騰訊藍鯨智雲配置平臺都在用這個包。

PqZvWq

一、User-Agent 是什麼

User-Agent 叫做用戶代理,是 HTTP 協議中請求頭中的一個字段值。通過該字段值可以告訴網站服務器用戶使用的什麼產品發送的 http 請求。該信息一般發送請求的產品名稱、操作系統、版本號等信息。大家熟知的瀏覽器其實就是所謂的一種用戶代理。

通過谷歌的 chrome 瀏覽器,我們可以看到 user-agent 字段值如下:user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36

user-agent 是一個文本字符串,其符合以下語法:

User-Agent: <product> / <product-version> <comment>

該語法我們可以稱之爲一個組成單元,在一個 user-agent 中可以有多個這樣的組成單元,組成單元之間用空格分隔。

一般瀏覽器的 user-agent 的格式如下:

User-Agent: Mozilla/5.0 (<system-information>) <platform> (<platform-details>) <extensions>

看起來有點跟最上面 user-agent 的通用語法不一樣。下面是 chrome 瀏覽器中一個 http 請求的真實的 user-agent 值。我們以該值爲例來分解器結構:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36

該值中我們通過 4 種顏色劃分了 4 個部分,每個部分實際上是通過空格劃分的。每個部分實際上都是符合 / 的語法的。如下:

在這個瀏覽器的實例中,每個部分又代表了不同的信息。如下:

關於瀏覽器中 UA 還有一些有趣的發展歷史,大家可以參考文末的參考鏈接。

二、User-Agent 能做什麼

2.1 根據用戶使用瀏覽器的不同,顯示不同的排版從而爲用戶提供更好的體驗。這就是我們平時看到的,用手機訪問谷歌和電腦訪問是不一樣的,這些是谷歌根據訪問者的 UA 來判斷的。

2.2 用於數據統計分析。例如可以根據 user-agent 中的信息統計來源於各平臺(PC、mobile、平板等)、用戶使用的操作系統(Android、iOS、Unix、Windows)等的數據。通過數據分析後進一步改善用戶的體驗。

當然,用戶代理不僅僅是瀏覽器,還可以是機器人、網絡爬蟲。網站服務器可以根據 user-agent 進行識別,以輸出不同的內容。

三、安裝 user-agent 包

使用 go get 進行安裝:

 go get github.com/mssola/user_agent

四、user-agent 包的基本使用

我們看下 user-agent 包的使用。使用很簡單,直接上代碼:

package main

import (
    "fmt"

    "github.com/mssola/user_agent"
)

func main() {
    // The "New" function will create a new UserAgent object and it will parse
    // the given string. If you need to parse more strings, you can re-use
    // this object and call: ua.Parse("another string")
    ua := user_agent.New("Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1")

    fmt.Printf("%v\n", ua.Mobile())   // => true
    fmt.Printf("%v\n", ua.Bot())      // => false
    fmt.Printf("%v\n", ua.Mozilla())  // => "5.0"
    fmt.Printf("%v\n", ua.Model())    // => "Nexus One"

    fmt.Printf("%v\n", ua.Platform()) // => "Linux"
    fmt.Printf("%v\n", ua.OS())       // => "Android 2.3.7"

    name, version := ua.Engine()
    fmt.Printf("%v\n", name)          // => "AppleWebKit"
    fmt.Printf("%v\n", version)       // => "533.1"

    name, version = ua.Browser()
    fmt.Printf("%v\n", name)          // => "Android"
    fmt.Printf("%v\n", version)       // => "4.0"

    
    // Let's see an example with a bot.
    ua.Parse("Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")

    fmt.Printf("%v\n", ua.Bot())      // => true

    name, version = ua.Browser()
    fmt.Printf("%v\n", name)          // => Googlebot
    fmt.Printf("%v\n", version)       // => 2.1
}

該包的實現原理本質上就是對字符串按上面的規格進行解析。但同時需要考慮各種 user-agent 中的細微差別。所以該包不僅僅是一個簡單的封裝,而是需要具有對 user-agent 在各平臺、各種場景下的深入瞭解才能做到的。

參考鏈接: 

瀏覽器 UA 的發展歷史:https://www.zhihu.com/question/306775584

瀏覽器 UA 的發展歷史(英文版):https://webaim.org/blog/user-agent-string-history/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/8YRqypiW1dQQVlZkmCd1mQ