🧑 博主簡介:CSDN博客專家,歷代文學網(PC端可以訪問:https://literature.sinhy.com/#/?__c=1000,移動端可微信小程序搜索“歷代文學”)總架構師,
15年
工作經驗,精通Java編程
,高并發設計
,Springboot和微服務
,熟悉Linux
,ESXI虛擬化
以及云原生Docker和K8s
,熱衷于探索科技的邊界,并將理論知識轉化為實際應用。保持對新技術的好奇心,樂于分享所學,希望通過我的實踐經歷和見解,啟發他人的創新思維。在這里,我希望能與志同道合的朋友交流探討,共同進步,一起在技術的世界里不斷學習成長。
技術合作請加本人wx(注明來自csdn):foreast_sea
------
爬蟲的精準識別:基于 User-Agent 的正則實現
引言
在當今實時交互場景中,WebSocket 技術已成為在線客服、即時通訊、實時數據推送等服務的核心支柱。然而,一個看似簡單的技術細節卻可能讓企業付出高昂的代價:當爬蟲機器人偽裝成“用戶”接入 WebSocket 時,客服系統可能誤將其識別為真實客戶,導致客服資源被無意義消耗,甚至因“無響應對話”而影響用戶體驗。
場景痛點:當技術便利遭遇“無效流量”
想象一個典型的在線客服場景:用戶訪問網站后,通過 WebSocket
與客服實時溝通。然而,大量爬蟲(如搜索引擎索引、SEO
工具、惡意掃描程序)的請求也會觸發 WebSocket
連接。這些爬蟲不會主動發送消息,卻會長期占用連接資源。客服人員看到“在線用戶”列表中的爬蟲會話,嘗試對話卻得不到任何回應,最終導致:
- 資源浪費:服務器帶寬、連接數被無效占用。
- 效率下降:客服需要手動排查“沉默用戶”,增加工作負擔。
- 數據污染:統計報表中的“用戶活躍數”被虛假流量污染。
更糟糕的是,部分攻擊者會利用 WebSocket
的長連接特性,發起高頻請求或注入攻擊,進一步威脅系統安全。
傳統方案的局限性
許多開發者試圖通過簡單的 IP 封禁 或 請求頻率限制 解決問題,但爬蟲的 IP 池和訪問策略日益動態化,傳統方案往往力不從心。而直接依賴 User-Agent 字符串過濾 看似直接,卻常因正則表達式設計不當(如漏判新爬蟲、誤傷正常用戶)導致效果大打折扣。
本文目標
本文將聚焦 “如何在 WebSocket 握手階段精準識別爬蟲”,通過以下實踐方案實現高效攔截:
- 多維度 User-Agent 檢測:基于正則表達式覆蓋 95% 的已知爬蟲標識,確保關鍵詞精準匹配。
- 輕量化瀏覽器端攔截:提供 JavaScript 正則方案,避免爬蟲觸發前端資源加載。
- 服務端兜底邏輯:結合 IP 黑名單與行為分析,應對偽造 User-Agent 的高級爬蟲。
文章將深入解析正則表達式設計技巧、跨語言(Java/JavaScript)實現方案,并探討如何在開源數據集(如 crawler-user-agents)基礎上動態更新策略。無論您是構建客服系統的開發者,還是需優化實時服務性能的架構師,均可通過本文獲得可直接復用的代碼與實踐經驗。
以下是基于常見爬蟲和機器人的 User-Agent
關鍵詞整理的正則表達式實現方案:
1. 常見爬蟲 User-Agent 關鍵詞
以下關鍵詞覆蓋了主流搜索引擎、SEO 工具、社交媒體、監控服務等類型的爬蟲機器人:
關鍵詞(不區分大小寫) | 示例爬蟲名稱 |
---|---|
bot | Googlebot, Bingbot |
spider | YandexSpider, Baiduspider |
crawler | AhrefsBot, SemrushBot |
slurp | Yahoo! Slurp |
facebookexternalhit | Facebook 鏈接預覽機器人 |
duckduckbot | DuckDuckGo 爬蟲 |
facebot | Facebook 爬蟲 |
alexa | Amazon 的 Alexa 爬蟲 |
applebot | Apple 的搜索引擎爬蟲 |
pinterest | Pinterest 爬蟲 |
twitterbot | Twitter 爬蟲 |
linkedinbot | LinkedIn 爬蟲 |
telegrambot | Telegram 爬蟲 |
uptimerobot | UptimeRobot 監控服務 |
exabot | Exalead 搜索引擎 |
msnbot | MSN 搜索引擎爬蟲 |
yahoo | Yahoo 爬蟲 |
2. 正則表達式實現
以下正則表達式會匹配包含上述關鍵詞的 User-Agent(不區分大小寫):
String pattern = "(?i).*\\b(bot|spider|crawler|slurp|facebookexternalhit|duckduckbot|facebot|alexa|applebot|pinterest|twitterbot|linkedinbot|telegrambot|uptimerobot|exabot|msnbot|yahoo|googlebot|bingbot|yandexbot|baiduspider|ahrefsbot|semrushbot)\\b.*";
3. 正則關鍵表達式說明
3.1 (?i)
:忽略大小寫的標記
- 作用:表示后續的正則匹配不區分大小寫。
- 原理:
(?i)
是正則表達式的 模式修飾符(Pattern Modifier),它會從當前位置開始,對整個表達式生效。 - 示例:
(?i)bot → 可以匹配 "Bot", "BOT", "bOt" 等任意大小寫組合
3.2 \\b
: 單詞邊界
- 作用:表示 單詞邊界(Word Boundary),確保匹配的是一個完整的單詞(而不是單詞的一部分)。
- 原理:
\\b
會匹配一個位置,該位置的一側是單詞字符(字母、數字、下劃線),另一側是非單詞字符(如空格、標點或字符串邊界)。 - 示例:
\\bbot\\b → 匹配 "bot" 但不會匹配 "robot" 或 "bots"
3.3 組合后的效果:(?i).*\\b(bot|spider)\\b.*
假設原始正則表達式為:
String pattern = "(?i).*\\b(bot|spider)\\b.*";
3.3.1 匹配邏輯
(?i)
→ 忽略大小寫。.*
→ 允許目標關鍵詞出現在 任意位置(如開頭、中間、結尾)。\\b
→ 確保關鍵詞是完整單詞(避免部分匹配,如robot
中的bot
)。(bot|spider)
→ 匹配 “bot” 或 “spider”。- 最后的
.*
→ 允許關鍵詞后有其他字符。
3.3.2 示例匹配的 User-Agent
"Googlebot/2.1"
→ 匹配bot
"YandexSpider"
→ 匹配spider
"BingPreviewBot"
→ 匹配bot
3.3.3 不匹配的 User-Agent
"Robot/1.0"
→\\bbot\\b
不會匹配 “Robot” 中的 “bot”"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
→ 不含關鍵詞
4. Java 代碼實現
import java.util.regex.Pattern;public class CrawlerDetector {private static final String BOT_PATTERN = "(?i).*\\b(bot|spider|crawler|slurp|facebookexternalhit|duckduckbot|facebot|alexa|applebot|pinterest|twitterbot|linkedinbot|telegrambot|uptimerobot|exabot|msnbot|yahoo|googlebot|bingbot|yandexbot|baiduspider|ahrefsbot|semrushbot)\\b.*";private static final Pattern pattern = Pattern.compile(BOT_PATTERN);public static boolean isCrawler(String userAgent) {if (userAgent == null || userAgent.trim().isEmpty()) {return false;}return pattern.matcher(userAgent).matches();}
}
4.1 java 使用示例
public static void main(String[] args) {String userAgent1 = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";String userAgent2 = "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1";System.out.println("Is crawler 1? " + CrawlerDetector.isCrawler(userAgent1)); // trueSystem.out.println("Is crawler 2? " + CrawlerDetector.isCrawler(userAgent2)); // false
}
5. JS 代碼實現
以下是 JavaScript 版本的正則表達式實現(適配瀏覽器環境):
5.1 JavaScript 正則表達式
const crawlerRegex = /\b(bot|spider|crawler|slurp|facebookexternalhit|duckduckbot|facebot|alexa|applebot|pinterest|twitterbot|linkedinbot|telegrambot|uptimerobot|exabot|msnbot|yahoo|googlebot|bingbot|yandexbot|baiduspider|ahrefsbot|semrushbot)\b/i;
5.2 實現解析
5.2.1 正則結構
\b
:匹配單詞邊界(確保關鍵詞是完整單詞,避免誤匹配類似robot
中的bot
)。(bot|spider|...)
:匹配列表中的任意關鍵詞。i
標志:忽略大小寫(替代 Java 的(?i)
)。
5.2.2 瀏覽器端使用示例
// 檢測當前瀏覽器 User-Agent 是否是爬蟲
function isCrawler() {const userAgent = navigator.userAgent;return crawlerRegex.test(userAgent);
}// 調用示例
if (isCrawler()) {console.log("檢測到爬蟲,阻止 WebSocket 連接");
} else {console.log("允許連接 WebSocket");
}
5.3注意事項
-
關鍵詞動態更新
可以將正則關鍵詞提取到配置中,便于動態擴展:const botKeywords = ["bot", "spider", "crawler", "slurp", "facebookexternalhit", "duckduckbot", "facebot",// ...其他關鍵詞 ]; const crawlerRegex = new RegExp(`\\b(${botKeywords.join("|")})\\b`, "i");
-
瀏覽器兼容性
- 所有現代瀏覽器(Chrome/Firefox/Safari/Edge)均支持
RegExp
和i
標志。 - 兼容到 IE9+。
- 所有現代瀏覽器(Chrome/Firefox/Safari/Edge)均支持
5.4 完整代碼
<script>
// 定義正則表達式
const botKeywords = ["bot", "spider", "crawler", "slurp", "facebookexternalhit","duckduckbot", "facebot", "alexa", "applebot", "pinterest","twitterbot", "linkedinbot", "telegrambot", "uptimerobot","exabot", "msnbot", "yahoo", "googlebot", "bingbot","yandexbot", "baiduspider", "ahrefsbot", "semrushbot"
];
const crawlerRegex = new RegExp(`\\b(${botKeywords.join("|")})\\b`, "i");// 檢測邏輯
function isCrawler() {return crawlerRegex.test(navigator.userAgent);
}// 根據檢測結果控制 WebSocket 連接
if (!isCrawler()) {const ws = new WebSocket("wss://your-websocket-endpoint");ws.onopen = () => console.log("WebSocket 已連接");
} else {console.log("爬蟲客戶端,禁止連接 WebSocket");
}
</script>
注意事項
- 誤判風險:極少數正常瀏覽器可能包含關鍵詞(如
Bot
),但概率極低。 - 動態更新:定期更新正則中的關鍵詞列表以覆蓋新出現的爬蟲。
- 性能:正則表達式復雜度較低,適合高頻調用。
如果需要更全面的關鍵詞列表,可以參考 user-agents 等公開數據集。