使用 chromedp 高效爬取 Bing 搜索結果

在數據采集領域,搜索引擎結果是重要的信息來源。但傳統爬蟲面對現代瀏覽器渲染的頁面時,常因 JavaScript 動態加載、跳轉鏈接加密等問題束手無策。本文將詳細介紹如何使用 Go 語言的chromedp庫,模擬真實瀏覽器行為爬取 Bing 搜索結果,并破解其跳轉鏈接加密,最終獲取真實目標地址。

一、需求背景與技術選型

1.1 爬取搜索引擎結果的痛點

在嘗試獲取 Bing 搜索結果時,我們會遇到兩個核心問題:

  • 動態渲染障礙:Bing 搜索結果頁通過 JavaScript 動態加載內容,傳統基于http.Client的爬蟲無法獲取完整 DOM 結構
  • 跳轉鏈接加密:搜索結果中的鏈接并非真實地址,而是經過 Base64 編碼的 Bing 跳轉鏈接(如https://www.bing.com/ck/a?!...&u=...

1.2 為何選擇 chromedp?

chromedp是一個基于 Chrome DevTools Protocol(CDP)的 Go 語言庫,相比其他方案有明顯優勢:

  • 真實瀏覽器環境:直接控制 Chrome/Chromium 瀏覽器,完美處理 JS 動態渲染
  • 無需額外依賴:無需安裝 Selenium 或 ChromeDriver,簡化部署流程
  • 強類型 API:基于 Go 語言的類型安全特性,減少運行時錯誤
  • 靈活的上下文控制:支持頁面導航、元素等待、JS 執行等完整瀏覽器操作

二、環境準備

2.1 基礎依賴

  • Go 1.18+(推薦使用最新穩定版)
  • Chrome/Chromium 瀏覽器(確保版本與 chromedp 兼容)
  • 依賴庫安裝:
go get github.com/chromedp/chromedp

2.2 核心配置說明

在代碼初始化階段,我們需要配置瀏覽器運行參數:

opts := append(chromedp.DefaultExecAllocatorOptions[:],chromedp.Flag("ignore-certificate-errors", true), // 忽略證書錯誤chromedp.Flag("headless", true),                  // 無頭模式(生產環境推薦)
)
  • 無頭模式(headless):不顯示瀏覽器窗口,適合服務器環境運行,設為false可用于調試
  • 證書錯誤忽略:避免因 HTTPS 證書問題導致的爬取失敗

三、核心功能實現

3.1 破解 Bing 跳轉鏈接:unwrapBingURL 函數

Bing 搜索結果中的鏈接格式通常為:
https://www.bing.com/ck/a?!...&u=a1aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbQ==
其中u參數即為加密后的真實地址,解密步驟如下:

  1. 解析 URL 參數:提取u參數值
  2. 去除前綴標識:Bing 會在 Base64 字符串前添加a1前綴,需先移除
  3. Base64 URL 解碼:使用 URL 安全的 Base64 解碼算法還原真實地址

實現代碼:

func unwrapBingURL(bing string) (real string, err error) {u, err := url.Parse(bing)if err != nil {return "", err}// 提取u參數(加密的真實地址)enc := u.Query().Get("u")if enc == "" {return bing, nil // 非跳轉鏈接,直接返回}// 移除Bing添加的a1前綴if strings.HasPrefix(enc, "a1") {enc = enc[2:]}// Base64 URL解碼dst := make([]byte, base64.URLEncoding.DecodedLen(len(enc)))n, err := base64.URLEncoding.Decode(dst, []byte(enc))if err != nil {return "", err}return string(dst[:n]), nil
}

3.2 分頁爬取與去重機制

為獲取更多搜索結果并避免重復,我們設計了分頁爬取與去重邏輯:

3.2.1 分頁控制

Bing 通過first參數控制分頁(first=1為第 1 頁,first=11為第 2 頁,以此類推),實現代碼:

pageSize := 10 // 每頁預期結果數
for pageIndex := 0; len(unique) < maxResults; pageIndex++ {start := pageIndex*pageSize + 1searchURL := fmt.Sprintf("https://www.bing.com/search?q=%s&first=%d",url.QueryEscape(keyword), start)// 爬取當前頁...
}
3.2.2 結果去重

使用map存儲已獲取的真實鏈接,確保最終結果唯一:

seen := make(map[string]bool)   // 記錄已發現的鏈接
var unique []string             // 存儲去重后的真實鏈接// 去重邏輯
if !seen[real] {seen[real] = trueunique = append(unique, real)newCount++
}

3.3 頁面元素提取

通過chromedp.Evaluate執行 JavaScript 代碼,提取搜索結果中的鏈接:

var rawLinks []string
if err := chromedp.Run(ctx,chromedp.Navigate(searchURL),                  // 導航到搜索頁面chromedp.WaitVisible(`#b_content`, chromedp.ByID), // 等待結果區域加載完成chromedp.Sleep(2*time.Second),                 // 額外等待,確保JS渲染完成// 提取h2標題下的鏈接chromedp.Evaluate(`Array.from(document.querySelectorAll('#b_content h2 a')).map(a => a.href)`, &rawLinks),
); err != nil {log.Printf("第 %d 頁加載失敗: %v", pageIndex+1, err)break
}
  • WaitVisible:等待結果容器#b_content可見,避免過早提取導致數據缺失
  • Sleep 延遲:應對 Bing 的動態加載機制,確保結果完全渲染
  • JS 選擇器:通過#b_content h2 a精準定位搜索結果鏈接

四、完整代碼解析

4.1 代碼結構總覽

整個程序分為三個核心部分:

  1. unwrapBingURL:解密 Bing 跳轉鏈接
  2. main 函數初始化:配置 chromedp 上下文、初始化去重容器
  3. 分頁爬取循環:控制分頁、提取鏈接、去重存儲

4.2 關鍵細節說明

  • 上下文管理:使用defer cancel()確保資源釋放,避免內存泄漏
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
defer cancel()ctx, cancel := chromedp.NewContext(allocCtx)
defer cancel()
  • 異常處理

    • 捕獲頁面加載錯誤,避免程序崩潰
    • 過濾無效鏈接(空鏈接、Microsoft 官方鏈接)
    • 處理 Base64 解碼失敗的情況
  • 終止條件

    • 已獲取足夠數量的結果(達到maxResults
    • 當前頁無新結果(newCount == 0),說明已爬取所有結果

五、完整代碼

package mainimport ("context""encoding/base64""fmt""log""net/url""strings""time""github.com/chromedp/chromedp"
)// 從 Bing 跳轉鏈中提取真實地址
func unwrapBingURL(bing string) (real string, err error) {u, err := url.Parse(bing)if err != nil {return "", err}// 取 u= 參數enc := u.Query().Get("u")if enc == "" {return bing, nil // 不是跳轉鏈,原樣返回}// 去掉前綴if strings.HasPrefix(enc, "a1") {enc = enc[2:]}// base64 解碼dst := make([]byte, base64.URLEncoding.DecodedLen(len(enc)))n, err := base64.URLEncoding.Decode(dst, []byte(enc))if err != nil {return "", err}return string(dst[:n]), nil
}func main() {keyword := "印度大幅下調消費稅應對經濟壓力"maxResults := 100 // 你想拿多少條opts := append(chromedp.DefaultExecAllocatorOptions[:],chromedp.Flag("ignore-certificate-errors", true),chromedp.Flag("headless", true), // 調試可改 false)allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)defer cancel()ctx, cancel := chromedp.NewContext(allocCtx)defer cancel()seen := make(map[string]bool)var unique []stringpageSize := 10for pageIndex := 0; len(unique) < maxResults; pageIndex++ {start := pageIndex*pageSize + 1searchURL := fmt.Sprintf("https://www.bing.com/search?q=%s&first=%d",url.QueryEscape(keyword), start)var rawLinks []stringif err := chromedp.Run(ctx,chromedp.Navigate(searchURL),chromedp.WaitVisible(`#b_content`, chromedp.ByID),chromedp.Sleep(2*time.Second),chromedp.Evaluate(`Array.from(document.querySelectorAll('#b_content h2 a')).map(a => a.href)`, &rawLinks),); err != nil {log.Printf("第 %d 頁加載失敗: %v", pageIndex+1, err)break}newCount := 0for _, l := range rawLinks {if l == "" || strings.Contains(l, "go.microsoft.com") {continue}real, err := unwrapBingURL(l)if err != nil || real == "" {continue}if !seen[real] {seen[real] = trueunique = append(unique, real)newCount++}if len(unique) >= maxResults {break}}if newCount == 0 { // 沒新結果就停break}}fmt.Printf("共拿到 %d 條真實鏈接:\n", len(unique))for i, u := range unique {fmt.Printf("%2d. %s\n", i+1, u)}
}

六、優化建議與注意事項

6.1 性能優化

  1. 調整 Sleep 時間:2 秒等待可能過長,可根據網絡情況調整為 1-1.5 秒
  2. 并發爬取:在合規前提下,可使用chromedp的多上下文特性實現并發爬取
  3. 結果緩存:將已爬取的鏈接存儲到本地文件,避免重復爬取

6.2 反爬應對

  1. 添加隨機延遲:在分頁請求之間添加隨機延遲(1-3 秒),模擬人類操作
  2. 設置 User-Agent:在 chromedp 選項中添加真實的 User-Agent,避免被識別為爬蟲
chromedp.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36")
  1. IP 輪換:若爬取量大,建議使用代理 IP 輪換,避免 IP 被封禁

6.3 合規性提醒

  • 遵守 Robots 協議:查看 Bing 的/robots.txt文件,了解爬取限制
  • 控制爬取頻率:避免給服務器造成過大壓力
  • 尊重版權:爬取的結果僅用于合法用途,不得侵犯他人權益

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/98524.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/98524.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/98524.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

遺漏的需求

“編寫執行者的目的&#xff0c;僅用別名來表達需要傳遞的數據”&#xff0c;就如客戶信息用名字和地址表示一樣&#xff0c;這是一個很好的建議。然而&#xff0c;對程序員來說&#xff0c;這沒有提供軟件開發所必需的詳細信息。程序設計人員和用戶界面設計者需要準確地知道地…

《云原生故障診療指南:從假活到配置漂移的根治方案》

當云原生架構成為企業數字化轉型的標配,系統故障的形態也隨之發生了根本性變化。曾經那些“一目了然”的報錯信息逐漸消失,取而代之的是“指標正常卻服務不可用”“偶發故障無規律可循”等隱性問題。這些故障如同架構中的“暗物質”,看不見卻持續影響著系統的穩定性,其排查…

“從零到一:使用GitLab和Jenkins實現自動化CI/CD流水線”

GitLab倉庫 簡單的來說就是開發人員提交代碼的倉庫&#xff0c;用于團隊開發&#xff0c;GitLab 上托管的倉庫通常作為遠程倉庫使用&#xff0c;開發人員可以將本地的 Git 倉庫推送到 GitLab 上&#xff0c;也可以從 GitLab 克隆倉庫到本地進行開發。 Jenkins Jenkins 是一個開…

3D開發工具HOOPS助力造船業數字化轉型,打造更高效、更智能的船舶設計與協作!

造船業是一個高度復雜且競爭激烈的行業&#xff0c;涵蓋船體設計、結構分析、生產制造到運維管理的完整生命周期。面對龐大的CAD數據、多方協作的復雜流程以及數字化轉型的迫切需求&#xff0c;傳統工具往往顯得力不從心。 Tech Soft 3D的HOOPS SDK系列&#xff0c;正以其卓越…

Python調用MCP:無需重構,快速為現有應用注入AI與外部服務能力!

文章目錄 ?? 介紹 ?? ?? 演示環境 ?? ? MCP核心概念:AI世界的“USB-C” ? ??? MCP安裝與基礎使用 ??? ?? 安裝模塊 ?? 創建第一個MCP服務端 ?? Python中MCP客戶端的調用方案 ?? ?? 概述 ?? 深度解析 ?? 參數詳情 ?? 常用方法 ?? 不同傳輸協…

【鏈表】3.重排鏈表(medium)

重排鏈表&#xff08;medium&#xff09;題?描述&#xff1a;解法&#xff1a;算法思路&#xff1a;算法代碼&#xff1a;題?鏈接&#xff1a;143. 重排鏈表 題?描述&#xff1a; 給定?個單鏈表 L 的頭節點 head &#xff0c;單鏈表 L 表?為&#xff1a; L(0) → L(1) →…

蜜罐平臺-Hfish部署

Hfish簡介&#xff1a; HFish是一款社區型免費蜜罐&#xff0c;側重企業安全場景&#xff0c;從內網失陷檢測、外網威脅感知、威脅情報生產三個場景出發&#xff0c;為用戶提供可獨立操作且實用的功能&#xff0c;通過安全、敏捷、可靠的中低交互蜜罐增加用戶在失陷感知和威脅…

docker-容器

安裝docker yum install -y docker查看版本 docker version安裝docker-compose yum install -y docker-compose查看版本 docker-compose --version基礎鏡像構建 tar --exclude/var/lib -cvf euler.tar /etc /boot /var /tmp /usr /mnt /bin /sbin /lib /lib64將JDK等需要的中間…

ESP32開發:ubuntu22.04 下esp-idf開發環境搭建

ubuntu22.04 下 esp-idf 開發環境搭建1.安裝編譯 ESP-IDF 需要以下軟件包2.獲取 ESP-IDF3.設置工具下載工具備選方案4.設置環境變量5.編譯工程并燒錄配置工程編譯工程燒錄固件到設備6.其他指令監視輸出擦除 flash清除編譯1.安裝編譯 ESP-IDF 需要以下軟件包 編譯 ESP-IDF 需要…

匯編基礎2

1.函數調用fun0mov r4, #100bx lrget_MaxNumcmp r0, r1stmfd sp!, {r0-r12, lr} //入棧bl fun0 //調用fun0函數ldmfd sp!, {r0-r12, lr} //出棧movge r3, r0movlt r3, r1bx lr mainldr sp, 0x40001000mov r0, #100mov r1, #200mov r2, #100stmfd sp!,…

20250909的學習筆記

HTML 基礎筆記1. HTML 基本格式<!DOCTYPE html> <html> <head><meta charset"utf-8"><title>中文測試</title> </head> <body>這里是測試body測試內容。 </body> </html>2. HTML 標簽常用標簽 - <h1…

Linux 安全加固;Windows 安全設置

一、Linux 安全加固1. 賬戶與權限管理最小權限原則禁用 root 遠程登錄&#xff1a;修改 /etc/ssh/sshd_config&#xff0c;設置 PermitRootLogin no。使用 sudo 替代直接 root 操作&#xff0c;并通過 /etc/sudoers 限制命令范圍&#xff08;如僅允許 apt 和 systemctl&#xf…

條碼打印檢測一體機是什么?

在工業4.0和智能制造的大背景下&#xff0c;數據的準確性和實時性是構建高效追溯系統。條碼/二維碼作為物理世界與數字世界連接的橋梁&#xff0c;其打印質量直接決定了數據鏈路的可靠性。傳統“打印-人工抽檢/離線全檢”的模式存在流程割裂、效率低下、無法100%覆蓋的弊端&…

Javaweb - 14.6 - Vue3 數據交互 Axios

目錄 Promise 普通函數和回調函數 Promise 簡介 Promise 基本用法 async 和 await 的使用 Axios 介紹 Axios 入門案例 Axios 的 get 和 post 方法 Axios 攔截器 完&#xff01; Promise 普通函數和回調函數 普通函數&#xff1a;正常調用的函數&#xff0c;一般函數…

怎么選適合企業的RPA財務機器人?

對于大多數財務人來說&#xff0c;“月初月末就是噩夢”已經成了常態&#xff1a;一邊要面對堆積如山的單據和報表&#xff0c;一邊還要應付領導不斷加碼的工作&#xff0c;常常忙到深夜&#xff0c;卻總覺得自己陷在重復事務中難有成長。其實&#xff0c;這并不是個體問題&…

html css js網頁制作成品——HTML+CSS無窮網頁設計(5頁)附源碼

目錄 一、?????網站題目 二、??網站描述 三、??網站介紹 四、??網站效果 五、?? 代碼實現 ??HTML

AUTOSAR進階圖解==>AUTOSAR_SWS_PDURouter

AUTOSAR PDU Router詳解文檔 AUTOSAR通信架構中的核心路由模塊目錄 1. 概述2. PDU Router模塊架構3. PDU Router配置模型4. PDU Router路由流程5. PDU Router狀態機6. 總結 1. 概述 PDU Router模塊是AUTOSAR通信架構中的核心組件&#xff0c;負責在AUTOSAR軟件組件之間路由I-…

RHEL7.9、RHEL9.3——源碼安裝MySQL

目錄 一、環境部署 1. 克隆rhel7.9虛擬機 二、源碼安裝MySQL 1. 準備工作 2. 源碼部署mysql8.0.40 1&#xff09;安裝編譯mysql所需軟件包 2&#xff09;編譯安裝mysql8.0.40 3&#xff09;生成啟動腳本 一、環境部署 1. 克隆rhel7.9虛擬機 改名為 “RHEL79_mysql_master” 并…

解決Win11 安全中心刪掉存在隱患的工具

打開設置&#xff0c; 找到Windows安全中心&#xff0c;找到病毒和威脅防護&#xff0c;選擇排除項&#xff0c;點 添加或刪除排除項添加文件&#xff0c;文件夾&#xff0c;工具按照自己需求選擇。或&#xff0c;刪除文件注意&#xff1a;隱患的工具或者文件安裝或者用完&…

通過URI Scheme實現從Web網頁上打開本地C++應用程序(以騰訊會議為例,附完整實現源碼)

目錄 1、需求描述 2、選擇URI Scheme實現 3、何為URI Scheme&#xff1f; 4、將自定義的URL Scheme信息寫入注冊表的C源碼實現 5、如何實現最開始的3種需求 6、后續需要考慮的細節問題 之前陸續收到一些從Web頁面上啟動我們C客戶端軟件的需求&#xff0c;希望我們能提供一…