最近有一个需求,需要使用chromedp模拟浏览器操作,进行网页点击,输入,截图等功能。该功能之前在windows上已经成功了,只要windows上面有谷歌浏览器,直接调用chromedp即可操作浏览器。但是现在需要把该功能上线到服务器上面,服务器上面可没有chrome浏览器,而且服务器也没有可视化界面,这该怎么办呢?

尝试一(直接安装chrome):

最初项目部署在docker容器中,那我就在docker容器中安装chrome,找了好几篇安装教程,都没有成功,最后找到了一个CentOS7中安装谷歌浏览器 - 知乎 (zhihu.com)

安装之后,运行代码,报错,chrome failed to start:\n[2137:2137:0315/154821.658064:ERROR:ozone_platform_x11.cc(239)] Missing X server or $DISPLAY\n[2137:2137:0315/154821.658111:ERROR:env.cc(255)] The platform failed to initialize. Exiting.\n

最终失败,也就是说,如果我们想要使用在liunx中使用chromedp,直接用普通的方式安装谷歌浏览器是行不通的。

尝试二:

尝试一无果,接着寻找解决方法,看到一篇博客go实现网页截图_headless-shell_猿进化的博客-CSDN博客

Chrome 浏览器的无界面形态

什么是 Headless Chrome Headless Chrome 是 Chrome 浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有 Chrome 支持的特性运行你的程序。 相比于现代浏览器,Headless Chrome 更加方便测试 web 应用,获得网站的截图,做爬虫抓取信息等。

于是我觉得,CentOs有专门的谷歌浏览器,需要用docker容器启动,然后我就按照上面的方法先启动了一个docker容器,该容器提供的是chrome浏览器服务,之前下载的谷歌浏览器可以直接删除了。

但是当我访问该容器服务的时候,显示如下

然后我就舍弃了这篇文章,之后又看到了一篇文章

在Linux(Centos 8)上使用Headless Chrome无头浏览器采集的真实体验(附上Golang的采集代码) - 知乎 (zhihu.com)

本篇文章和前一篇文章是相似的,也是用docker启动chrome的headless服务。然后启动成功后,监测方式如下:

然后就成功了

后续我参考该文章的代码,对我的代码进行了微调,主要就是一些关于chromedp的配置

func GetChromeCtx(focus bool) context.Context {
    if ChromeCtx == nil || focus {
        allocOpts := chromedp.DefaultExecAllocatorOptions[:]
        allocOpts = append(
            chromedp.DefaultExecAllocatorOptions[:],
            chromedp.DisableGPU,
            //chromedp.NoDefaultBrowserCheck, //不检查默认浏览器
            //chromedp.Flag("headless", false),
            chromedp.Flag("blink-settings", "imagesEnabled=false"), //开启图像界面,重点是开启这个
            chromedp.Flag("ignore-certificate-errors", true),       //忽略错误
            chromedp.Flag("disable-web-security", true),            //禁用网络安全标志
            chromedp.Flag("disable-extensions", true),              //开启插件支持
            chromedp.Flag("accept-language", `zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6`),
            //chromedp.Flag("disable-default-apps", true),
            //chromedp.NoFirstRun, //设置网站不是首次运行
            chromedp.WindowSize(1921, 1024),
            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"), //设置UserAgent
        )

        if checkChromePort() {
            // 不知道为何,不能直接使用 NewExecAllocator ,因此增加 使用 ws://127.0.0.1:9222/ 来调用
            c, _ := chromedp.NewRemoteAllocator(context.Background(), "ws://127.0.0.1:9222/")
            ChromeCtx, _ = chromedp.NewContext(c)
        } else {
            c, _ := chromedp.NewExecAllocator(context.Background(), allocOpts...)
            ChromeCtx, _ = chromedp.NewContext(c)
        }
    }
    return ChromeCtx
}

上面代码配置的是chromedp.NewRemoteAllocator(context.Background(), "ws://127.0.0.1:9222/"),所以该服务不能再部署在docker容器里面了,因为chrome服务是通过docker部署在服务器上面的,所以我们需要把服务直接部署在服务器上面。

如果也想要把服务器部署到容器内部,需要查看容器的ip地址

然后docker两个容器之间是可以直接通信的,我们可以把

chromedp.NewRemoteAllocator(context.Background(), "ws://127.0.0.1:9222/") 改成 chromedp.NewRemoteAllocator(context.Background(), "ws://172.17.0.8:9222/")

总结

chrome官方为我们提供了Centos环境下的chrome,可以达到和windows环境下的chrome同等效果,windows的话,直接下载软件安装即可,Linux系统的话,需要使用docker启动chrome headless服务。

Logo

更多推荐