代码之家  ›  专栏  ›  技术社区  ›  Brondahl

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

  •  5
  • Brondahl  · 技术社区  · 6 年前

    我正在尝试使用Selenium和.NET核心构建一个Web抓取应用程序,但我在获取WebDriver时遇到了困难。 exe 将被发现。

    我有一个.csproj将运行该项目的API,它调用另一个.csproj来处理Webscraping。 所有这些都在一个.sln中,并且都在运行.NET核心2.1

    在刮削项目中,我已经安装了Nuget Selenium.WebDriver Selenium.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>
    

    看起来相当清楚(尽管它没有告诉你“当前目录”是什么意思。我马上就要提交一份公关报告)


    通过观察重建过程中的变化和其他在线研究,我发现:
    • 所有的 dll S和 exe nuget包中的s存储在全局nuget缓存中,而不是nuget packages 解决方案目录中的文件夹。
    • 这个 chromedriver.exe 似乎被复制到 <solutionFolder>\<ScrapingProjectFolder>\bin\Debug\chromeDriver.exe .
      • 我想这就是 ChromeDriver Nuget软件包有,当然我自己还没有配置。
      • 对于Chromedriver软件包来说,这表面上似乎是一件合理的事情,它试图“安装此软件以使 新Chromedriver() JustWork。”
    • 深入研究WebDriver代码库,可以发现它正在查看的“currentdirectory”是“ WebDriver.dll “。
      • 在我的情况下,这是” <globalNugetPackagesCache>\selenium.webdriver\3.141.0\lib\netstandard2.0
      • 看起来我不应该试图 Chromedriver.exe文件 要在这个文件夹中结束-将它复制到另一个包的全局缓存中似乎是错误的? (人们同意吗?)
    • This article 似乎得出了大致相同的结论,并表示解决方案是调用驱动程序,如下所示:

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

      • 不幸的是,这条路把我带到 <solutionFolder>\<APIProjectFolder>\bin\Debug\<ScrapingProjectFolder>.dll 因为动态链接库是通过api项目的文件夹复制的。

    我想到了几个解决办法,但没有一个真正有吸引力:

    • 我可以安装 selenium.webdriver.chromedriver(硒.webdriver.chromedriver) 进入API项目。
      • EWW…API项目不知道WebDriver或Selenium,而现在刮削项目没有驱动程序exe。
    • 我可以手动将exe文件复制到正确的位置。
      • 感觉不太好,感觉很脆弱。我怀疑这会让部署很痛苦。
    • 我可以手动将chromedriver构造函数指向一个硬编码路径,我刚好知道它包含当前 exe .
      • 似乎与上述情况类似;虽然还不算太糟。
    • ????有没有办法让一个项目的所有DLL等编译成一个单一的公用文件夹?????

    有没有一个好的,非黑客的方法来解决这个问题。这将导致git repo正常工作,并且将来部署到服务器将相对轻松?

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

    2 回复  |  直到 6 年前
        1
  •  1
  •   LukaszBalazy    6 年前

    如果我错了,请纠正我。您有一种引用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>
    

    这将把chromedriver.exe复制到api bin。稍后在初始化Chromedriver时使用:

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

    同时 AppDomain.CurrentDomain.BaseDirectory 将指向您的api bin目录。

        2
  •  0
  •   Øyvind Hvamstad    6 年前

    据我所知,您有一个依赖于刮擦项目的API项目。

    刮削.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>
    

    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>
    

    诀窍是增加 <PublishChromeDriver>true</PublishChromeDriver> 传递项目,使其在运行时发布chromedriver dotnet publish API.csproj Chromedriver包在nuget包中有自定义的构建目标,因此 习俗 .

    您现在可以使用

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

    dotnet run API.csproj