起因
在使用网络爬虫时,尤其是使用 chromedp 库进行爬虫的过程中,我们可能会遇到点击某个链接后,目标页面在浏览器的新标签页或新窗口中打开的情况。这样的行为可能会导致我们无法直接获取新标签页中的内容,因为 chromedp 只会在原始的上下文(Context)中保持活动,而不能自动转到新打开的标签页。
为了解决这个问题,我们需要监听新标签页的创建,这样便可以在新的上下文中操作新标签页的内容。
实现方式
以下是一个示例代码,展示如何使用 chromedp 监听新的标签页并获取其内容。
/**
* 使用 chromedp 监听新标签页的功能
*/
package main
import (
"context"
"github.com/chromedp/cdproto/target"
"github.com/chromedp/chromedp"
"log"
"net/http/httptest"
"time"
)
// addNewTabListener 注册新标签页的监听服务并返回新标签页的 ID 通道
func addNewTabListener(ctx context.Context) <-chan target.ID {
// 创建一个 HTTP 服务器用于监听新标签页
mux := http.NewServeMux()
ts := httptest.NewServer(mux)
defer ts.Close() // 确保服务器在退出时得到关闭
// 监听新目标的创建,当新标签页的 URL 不为空时返回
return chromedp.WaitNewTarget(ctx, func(info *target.Info) bool {
return info.URL != ""
})
}
// configureChromeOptions 设置 Chrome 启动参数
func configureChromeOptions() []chromedp.ExecAllocatorOption {
return append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.NoDefaultBrowserCheck, // 不检查默认浏览器
chromedp.Flag("headless", false), // 启用可视化界面
chromedp.Flag("ignore-certificate-errors", true), // 忽略证书错误
chromedp.Flag("disable-web-security", true), // 禁用网络安全设置
chromedp.Flag("disable-extensions", false), // 开启扩展支持
chromedp.Flag("disable-default-apps", false),
chromedp.NoFirstRun, // 不是首次运行
chromedp.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36"),
)
}
// main 主函数,程序的入口
func main() {
// 创建执行上下文
allocCtx, _ := chromedp.NewExecAllocator(context.Background(), configureChromeOptions()...)
ctx, _ := chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))
// 添加新标签页监听
newTabChan := addNewTabListener(ctx)
// 执行爬虫任务
err := chromedp.Run(ctx,
chromedp.Navigate("https://buyin.jinritemai.com/dashboard/live/control"),
chromedp.Sleep(3*time.Second),
chromedp.WaitReady(`._1M2DJMjmtJZhkk7ei5nC9F`, chromedp.ByQuery),
chromedp.Sleep(5*time.Second),
chromedp.Click(`._1M2DJMjmtJZhkk7ei5nC9F`, chromedp.ByQuery, chromedp.NodeNotVisible), // 点击链接打开新标签
)
if err != nil {
log.Fatal(err)
}
// 获取新标签页的上下文
newCtx, _ := chromedp.NewContext(ctx, chromedp.WithTargetID(<-newTabChan))
// 新标签页执行任务,获取内容
var res string
err = chromedp.Run(newCtx,
chromedp.WaitReady(`#app`, chromedp.ByID),
chromedp.Text(`#app`, &res, chromedp.NodeVisible, chromedp.ByID),
)
if err != nil {
log.Fatal(err)
}
// 输出获取到的内容
log.Println(res)
}
参考
https://studygolang.com/articles/30736
https://github.com/chromedp/chromedp/issues/367