Go chromedp库的使用 —CDP

CDP(Chrome DevTools Protocol)

Chrome DevTools Protocol 是基于websocket的一种协议,可以运行其他工具或者库来通过CDP协议进行检查、调试Chrome和其他基于Blink的浏览器。

基于CDP协议的相关语言操作

  • Pyppeteer,它是谷歌chrome官方无头框架puppeteer的python版本 https://miyakogi.github.io/pyppeteer/reference.html
  • Puppeeer,它是一个Node库,可以使用Node.js来实现控制Chrome或Chromiumhttp://www.puppeteerjs.com/
  • Chromedp, 是由Go语言编写,支持Chrome DevTools Protocol的一个库,不需要依赖其他的外界服务(如Selenium和PhantomJS) https://github.com/chromedp/chromedp

Chromedp使用

  • chromedp.NewContext() 初始化chromedp的上下文,后续这个页面都使用这个上下文进行操作
  • chromedp.Run() 运行一个chrome的一系列操作
  • chromedp.Navigate() 将浏览器导航到某个页面
  • chromedp.WaitVisible() 等候某个元素可见,再继续执行。
  • chromedp.Click() 模拟鼠标点击某个元素
  • chromedp.Value() 获取某个元素的value值
  • chromedp.ActionFunc() 再当前页面执行某些自定义函数
  • chromedp.Text() 读取某个元素的text值
  • chromedp.Evaluate() 执行某个js,相当于控制台输入js
  • network.SetExtraHTTPHeaders() 截取请求,额外增加header头
  • chromedp.SendKeys() 模拟键盘操作,输入字符
  • chromedp.Nodes() 根据xpath获取某些元素,并存储进入数组
  • chromedp.NewRemoteAllocator
  • chromedp.OuterHTML() 获取元素的outer html
  • chromedp.Screenshot() 根据某个元素截图
  • page.CaptureScreenshot() 截取整个页面的元素
  • chromedp.Submit() 提交某个表单
  • chromedp.WaitNotPresent() 等候某个元素不存在,比如“正在搜索。。。”
  • chromedp.Tasks{} 一系列Action组成的任务

示例

本地界面浏览器操作

默认情况下chromedp使用的浏览器为headless-chrome

func main() {
    //禁用headless-chrome 无头浏览器  推荐debug模式下使用
	opts := append(chromedp.DefaultExecAllocatorOptions[:], chromedp.Flag("headless", false))
	alloctx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
	defer cancel()

	ctx, cancel := chromedp.NewContext(alloctx, chromedp.WithErrorf(log.Printf))
	defer cancel()
	var nodes []*cdp.Node
	err := chromedp.Run(ctx,
		chromedp.Navigate("https://www.cnblogs.com/"),
		chromedp.WaitVisible(`#footer`, chromedp.ByID),
		chromedp.Nodes(`//*[@id="footer_bottom"]/div[2]/*`,&nodes),
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("get nodes:", len(nodes))
	// print titles
	for _, node := range nodes {
		fmt.Println(node.Children[0].NodeValue, ":", node.AttributeValue("href"))
	}
}

远程操作示例(无头浏览器)

Centos 安装chronium-headless

###搜索chrome的yum源
yum search chromium
##选择chromium-headless.x86_64
sudo yum install chromium-headless.x86_64
###查看chrome二进制文件位置
rpm -ql chromium-headless.x86_64     ///usr/lib64/chromium-browser/headless_shell
nohup /usr/lib64/chromium-browser/headless_shell --no-first-run --no-default-browser-check --headless --disable-gpu --remote-debugging-port=9222 --no-sandbox --disable-plugins --remote-debugging-address=0.0.0.0 --window-size=1920,1080 &

###查看端口服务器是否开启
netstat -lntp

headless_shell(chrome)Flag参数说明

--no-first-run---default-browser-check--headless--disable-gpuremote-debugging-port--no-sandbox--remote-debugging-address=127.0.0.1--disable-plugins--remote-debugging-address0.0.0.0127.0.0.1--window-size

示例代码

package main

import (
	"context"
	"flag"
	"fmt"
	"github.com/chromedp/cdproto/cdp"
	"github.com/chromedp/chromedp"
	"log"
)

func main() {
	devtoolsWsURL := flag.String("devtools-ws-url", "http://192.168.3.177:9222/json", "DevTools WebSsocket URL")
	flag.Parse()
	if *devtoolsWsURL == "" {
		log.Fatal("must specify -devtools-ws-url")
	}
	fmt.Println("----", *devtoolsWsURL)
	// create allocator context for use with creating a browser context later
	allocatorContext, cancel := chromedp.NewRemoteAllocator(context.Background(), *devtoolsWsURL)
	defer cancel()

	// create context
	ctxt, cancel := chromedp.NewContext(allocatorContext)
	defer cancel()
	var nodes []*cdp.Node
	err := chromedp.Run(ctxt,
		chromedp.Navigate("https://www.cnblogs.com/"),
		chromedp.WaitVisible(`#footer`, chromedp.ByID),
		chromedp.Nodes(`//*[@id="footer_bottom"]/div[2]/*`, &nodes),
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("get nodes:", len(nodes))
	// print titles
	for _, node := range nodes {
		fmt.Println(node.Children[0].NodeValue, ":", node.AttributeValue("href"))
	}

}
Browsesrless/chrome部署

注:部署Browserless需要有docker环境

####拉取镜像
docker pull browserless/chrome
###运行 设置最大并发会话数。默认情况下,未指定时设置为 5。一旦达到限制,就会开始排队,请求将等到更多工作人员准备就绪
 docker run -e "MAX_CONCURRENT_SESSIONS=3" -p 10003:3000 --restart always -d browserless/chrome

docker run -e "TOKEN=2cbc5771-38f2-4dcf-8774-50ad51a971b8" -p 3000:3000 --restart always -d --name browserless browserless/chrome

###在应用查询中使用查询参数来传递改令牌
const browser = await puppeteer.connect({
    browserWSEndpoint: 'ws://localhost:3000?token=2cbc5771-38f2-4dcf-8774-50ad51a971b8',
});

Linux-Centos安装NodeJS

su root
yum install -y wget
####官方下载地址:https://nodejs.org/en/download/
wget https://nodejs.org/dist/v12.18.1/node-v12.18.1-linux-x64.tar.xz
tar -xvf node-v12.18.1-linux-x64.tar.xz
ln -s /root/node-v12.18.1-linux-x64/bin/node /usr/bin/node
ln -s /root/node-v12.18.1-linux-x64/bin/npm /usr/bin/npm
node -v
npm -v

参考

p://www.puppeteerjs.com/ “Puppeteer”
11: https://github.com/chromedp/chromedp “chromedp”
12: https://www.cnblogs.com/yjf512/p/13181998.html “chromedp入门”
13: https://blog.csdn.net/wanwuguicang/article/details/79751571 “Chrome启动参数大全”