来源:未知 时间: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