使用.NET核心库csproj中的Selenium WebDriver

Rei*_*l-- 7 c# selenium selenium-webdriver asp.net-core-2.0

我正在尝试使用Selenium和.NET Core组建一个网络抓取应用程序,但是我无法找到我的WebDriver exe.

我有一个.csproj,它将运行项目的API,调用(以及其他)另一个将处理webscraping的.csproj.所有都在单个.sln中,并且都运行.NET Core 2.1

在刮凸出,我已经的NuGet安装Selenium.WebDriverSelenium.WebDriver.ChromeDriver.

我在API中创建了一个端点,它调用了抓取项目,并运行了一个尝试调用的方法new ChromeDriver().它不起作用:(具体来说,我得到:

The chromedriver.exe file does not exist in the current directory or in a directory on the PATH environment variable. The driver can be downloaded at ... <url>
Run Code Online (Sandbox Code Playgroud)

看起来相当清楚(虽然它令人失望并没有告诉你"当前目录"是什么意思.我将立刻提交PR)


通过观察重建期间的变化以及其他在线研究,我看到:

  • nuget包中的所有dlls和exes都存储在Global Nuget缓存中,而不是packages解决方案目录中的nuget 文件夹.
  • chromedriver.exe出现得到复制到<solutionFolder>\<ScrapingProjectFolder>\bin\Debug\chromeDriver.exe.
    • 我假设这是ChromeDriverNuget包的功能; 当然我自己没有配置它.
    • 对于ChromeDriver软件包而言,这表面看起来像是一个合理的事情,试图"安装这个以制作new ChromeDriver()JustWork".
  • 深入研究WebDriver代码库,发现它正在查看的"currentDirectory"是"的位置WebDriver.dll".
    • 在我的情况下,那是" <globalNugetPackagesCache>\selenium.webdriver\3.141.0\lib\netstandard2.0"
    • 似乎我不应该试图chromedriver.exe让它最终进入这个文件夹 - 将它复制到另一个包的全局缓存似乎是错误的?(人们同意吗?)
  • 这篇文章似乎得出了大致相同的结论,并说解决方案是调用驱动程序:

    new ChromeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))

    • 不幸的是,这条路径需要我<solutionFolder>\<APIProjectFolder>\bin\Debug\<ScrapingProjectFolder>.dll,因为dll会被复制到API项目的文件夹中.

我想到了几个解决方案,其中没有一个真正吸引人:

  • 我可以安装Selenium.WebDriver.ChromeDriver到API项目中.
    • Eww ... API项目不了解WebDriver或Selenium,现在Scraping项目没有驱动程序exe.
  • 我可以手动明确地将exe复制到正确的位置.
    • 感觉不对,感觉很脆弱.我怀疑这会让部署变得痛苦.
  • 我可以手动将ChromeDriver构造函数指向一个硬编码的路径,我恰好知道它包含当前的路径exe.
    • 似乎与上面类似; 虽然不是那么糟糕.
  • ??? 有没有办法让项目的所有DLL等编译成一个公共文件夹????

是否有一种好的,非黑客的方法来解决这个问题.这将导致JustWorks的git repo,并且将来部署到服务器将会相对轻松?

我上面描述的任何事情是错误的,还是错误配置的?

Øyv*_*tad 5

据我了解,您有一个依赖于 Scraping 项目的 API 项目。

Scraping.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>  
    <LangVersion>7.2</LangVersion>
    <PublishChromeDriver>true</PublishChromeDriver>    
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Selenium.WebDriver" Version="3.141.0" />
    <PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="2.46.0" />
  </ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

API.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <ItemGroup>
    <ProjectReference Include="..\Scraping\Scraping.csproj" />
  </ItemGroup>

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <LangVersion>7.2</LangVersion>
  </PropertyGroup>

</Project>
Run Code Online (Sandbox Code Playgroud)

诀窍是添加<PublishChromeDriver>true</PublishChromeDriver>到可传递项目以使其在运行时发布 chromedriver dotnet publish API.csprojChromeDriver 包在 NuGet 包中有自定义构建目标,因此它是自定义的

您现在可以使用

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>  
    <LangVersion>7.2</LangVersion>
    <PublishChromeDriver>true</PublishChromeDriver>    
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Selenium.WebDriver" Version="3.141.0" />
    <PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="2.46.0" />
  </ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

dotnet run API.csproj


Luk*_*azy 3

如果我错了,请纠正我。您有某种引用 Selenium 的类库,并且您想使用 ChromeDriver.exe,但您收到错误,无法在以下位置找到它。这相当简单。目前您正在引用类库(例如 Foo 到 API)。您的程序集位置将指向 API bin 位置,而 chromedriver.exe 位于类库 bin 下。如果是这种情况,您唯一要做的就是将以下 chromedriver.exe 复制到最终的 bin 目录(即 API)。

将以下构建后事件添加到您的 API 项目以复制 chromedriver:

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="copy $(SolutionDir)\ClassLibrary\bin\Debug\netstandard2.0\chromedriver.exe $(TargetDir)" />
  </Target>
Run Code Online (Sandbox Code Playgroud)

这会将您的 chromedriver.exe 复制到 API bin。稍后在初始化 ChromeDriver 时使用:

        var options = new ChromeOptions();
        var service = ChromeDriverService.CreateDefaultService(AppDomain.CurrentDomain.BaseDirectory);

        WebDriver = new ChromeDriver(service, options);
Run Code Online (Sandbox Code Playgroud)

whileAppDomain.CurrentDomain.BaseDirectory将指向您的 API bin 目录。