.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. Docker | redis集群部署实战

    前面已经简单熟悉过redis的下载安装使用,今天接着部署redis集群(cluster),简单体会一下redis集群的高可用特性. 环境准备 Redis是C语言开发,安装Redis需要先将Redis的 ...

  2. C++之值传递&指针传递&引用传递详解

    C++之值传递&指针传递&引用传递详解 目录 C++之值传递&指针传递&引用传递详解 1.函数基础 2.值传递 3.指针传递 4.引用传递 1.函数基础 一个函数由以下 ...

  3. Spring知识框架

  4. nrf52——DFU升级USB/UART升级方式详解(基于SDK开发例程)

    摘要:在前面的nrf52--DFU升级OTA升级方式详解(基于SDK开发例程)一文中我测试了基于蓝牙的OTA,本文将开始基于UART和USB(USB_CDC_)进行升级测试. 整体升级流程: 整个过程 ...

  5. 20_Vue如何监测数组类型数据发生改变的?

    通过上一节,我们知道了vue检测对象数据发生改变的原理 但是还有个api我们没有讲解,Vue.set(): 这个API比较适合在理解了对象检测的原理后进行讲解 案例准备 html <!-- 创建 ...

  6. windows中 mysql 免安装版安装

    基本安装 绝对路径中避免出现中文,推荐首选英文为命名条件! 以管理员身份打开命令行,并转到mysql的bin目录下 安装mysql服务 mysqld --install 若出现以下错误,需将缺失的文件 ...

  7. Git 分支管理策略汇总

    原文链接: Git 分支管理策略 最近,团队新入职了一些小伙伴,在开发过程中,他们问我 Git 分支是如何管理的,以及应该怎么提交代码? 我大概说了一些规则,但仔细想来,好像也并没有形成一个清晰规范的 ...

  8. js高级之对象高级部分

    基于尚硅谷的尚硅谷JavaScript高级教程提供笔记撰写,加入一些个人理解 github源码 博客下载 对象的创建模式 Object构造函数模式 套路: 先创建空Object对象, 再动态添加属性/ ...

  9. 嵌入式-Linux基础操作

    Crtl+Alt+T:调出命令窗口 xrandr:列出分辨率列表 设置窗口的分辨率大小为1280x960:xrandr -s 1280x960 通过命令窗口来执行一段C语言程序: VI工具的使用: ( ...

  10. MyBatis详解(一)

    MyBatis简单介绍 [1]MyBatis是一个持久层的ORM框架[Object Relational Mapping,对象关系映射],使用简单,学习成本较低.可以执行自己手写的SQL语句,比较灵活 ...