.Net6中想实现对某个网址截屏,可通过Selenium模拟访问网址并实现截图。

实现

安装Nuget包

<PackageReference Include="Selenium.Chrome.WebDriver" Version="85.0.0" />
<PackageReference Include="Selenium.Support" Version="4.1.0" />
<PackageReference Include="Selenium.WebDriver" Version="4.1.0" />

之后可通过代码实现模拟访问网址并截图

public static string PageScreenshot(string url, string uploadbasepath)
{
ChromeDriver driver = null;
try
{
ChromeOptions options = new ChromeOptions(); options.AddArguments("headless", "disable-gpu", "no-sandbox");
driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), options); //driver = new ChromeDriver("/usr/bin/google-chrome-stable", options);
driver.Navigate().GoToUrl(url);
string width = driver.ExecuteScript("return document.body.scrollWidth").ToString();
string height = driver.ExecuteScript("return document.body.scrollHeight").ToString();
driver.Manage().Window.Size = new System.Drawing.Size(int.Parse(width), int.Parse(height)); //=int.Parse( height);
var screenshot = (driver as ITakesScreenshot).GetScreenshot(); //directory create
var basepath = uploadbasepath + DateTime.Now.ToString("yyyyMMdd") + "/";
if (!Directory.Exists(uploadbasepath))
{
Directory.CreateDirectory(uploadbasepath);
}
if (!Directory.Exists(basepath))
{
Directory.CreateDirectory(basepath);
} var path = basepath + Guid.NewGuid().ToString("N") + ".jpg"; screenshot.SaveAsFile(path);
return path;
}
catch (Exception ex)
{
throw;
}
finally
{
if (driver != null)
{
driver.Close();
driver.Quit();
}
}
}

需要另外做的一步是把chromedriver从bin/Release/netcoreapp3.1/chromedriver复制到publish目录。

你以为到这就完了?这个代码确实可以在windows/linux非容器环境下运行。但是在docker里还是有些不一样。

Docker中运行的那些坑

首先需要注意.netcore3.1在Docker中操作图片记得安装libgdiplus.so

#Dockerfile
RUN apt-get update -y && apt-get install -y --allow-unauthenticated libgdiplus && apt-get clean && ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll

1.第一个坑

首先遇到的就是OpenQA.Selenium.DriverServiceNotFoundException异常,异常信息是

OpenQA.Selenium.DriverServiceNotFoundException: The file /opt/google/chrome/chrome/chromedriver does not exist. The driver can be downloaded at http://chromedriver.storage.googleapis.com/index.html

这个异常明显是找不到chromedriver,那就与在非Docker环境linux中直接运行的方式一样,尝试把chromedriver复制到Docker的publish目录中,在Dockerfile中添加以下内容

#dockerfile

RUN cp /src/xxx/Release/netcoreapp3.1/chromedriver /app/publish/

2.第二个坑

尝试运行以上容器,还是失败,进入容器内部,直接运行chromedriver,可以看到缺少libxx.so之类的库。那咋办,只能尝试在镜像中安装chrome,这样相关库就有了

安装chrome相关资料

https://stackoverflow.com/questions/55206172/how-to-run-dotnet-core-app-with-selenium-in-docker

https://github.com/devpabloassis/seleniumdotnetcore/blob/master/Dockerfile

那在Dockerfile中添加安装chrome的命令

#Dockerfile Install Chrome
RUN apt-get update && apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg \
hicolor-icon-theme \
libcanberra-gtk* \
libgl1-mesa-dri \
libgl1-mesa-glx \
libpango1.0-0 \
libpulse0 \
libv4l-0 \
fonts-symbola \
--no-install-recommends \
&& curl -sSL https://dl.google.com/linux/linux_signing_key.pub | apt-key add - \
&& echo "deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list \
&& apt-get update && apt-get install -y \
google-chrome-stable \
--no-install-recommends \
&& apt-get purge --auto-remove -y curl \
&& rm -rf /var/lib/apt/lists/*

3.第三个坑

运行以上修改后的容器,又一个异常

DevToolsActivePort file doesn't exist

继续查资料发现需要加个参数disable-dev-shm-usage

https://stackoverflow.com/questions/50642308/webdriverexception-unknown-error-devtoolsactiveport-file-doesnt-exist-while-t

但是前面试了不在docker内运行,需要这个参数,那就加个环境变量区分开docker与非docker环境

#Dockerfile

ENV INDOCKER 1
public static string PageScreenshot(string url, string uploadbasepath)
{
ChromeDriver driver = null;
try
{
var indocker = Environment.GetEnvironmentVariable("INDOCKER");
ChromeOptions options = new ChromeOptions(); if (indocker == "1")
{
options.AddArguments("headless", "disable-gpu", "no-sandbox", "disable-dev-shm-usage");
//driver = new ChromeDriver("/opt/google/chrome/chrome", options);
}
else
{
options.AddArguments("headless", "disable-gpu", "no-sandbox");
}
driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), options); //driver = new ChromeDriver("/usr/bin/google-chrome-stable", options);
driver.Navigate().GoToUrl(url);
string width = driver.ExecuteScript("return document.body.scrollWidth").ToString();
string height = driver.ExecuteScript("return document.body.scrollHeight").ToString();
driver.Manage().Window.Size = new System.Drawing.Size(int.Parse(width), int.Parse(height)); //=int.Parse( height);
var screenshot = (driver as ITakesScreenshot).GetScreenshot(); //directory create
var basepath = uploadbasepath + DateTime.Now.ToString("yyyyMMdd") + "/";
if (!Directory.Exists(uploadbasepath))
{
Directory.CreateDirectory(uploadbasepath);
}
if (!Directory.Exists(basepath))
{
Directory.CreateDirectory(basepath);
} var path = basepath + Guid.NewGuid().ToString("N") + ".jpg"; screenshot.SaveAsFile(path);
return path;
}
catch (Exception ex)
{
throw;
}
finally
{
if (driver != null)
{
driver.Close();
driver.Quit();
}
}
}

4.第四个坑

尝试运行上面修改后的容器,又一个异常

This version of ChromeDriver only supports Chrome version 99
Current browser version is 109.0.5414.74 with binary path /usr/bin/google-chrome

这个信息字面意思就是之前第一个坑复制的chromedriver版本较低。那就直接去官网下载最新的chromedriver,并放到镜像内

下载地址:http://chromedriver.storage.googleapis.com/index.html

# Dockerfile
COPY ["xxx/chromedriver", "."]
RUN chmod +x chromedriver

5.第五个坑

继续尝试运行,发现这次能成功截图了,等等...这字体咋还是乱码呢

明显是中文乱码了,应该是容器内没中文字体,那就安装中文字体,字体可以从C:\Windows\Fonts中获取ttc,ttf字体文件

#Dockerfile

RUN apt-get update
RUN apt-get install -y --no-install-recommends libgdiplus libc6-dev
RUN apt-get install -y fontconfig xfonts-utils
COPY fonts/ /usr/share/fonts/
RUN mkfontscale
RUN mkfontdir
RUN fc-cache -fv

再次运行,终于成功

.Net6在Docker环境下操作Selenium.Chrome的那些坑的更多相关文章

  1. arm 环境下安装selenium+chrome

    1.  升级软件 apt-get update 2. 安装pip apt-get install python3-pip 3. 安装selenium pip3 install selenium .4. ...

  2. Docker环境下运行python+selenium+chrome

    Docker环境下运行python+selenium+chrome docker运行时占用的资源非常少,而且能将环境进行有效的隔离,可以快速的进行部署,因此可以将docker与selenium结合实现 ...

  3. docker环境下solr6.0配置(中文分词+拼音)

    前言:这篇文章是基于之前的“linux环境下配置solr5.3详细步骤”(http://www.cnblogs.com/zhangyuan0532/p/4826740.html)进行扩展的.本篇的步骤 ...

  4. docker环境下solrcloud+zookeeper集群部署教程

    前言:两个月前的16年11月份完成的配置,使用的solr6.1和zookeeper3.4,刚刚写成blog,目前版本可能有小版本的变化. 本例完成结果为:在docker环境下部署solrcloud集群 ...

  5. Elasticsearch Docker环境下安装

    Elasticsearch Docker环境下安装 Daemon镜像配置的是https://registry.docker-cn.com Linux:vi /etc/docker/daemon.jso ...

  6. Docker环境下的Mysql8 实现主从数据库数据同步方案

    本文记录下通过MySQL Replication在Docker环境下,通过多个容器 实现数据库主从配置. MySQL Replication就不多解释了,简单说就是MySQL非常出色的一个功能,该功能 ...

  7. Mac+Docker环境下xdebug的配置

    由于容器化的需要,前几天我本地也换成了docker环境.就研究了一下docker环境下phpstorm和xdebug的配置. http://www.mmfei.com/?p=453 这个博客给出了一个 ...

  8. docker环境下mysql参数修改

    原文:docker环境下mysql参数修改 需要修改log_bin为on,看了好几个博客说都需要删掉容器重新生成,然而并非如此, 我们可以用docker cp 命令将docker的文件"下载 ...

  9. arm树莓派Raspbian 下安装selenium+chrome

    arm树莓派Raspbian 下安装selenium+chrome 安装selenium pip3 install selenium 安装chromedriver sudo apt-get insta ...

  10. Docker环境下Java应用的最大内存和堆内存的设置

    Docker环境下Java应用的最大内存和堆内存的设置 1.  设置应用允许使用的最大内存 通过docker run(创建一个新的容器并运行)命令中设置-m来进行设置.案例如下所示. docker r ...

随机推荐

  1. 一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 1.简述Redis事务实现 2.redis集群方案 3.redis主从复制的核心原理 4.CAP理论,BASE理论 5.负 ...

  2. 网页头部的声明应该是用 lang="zh" 还是 lang="zh-CN"?

    网页头部的声明应该是用 lang="zh" 还是 lang="zh-CN"? 遇到问题 不知道大家有没有留意到一个问题,就是使用 VsCode 新建的 html ...

  3. 三十三、HPA实现自动扩缩容

    通过HPA实现业务应用的动态扩缩容 HPA控制器介绍 当系统资源过高的时候,我们可以使用如下命令来实现 Pod 的扩缩容功能 $ kubectl -n luffy scale deployment m ...

  4. 用Nodejs 实现一个简单的 Redis客户端

    目录 0. 写在前面 1. 背景映入 2. 数据库选择 3. Nodejs TCP连接 3. 代码编写 4. 实验 5. wireshark 抓包分析 6. 杂与代码 0. 写在前面 大家如果有去看过 ...

  5. Java继承Frame画一个窗口显示图片

    将图片显示到窗口上. 在工程目录下准备好图片5.png 运行代码: import javax.imageio.ImageIO; import java.awt.*; import java.awt.e ...

  6. 1.docker的基本使用

    1.简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化.容器是完 ...

  7. python学习——查找计算机中的文件

    # import os # # path = 'C:/Users/admin/Desktop/images' # files = os.listdir(path) # # for f in files ...

  8. java基础篇—基础语法

    一.关键字和保留字    1.什么是关键字? 通俗来说就是带有特殊含义的字符,有自己专门用途的单词 2.特点? 关键字全部由小写构成,以下是java官方列举出的关键字 注意: 保留关键字:指的是现有版 ...

  9. minio API demo

    package mainimport ( "context" "fmt" "github.com/minio/minio-go/v7" &q ...

  10. Go语言核心36讲05

    你已经使用过Go语言编写了小命令(或者说微型程序)吗? 当你在编写"Hello, world"的时候,一个源码文件就足够了,虽然这种小玩意儿没什么用,最多能给你一点点莫名的成就感. ...