使用 Chromedp 监听网页请求和响应
在进行网络爬虫的时候,有很多网站都有反爬机制,比如你想抓点数据,结果发现每次请求都带一堆奇奇怪怪的参数 —— 什么 timestamp 签名、AES 加密的字段,还有各种 Token 令牌,跟密码本似的。你直接看网页源代码吧,那些 JS 代码被混淆得亲妈都不认识,像一团乱麻似的根本理不清头绪。
这时候我们可以使用chromedp来监听网页请求,它的核心价值在于:第一不用费劲巴拉地去解密那些被混淆的 JS 代码,直接拿现成的参数用;第二能盯着不同操作时参数怎么变,比如刷新页面时哪个值会变,登录时多了哪个字段;
什么是 Chromedp
ChromeDP 是一个 Go 语言实现的库,它提供了无头浏览器的操作和控制能力,可以用来进行网页自动化、爬虫和测试等工作。通过 ChromeDP,我们可以编程方式监听网页上的各种事件,包括网络请求和响应。
环境准备
首先,我们需要安装 Go 和 ChromeDP 库:
go">// 安装 ChromeDP
go get -u github.com/chromedp/chromedp
演示代码
下面是一个基本的示例,演示如何使用 ChromeDP 监听网页请求:
go">package mainimport ("context""encoding/base64""fmt""log""time""github.com/chromedp/cdproto/network""github.com/chromedp/chromedp"
)func EnBase64(base64String string) string {decodedBytes, err := base64.StdEncoding.DecodeString(base64String)if err != nil {log.Println("解码错误:", err)return ""}return string(decodedBytes)
}func main() {// 创建一个带取消功能的上下文ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)defer cancel()// 创建一个ChromeDP选项,启用网络事件opts := append(chromedp.DefaultExecAllocatorOptions[:],chromedp.Flag("headless", false),chromedp.Flag("disable-gpu", true),chromedp.Flag("enable-automation", true),chromedp.Flag("disable-extensions", true),)allocCtx, cancel := chromedp.NewExecAllocator(ctx, opts...)defer cancel()// 创建一个新的浏览器实例taskCtx, taskCancel := chromedp.NewContext(allocCtx)defer taskCancel() // 确保在退出时取消 taskCtx// 监听请求开始事件chromedp.ListenTarget(taskCtx, func(ev interface{}) {switch e := ev.(type) {case *network.EventRequestWillBeSent:// 打印请求信息fmt.Printf("请求URL: %s\n", e.Request.URL)fmt.Printf("请求方法: %s\n", e.Request.Method)fmt.Printf("请求头: %v\n", e.Request.Headers)// 如果有请求体,打印请求体if e.Request.HasPostData {entries := e.Request.PostDataEntriesfor _, entry := range entries {fmt.Printf("请求体: %s\n", EnBase64(entry.Bytes))}}fmt.Println("------------------------")case *network.EventResponseReceived:// 打印响应信息fmt.Printf("响应URL: %s\n", e.Response.URL)fmt.Printf("响应状态: %d\n", e.Response.Status)fmt.Printf("响应头: %v\n", e.Response.Headers)// 获取响应体/*不知道怎么回事直接在ListenTarget中使用GetResponseBody,会一直报错invalid context关于GetResponseBody 处理可以看 https://github.com/chromedp/chromedp/issues/427*/go func() {chromedp.Run(taskCtx, chromedp.ActionFunc(func(ctx context.Context) error {body, err := network.GetResponseBody(e.RequestID).Do(ctx)if err != nil {fmt.Println(err)}fmt.Printf("响应体: %s\n", string(body))return nil}))}()fmt.Println("------------------------")}})// 启用网络监听if err := chromedp.Run(taskCtx,network.Enable(),// 访问指定网页chromedp.Navigate("https://blog.csdn.net/yang731227"),// 等待页面加载完成chromedp.Sleep(15*time.Second),); err != nil {log.Fatal(err)}
}
过滤特定类型的请求
如果您只想监听特定类型的请求(例如,只关注 XHR 请求或特定 URL 模式),可以这样做:
go">// 在 EventRequestWillBeSent 事件处理中添加过滤逻辑
case *network.EventRequestWillBeSent:// 只关注 XHR 请求if e.Type == network.ResourceTypeXHR {fmt.Printf("XHR请求: %s %s\n", e.Request.Method, e.Request.URL)}// 或者只关注特定URL模式if strings.Contains(e.Request.URL, "api") {fmt.Printf("API请求: %s %s\n", e.Request.Method, e.Request.URL)}