
本文介绍在 Go 中处理 AJAX 驱动网站爬虫的核心思路:由于标准 http.Get 仅获取静态 HTML,无法执行 JavaScript,因此需模拟浏览器行为或逆向分析 AJAX 请求,才能提取真实渲染后的内容。
本文介绍在 go 中处理 ajax 驱动网站爬虫的核心思路:由于标准 `http.get` 仅获取静态 html,无法执行 javascript,因此需模拟浏览器行为或逆向分析 ajax 请求,才能提取真实渲染后的内容。
Go 语言原生 HTTP 客户端(如 net/http)不具备 JavaScript 执行能力,调用 http.Get() 返回的只是服务器初始响应的 HTML 骨架——所有由 AJAX 动态注入的内容(例如填充在
中的链接)均不会出现在响应体中。要成功抓取这类站点,需采用以下两类主流方案:✅ 方案一:逆向分析 AJAX 请求(推荐,轻量高效)
适用于前端逻辑清晰、API 接口稳定的情况。步骤如下:
- 在浏览器开发者工具(F12 → Network → XHR/Fetch)中观察页面加载时发出的真实请求;
- 提取请求 URL、HTTP 方法、Headers(尤其是 User-Agent、Referer、X-Requested-With)、查询参数及请求体(如 JSON);
- 使用 Go 模拟该请求,解析返回的 JSON/XML/HTML 片段,提取所需链接。
示例:模拟一个获取文章列表的 AJAX 请求
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
)
type Article struct {
ID int `json:"id"`
URL string `json:"link"`
Title string `json:"title"`
}
func main() {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://example.com/api/articles?page=1", nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
req.Header.Set("X-Requested-With", "XMLHttpRequest")
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var articles []Article
if err := json.Unmarshal(body, &articles); err == nil {
for _, a := range articles {
fmt.Printf("- %s → %s\n", a.Title, a.URL)
}
}
}✅ 优势:速度快、资源占用低、易于并发;
⚠️ 注意:需关注接口鉴权(如 token、cookie)、反爬策略(如时间戳、签名)、频率限制。
✅ 方案二:集成无头浏览器(适用于复杂 SPA)
当 AJAX 逻辑高度耦合、加密参数难以还原,或页面依赖完整 DOM 生命周期(如 Vue/React 路由、滚动加载)时,可借助支持 DevTools 协议的 Headless 浏览器。
推荐库:chromedp(纯 Go 实现,无需外部 Selenium)
安装 Chrome/Chromium 后,通过 chromedp 启动并控制浏览器执行 JS、等待元素加载、提取渲染后 DOM:
package main
import (
"context"
"log"
"time"
"github.com/chromedp/chromedp"
)
func main() {
ctx, cancel := chromedp.NewExecAllocator(context.Background(), append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.Flag("headless", true),
chromedp.Flag("disable-gpu", true),
)...)
defer cancel
ctx, cancel = chromedp.NewContext(ctx)
defer cancel
var links []string
err := chromedp.Run(ctx,
chromedp.Navigate("https://example.com"),
// 等待 .content 加载完成(最多 5 秒)
chromedp.WaitVisible(".content", chromedp.ByQuery, chromedp.NodeReadyStateComplete),
// 执行 JS 提取所有 a 标签 href
chromedp.Evaluate(`Array.from(document.querySelectorAll('.content a')).map(a => a.href)`, &links),
)
if err != nil {
log.Fatal(err)
}
for _, link := range links {
log.Println("Found link:", link)
}
}✅ 优势:100% 复现用户浏览行为,兼容任意前端框架;
⚠️ 注意:启动开销大、内存占用高、需管理浏览器生命周期,不建议高频/大规模使用。
? 总结与选型建议
- 优先尝试方案一:90% 的 AJAX 网站可通过 Network 面板定位真实 API,手动构造请求更可控、可维护;
- 慎用方案二:仅当逆向成本过高或业务强依赖客户端渲染时启用,生产环境建议配合连接池与超时控制;
- 通用增强项:无论哪种方案,都应添加 User-Agent、合理设置 Timeout、复用 http.Client、处理重定向与 Cookie,并遵守 robots.txt 及网站 Terms of Service。
动态网页爬取的本质不是“让 Go 执行 JS”,而是理解前端数据流——从“页面如何变”转向“数据从哪来”。掌握请求逆向与协议交互,才是 Go 爬虫工程师的核心能力。


















