雜記 › 技術筆記 › 伺服器日誌裡那串 User-Agent,哪幾個欄位是自己填的

伺服器日誌裡那串 User-Agent,哪幾個欄位是自己填的

引號之間那一段,是客戶端自己寫的

有次翻 Nginx 的 access.log,想確認反覆來取介面的到底是誰:搜尋引擎的蜘蛛、微信內建瀏覽器裡的真人,還是拿腳本把自己寫成 Chrome 的人。證據只有引號之間那段 User-Agent,而它是客戶端自己拼出來、原樣發上來的——「像 Chrome」和「是 Chrome」是兩個命題:前者查字面,後者要字面以外的東西。

先擺尺度:8 條樣本最長 274 字元、最短 curl/8.5.0 的 10 字元,合計 935。段落數量與順序全由發出去那一端決定。

Chrome / Win 111 字元 Edge / Win 125 字元 Safari / Mac 117 字元 Firefox / Win 80 字元 iPhone Safari 135 字元 安卓微信 274 字元 百度蜘蛛 83 字元 curl 命令列 10 字元

圖 1|8 條樣本的字元數,長條按字元數等比。

六個維度各讀哪一段,值從哪張表來

維度值從哪裡來讀不到時顯示
瀏覽器 / 客戶端BROWSERS 32 條由上而下取首個命中未識別
渲染核心獨立一條鏈:Trident、Edge、Chromium 裸子串、Gecko—(非瀏覽器 UA)
作業系統Windows NT 對照表 7 條命中—(無法判斷)
裝置類型iPad、iPhone、是否帶 Mobile,再問爬蟲—(無法判斷)
CPU 架構Intel Mac 優先,arm64 對 x64,WOW64 另判—(未宣告)
語言環境8 條裡只有安卓微信給出 zh-cn其餘 7 條 —(未宣告)

安卓微信那條同時有 AppleWebKit/537.36 與 MicroMessenger/8.0.40.2420,客戶端給 微信(內建瀏覽器) 8.0.40.2420,核心卻給 Blink(Chromium 核心) / 537.36;Safari/Mac 是 WebKit(Safari 核心) / 605.1.15,兩根軸各判各的。

同一條字串,位次決定它變成誰

  • MicroMessenger 排第 1 條,安卓微信那條裡的 Chrome/77.0.3969.139 輪不到。
  • Edg 第 13 條早於舊版 Edge 第 14 條;Chrome 第 28 條、Firefox 第 30 條、Safari 第 31 條。
  • 爬蟲表 21 條,後備那條排在具名蜘蛛與程式庫之後。
  • 程式庫也走爬蟲表:curl/8.5.0 第 13 條、python-requests/2.31.0 第 15 條。
安卓微信 第 1 條 Edge 第 13 條 舊版 Edge 第 14 條 Chrome 第 28 條 Firefox 第 30 條 Safari 第 31 條

圖 2|瀏覽器表 32 條裡各類客戶端的命中位次,長條按位次等比。

爬蟲那側優先級更高:先跑 detectBot,有回傳就不看瀏覽器表。偽造那條 compatible; Spybot/1.0 夾著合法的 Chrome/131.0.0.0,本可命中第 28 條,卡片卻寫 自動化程式 / 爬蟲、主版本號 bot——命中 21 條裡最後的後備 /(bot|spider|crawler|fetcher|httpclient)\b/i。只寫 compatible; GenericClient/1.0 時後備不響,回落 Chrome 131.0.0.0,作業系統與裝置都是 —(無法判斷)。

核心欄為什麼會自己冒出 Blink

detectEngine 的 Chromium 分支是 /Edg|OPR|Vivaldi|Chrome|CriOS|Chromium/ 裸子串,沒有 i 修飾符。小寫因此不算:3 條只含 pledge、edgeless、knowledge-sync 的 UA 被它命中的條數是 0,最後那條照報 Gecko 132.0。

大寫就中招:4 條含大寫子串的自建 UA 被改判的條數正是 4——機型名 OPRO-X、裝置名 Chromecast、EdgeSync-Agent/2.0 全報成 Blink(Chromium 核心)且版本為空;一條 Firefox 128.0 只因尾部多了 MicrosoftEdgeRuntime 就從 Gecko 變 Blink,第 5 條真 Edge 對照一致。「核心有名稱、版本為空」就是訊號。

版本號裡那些底線是誰換掉的

iOS 捕獲 17_4 換成小數點後顯示 iOS 17.4,macOS 的 10_15_7 顯示 10.15.7。Windows 那張對照表只有 7 條命中,10.0 對 Windows 10 / 11 直到 5.2 對 Windows Server 2003,取不到就回落「較舊版本」:NT 11.0、6.4、5.0 都算較舊版本,真 Windows 11 走的反而是 10.0。微信 8.0.40.2420 的 4 段全保留,(0x28002837) 不參與版本;rv:132.0 優先於 20100101。

第三張表只解釋字面,不下結論

TOKENS 34 條只說明每段是什麼意思。對 125 字元那條 Edge/Win 做高亮,命中 9 個片段,25 條沒匹配上或被區間重疊去掉。兩條註解回答開頭:Mozilla/5.0「幾乎所有瀏覽器都固定寫 5.0,不代表瀏覽器品牌」,(KHTML, like Gecko) 是「WebKit 的偽裝宣告」。這 34 條我背不下來,通常把整列丟進User-Agent 解析逐段標出來。

「到底是誰」這一欄答不了。要把蜘蛛和偽裝者分開,得拿同一列日誌裡的 IP 去對歸屬地與反向解析,IP 歸屬地查詢給的機房線索才回答「這台機器有沒有可能是百度出口」。範本裡 Sec-CH 與 Client Hints 各出現 0 次,所以凍結在 108.0.0.0 的精簡版只能讀成 Chrome 108.0.0.0;尾部掛著編碼過的一段,先按 Base64 編解碼解一遍。

Q:UA 能不能偽造?

能,不需要技巧——那串字元本來就是客戶端拼的。有爬蟲關鍵詞就落到 自動化程式 / 爬蟲,沒有就回落 Chrome 131.0.0.0。它讀字面不讀來源,只靠這一欄做存取控制都能被繞過。

Q:為什麼 Chrome 的 UA 裡寫著 Safari?

相容遺留。Chromium 系結尾都帶一段 Safari/537.36,註解寫著「Chromium 結尾也帶一段,是相容遺留」。核心那欄不看名稱,Chrome、Edge、安卓微信都報 Blink(Chromium 核心) / 537.36。

Q:辨識爬蟲和封鎖爬蟲是一回事嗎?

不是。21 條爬蟲表只回答「這串字元像不像爬蟲」,第 21 條是 bot、spider、crawler、fetcher、httpclient 的泛化匹配;取捨靠 IP 與反向解析。寫成 Googlebot 的腳本照樣被認成蜘蛛。

Q:頁面說明裡的微信版本為什麼和卡片不一樣?

程式碼捕獲 8.0.40.2420 這 4 段,卡片就顯示它;工具說明裡的 MicroMessenger/8.0.40 少了一段。同一份說明還提小程式,而範本裡 miniProgram 出現 0 次,那條 UA 只是被讀成 微信(內建瀏覽器)8.0.44。

📎 相關文章

PNG 壓了三遍只減 426 位元組:無損壓縮的真實邊界 2026-10-22 WebP 轉 PNG 後體積漲了幾倍:什麼時候必須轉,怎麼把漲幅壓住 2026-10-22 截圖縮到四分之一,小字糊成一團的三種原因 2026-10-22 同樣裁 300×300,頭像為什麼總偏右下角半格 2026-10-22 按每月 1.7 倍預估 18 個月,腳本和表格為什麼給出兩個數 2026-10-22