来源:未知 时间:2023-04-21 16:48 作者:小飞侠 阅读:次
[导读] 1. chromedp 是什么? 而最近广泛使用的headless browser解决方案PhantomJS已经宣布不再继续维护,转而推荐使用headless chrome. 那么headless chrome究竟是什么呢,Headless Chrome 是 Chrome 浏览器的无界面形态...
1. chromedp 是什么?而最近广泛使用的headless browser解决方案PhantomJS已经宣布不再继续维护,转而推荐使用headless chrome. 那么headless chrome究竟是什么呢,Headless Chrome 是 Chrome 浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有 Chrome 支持的特性运行您的程序. 简而言之,除了没有图形界面,headless chrome具有所有现代浏览器的特性,可以像在其他现代浏览器里一样渲染目标网页,并能进行网页截图,获取cookie,获取html等操作. 想要在golang程序里使用headless chrome,需要借助一些开源库,实现和headless chrome交互的库有很多,这里选择chromedp,接口和Selenium类似,易上手. chromedp提供一种更快,更简单的方式来驱动浏览器 (Chrome, Edge, Safari, Android等)在 Go中使用Chrome Debugging Protocol 并且没有外部依赖 (如Selenium, PhantomJS等). 2. chromedp 能够做什么?
3. 使用Go语言chromedp包调用chrome(headless)使用chromedp 之前您必须有一下基础
3.1 安装go语言chromedp包go get 命令安装chromedp chromepd 包 go get -u github.com/chromedp/chromedp 3.2 chromedp包使用chrome 普通模式普通模式会在电脑上弹出浏览器窗口.调用完成之后需要关闭掉浏览器, 当然在电脑上也可以使用chrome headless 模式, 缺点就是您多次go run main.go 的时候, go 代码运行中断导致后台chrome headless不能退出,导致第二次本地调试失败, 解决方案就是自己手动结束chrome进程. 建议在不提调试go代码的时候不要使用 chrome headless 模式. 使用普通模式可以在浏览器中看到代码执行的效果. 在我本机(windows10)上测试的时候chromedp 提示找不到chrome.exe所以需要制定一下chrome.exe的执行程序地址 runner.Path(`C:\Users\mojotv.cn\AppData\Local\Google\Chrome\Application\chrome.exe`), main.go 代码package mainimport ( "context" "github.com/chromedp/chromedp/runner" "io/ioutil" "log" "time" "github.com/chromedp/cdproto/cdp" "github.com/chromedp/chromedp")func main() { var err error // create context ctxt, cancel := context.WithCancel(context.Background()) defer cancel() // 本期启动chrome的一些参数相当于执行了 shell 命令 // C:\Users\mojotv.cn\AppData\Local\Google\Chrome\Application\chrome.exe --no-default-browser-check=true --no-sandbox=true --window-size=1280,900 // 如果需要更多参数详解chrome浏览器参数的文档 runnerOps := chromedp.WithRunnerOptions( //我的windows10电脑使用chromedp默认配置导致找不到chrome.exe //这行代码可以注释掉,如果找不到自己的chrome.exe 请像我一样制定chrome.exe路径 //一下配置都不是必选的 //更多参数详解文档 https://blog.csdn.net/wanwuguicang/article/details/79751571 runner.Path(`C:\Users\mojotv.cn\AppData\Local\Google\Chrome\Application\chrome.exe`), //启动chrome的时候不检查默认浏览器 runner.Flag("no-default-browser-check", true), //启动chrome 不适用沙盒, 性能优先 runner.Flag("no-sandbox", true), //设置浏览器窗口尺寸, runner.WindowSize(1280, 1024), //设置浏览器的userage runner.UserAgent(`Mozilla/5.0 (iPhone; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.25 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1`), ) //在普通模式的情况下启动chrome程序,并且建立共代码和chrome程序的之间的连接(https://127.0.0.1:9222) c, err := chromedp.New(ctxt, chromedp.WithLog(log.Printf), runnerOps) if err != nil { log.Fatal(err) } var siteHref, title, iFrameCode string err = c.Run(ctxt, visitMojoTvDotCn("https://mojotv.cn/2018/12/10/how-to-create-a-https-proxy-serice-in-100-lines-of-code.html", &siteHref, &title, &iFrameCode)) if err != nil { log.Fatal(err) } log.Printf("`%s` (%s),html:::%s", title, siteHref, iFrameCode) // shutdown chrome err = c.Shutdown(ctxt) if err != nil { log.Fatal(err) } // wait for chrome to finish err = c.Wait() if err != nil { log.Fatal(err) }}func visitMojoTvDotCn(url string, elementHref, pageTitle, iFrameHtml *string) chromedp.Tasks { //临时放图片buf var buf []byte return chromedp.Tasks{ //跳转到页面 chromedp.Navigate(url), //chromedp.Sleep(2 * time.Second), //等待博客正文显示 chromedp.WaitVisible(`#post`, chromedp.ByQuery), //滑动页面到google adsense 广告 chromedp.ScrollIntoView(`ins`, chromedp.ByQuery), chromedp.Screenshot(`#post`, &buf, chromedp.ByQuery, chromedp.NodeVisible), //等待2s chromedp.Sleep(2 * time.Second), //截图到文件 chromedp.ActionFunc(func(context.Context, cdp.Executor) error { //保存图片到mojotv_local.png return ioutil.WriteFile("mojotv_local.png", buf, 0644) }), //滑动页面到#copyright chromedp.ScrollIntoView(`#copyright`, chromedp.ByID), //等待mojotv google广告展示出来 chromedp.WaitVisible(`#post__title`, chromedp.ByID), chromedp.Sleep(2 * time.Second), //获取我的google adsense 广告代码 chromedp.InnerHTML(`#post__title`, iFrameHtml, chromedp.ByID), //跳转到我的bilibili网站 chromedp.Sleep(5 * time.Second), chromedp.Click("#copyright > a:nth-child(3)", chromedp.NodeVisible), //等待则个页面显现出来 chromedp.WaitVisible(`#page`, chromedp.ByQuery), //在chrome浏览器页面里执行javascript chromedp.Evaluate(`document.title`, pageTitle), chromedp.Screenshot(`#page`, &buf, chromedp.ByQuery, chromedp.NodeVisible), chromedp.Sleep(5 * time.Second), //截取bili网页图片 chromedp.ActionFunc(func(context.Context, cdp.Executor) error { return ioutil.WriteFile("bili_local.png", buf, 0644) }), //获取bilibili网页的标题 chromedp.JavascriptAttribute(`a`, "href", elementHref, chromedp.ByQuery), }} chromedp普通模式您可以通过 runner.Flag 函数来定义 chrome 启动的参数chromedp截图效果3.3 chromedp包使用chrome headless模式(不会弹出GUI界面)3.3.1 Centos7(没有图像界面) 安装chrome使用官方Docker安装
浏览器访问 http://10.202.255.220:9222/json 输出结果如下: [ { "description": "", "devtoolsFrontendUrl": "/devtools/inspector.html?ws=10.202.255.220:9222/devtools/page/EB66F54F32DE9C40D190E4B963DFBB8F", "id": "EB66F54F32DE9C40D190E4B963DFBB8F", "title": "about:blank", "type": "page", "url": "about:blank", "webSocketDebuggerUrl": "ws://10.202.255.220:9222/devtools/page/EB66F54F32DE9C40D190E4B963DFBB8F"} ] chrome-headless 启动成功 在服务器yum安装chronium-headless
chrome-headless 9222端口效果3.3.2 golang代码实现chromedp 调用远程chrome-headless程序一下代码实例包含多个chromedp/example多个项目的功能
package mainimport ( "context" //"fmt" "io/ioutil" "log" "github.com/chromedp/cdproto/cdp" "github.com/chromedp/chromedp" "github.com/chromedp/chromedp/client") func main() { var err error // create context ctxt, cancel := context.WithCancel(context.Background()) defer cancel() // 连接我远程服务器上启动和chrome-headless 服务器 // 因为我的代码不是在我的笔记本上运行,所以不能使用client.New默认配置 // 所以使用client.URL来自定义自己服务器地址 c, err := chromedp.New(ctxt, chromedp.WithTargets(client.New(client.URL("http://pan.mojotv.cn:9222/json")).WatchPageTargets(ctxt)), chromedp.WithLog(log.Printf)) if err != nil { log.Fatal(err) } // run task list var siteHref, title, iFrameCode string err = c.Run(ctxt, visitMojoTvDotCn("https://mojotv.cn/2018/12/10/how-to-create-a-https-proxy-serice-in-100-lines-of-code.html", &siteHref, &title, &iFrameCode)) if err != nil { log.Fatal(err) } log.Printf("`%s` (%s),html:::%s", title, siteHref, iFrameCode)} func visitMojoTvDotCn(url string, elementHref, pageTitle, iFrameHtml *string) chromedp.Tasks { //临时放图片buf var buf []byte return chromedp.Tasks{ //跳转到页面 chromedp.Navigate(url), //chromedp.Sleep(2 * time.Second), //等待博客正文显示 chromedp.WaitVisible(`#post`, chromedp.ByQuery), //滑动页面到google adsense 广告 chromedp.ScrollIntoView(`ins`, chromedp.ByQuery), chromedp.Screenshot(`#post`, &buf, chromedp.ByQuery, chromedp.NodeVisible), //截图到文件 chromedp.ActionFunc(func(context.Context, cdp.Executor) error { return ioutil.WriteFile("mojotv.png", buf, 0644) }), //等待mojotv google广告展示出来 chromedp.WaitVisible(`ins`, chromedp.ByQuery), //获取我的google adsense 广告代码 chromedp.InnerHTML(`ins`, iFrameHtml, chromedp.ByQuery), //跳转到我的bilibili网站 chromedp.Click("#copyright > a:nth-child(3)", chromedp.NodeVisible), //等待则个页面显现出来 chromedp.WaitVisible(`#page-index`, chromedp.ByQuery), //在chrome浏览器页面里执行javascript chromedp.Evaluate(`document.title`, pageTitle), chromedp.Screenshot(`#page-index`, &buf, chromedp.ByQuery, chromedp.NodeVisible), //截取bili网页图片 chromedp.ActionFunc(func(context.Context, cdp.Executor) error { return ioutil.WriteFile("bili.png", buf, 0644) }), //获取bilibili网页的标题 chromedp.JavascriptAttribute(`a`, "href", elementHref, chromedp.ByQuery), }} chromedp代码和chrome-headless分离优缺点
截图效果不能显示字体,因为我的centos7服务器没有安装中文字体导致, centos 安装中文字体教程 4. 总结对与不习惯函数式编程的同学来说,chromedp的代码还是比较奇怪不是容易看懂, 但是如果您有耐心多点击cmd+鼠标左键还是可以看懂的,需要有耐心. chromedp在使用selector 和执行js代码的时,如果表达式复杂就会找不到元素或者,js代码复制就会执行出错. 但是满足大部分需求是没有问题的. |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com