Использование Selenium WebDriver в библиотеке csproj с .NET Core - PullRequest
0 голосов
/ 21 января 2019

Я пытаюсь собрать приложение для просмотра веб-страниц, используя Selenium и .NET Core, но у меня возникают проблемы с поиском моего WebDriver exe s.

У меня есть один .csproj, который будет запускать API для проекта, который вызывает (среди прочего) другой .csproj, который будет обрабатывать webscraping. Все они находятся в одном .sln, и все работают под управлением .NET Core 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>

Кажется довольно ясным (хотя это неутешительно не говорит вам, что означает "текущий каталог". Я буду представлять PR для этого неизбежно)


Наблюдая за изменениями во время перестройки и других онлайн-исследований, я вижу, что:
  • Все dll и exe из пакетов nuget хранятся в глобальном кэше Nuget, а не в папке nuget packages в каталоге решений.
  • Появляется chromedriver.exe, скопированный в <solutionFolder>\<ScrapingProjectFolder>\bin\Debug\chromeDriver.exe.
    • Я предполагаю, что это то, что делает пакет ChromeDriver Nuget; конечно, я не настроил это сам.
    • На первый взгляд кажется разумным, что пакет 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 и т. Д. Проекта скомпилированными в одну общую папку? ???

Есть хороший, не хакерский способ решить эту проблему. Что приведет к созданию git-репозитория JustWorks и в будущем будет относительно безболезненным для развертывания на сервере?

Есть что-то, что я описал выше, неправильно или неправильно настроено?

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Пожалуйста, поправьте меня, если я ошибаюсь.У вас есть какая-то библиотека классов, которая имеет ссылку на Selenium, и вы хотели бы использовать ChromeDriver.exe, но вы получаете ошибку, которую не удается найти в следующем месте.Это довольно просто.В настоящее время вы ссылаетесь на Class Library, скажем Foo для API.Местоположение вашей сборки будет указывать на местоположение бина API, тогда как chromedriver.exe находится в бине библиотеки классов.В этом случае единственное, что вам нужно сделать, это скопировать следующий файл 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.Позже при инициализации ChromeDriver используйте:

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

        WebDriver = new ChromeDriver(service, options);

Пока AppDomain.CurrentDomain.BaseDirectory будет указывать на каталог вашего API bin.

0 голосов
/ 10 февраля 2019

Насколько я понимаю, у вас есть проект API, который зависит от проекта Scraping.

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>

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, поэтому он custom .

Теперь вы можете использовать

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

и dotnet run API.csproj

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...