前言
说起 Golang 实现爬虫,网上可以找到很多很多代码和文章。而这里,主要想分享的是,实际爬虫项目中的开发与生产环境配置与相关代码经验。
我们都知道,在Golang中,是利用 chromedp+goquery 来实现爬虫的。
chromedp
chromedp 是一款基于 Chrome DevTools 协议的 Go 语言工具,可实现高效、可靠的 Web 自动化。chromedp 支持两种创建 chrome 实例的方法:
- 本地应用
- 远程链接
正好,我们使用本地应用方式作为本地开发环境模式,远程链接方式则作为 Kubernetes 生产环境模式(也可以包括测试环境)。
本地开发环境
以 MacOS 为例,下载并安装 Chrome 浏览器,就这么简单。
K8S生产环境
在K8S集群上,直接使用 chromedp/headless-shell 镜像即可,与开发的爬虫应用放在同一个 Pod 中。
spec:
containers:
# 爬虫应用容器
# ...
# chromedp容器
- image: 'chromedp/headless-shell:latest'
name: chromedp
ports:
- containerPort: 9222
name: ws
protocol: TCP
代码
1)初始化 chrome 实例
配置好开发与生产环境之后,我们来看一下代码中如何实现不同环境的适配。
var chromeCtx context.Context = nil
func getChromeCtx(chromeRemoteURL string) context.Context {
if chromeCtx == nil {
var c context.Context
if chromeRemoteURL != "" {
c, _ = chromedp.NewRemoteAllocator(context.Background(), config.Conf.Chrome.RemoteURL)
} else {
options := append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.DisableGPU,
chromedp.Flag("headless", true), // debug使用, true不显示浏览器,false打开浏览器
chromedp.Flag("blink-settings", "imagesEnabled=false"),
chromedp.UserAgent(`Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36`),
)
c, _ = chromedp.NewExecAllocator(context.Background(), options...)
}
chromeCtx, _ = chromedp.NewContext(c, chromedp.WithLogf(log.Infof))
// 执行一个空task, 提前创建Chrome实例
chromedp.Run(chromeCtx, make([]chromedp.Action, 0, 1)...)
}
return chromeCtx
}
通过配置实现不同环境的 chromeRemoteURL 参数:
- 本地开发环境,chromeRemoteURL 为空;
- K8S生产环境,chromeRemoteURL = "ws://127.0.0.1:9222/"
2)读取 HTML 内容
初始化 Chrome 实例之后,便可以使用 chromedp 读取指定URL的HTML内容。
func getHtmlContent(url string) (html string, err error) {
timeoutCtx, cancel := context.WithTimeout(getChromeCtx(), 60*time.Second)
defer cancel()
var ids []cdp.NodeID
err = chromedp.Run(timeoutCtx,
chromedp.Navigate(url),
chromedp.NodeIDs(`document`, &ids, chromedp.ByJSPath),
chromedp.ActionFunc(func(ctx context.Context) (e error) {
html, e = dom.GetOuterHTML().WithNodeID(ids[0]).Do(ctx)
return e
}),
)
return html, err
}
goquery
goquery 是用 Go 语言编写的一个类似于 jQuery 的库——基于 HTML 解析库 net/html 和 CSS 库 cascadia,提供与 jQuery 相近的接口。上面通过 chromedp 读取指定URL的HTML内容后,则利用 goquery 进行解析,从而抓取所需要的内容。
doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
if err != nil {
return err
}
elements := doc.Find(".a")
elements.ChildrenFiltered(".b").Each(func(i int, n *goquery.Selection) {
// ...
}
要用好 goquery,最重要的就是搞清楚 HTML 元素选择器,以及节点属性值。这里,就不具体展开了,可以结合自身需要,查阅官方接口文档。
结束语
这里,以实际项目为例,分享了分别针对 MacOS 和 K8S 的 chromedp 环境配置与代码实现。后续,如果有涉及到了其他软硬件环境,还将继续分享。