【问题标题】:Download file from Button link to specific folder on C drive从 Button 链接下载文件到 C 盘上的特定文件夹
【发布时间】:2019-11-28 14:01:46
【问题描述】:

我正在抓取网页并导航到正确的位置,但是作为整个 c# 世界的新手,我一直在下载 pdf 文件。

链接隐藏在这个后面

var reportDownloadButton = driver.FindElementById("company_report_link");

类似于:www.link.com/key/489498-654gjgh6-6g5h4jh/link.pdf

如何将文件下载到 C:\temp\?

这是我的代码:

using System.Linq;
using OpenQA.Selenium.Chrome;

namespace WebDriverTest
{
    class Program
    {
        static void Main(string[] args)
        {

            var chromeOptions = new ChromeOptions();
            chromeOptions.AddArguments("headless");

            // Initialize the Chrome Driver // chromeOptions
            using (var driver = new ChromeDriver(chromeOptions))
            {
                // Go to the home page
                driver.Navigate().GoToUrl("www.link.com");
                driver.Manage().Timeouts().ImplicitWait = System.TimeSpan.FromSeconds(15);
                // Get the page elements
                var userNameField = driver.FindElementById("loginForm:username");
                var userPasswordField = driver.FindElementById("loginForm:password");
                var loginButton = driver.FindElementById("loginForm:loginButton");

                // Type user name and password
                userNameField.SendKeys("username");
                userPasswordField.SendKeys("password");

                // and click the login button
                loginButton.Click();

                driver.Navigate().GoToUrl("www.link2.com");
                driver.Manage().Timeouts().ImplicitWait = System.TimeSpan.FromSeconds(15);

                var reportSearchField = driver.FindElementByClassName("form-control");

                reportSearchField.SendKeys("Company");

                var reportSearchButton = driver.FindElementById("search_filter_button");
                reportSearchButton.Click();

                var reportDownloadButton = driver.FindElementById("company_report_link");
                reportDownloadButton.Click();

编辑:


编辑 2:

我还不是 Stackoverflow 社区中最锋利的笔。我不明白如何用 Selenium 做到这一点。我已经完成了

        var reportDownloadButton = driver.FindElementById("company_report_link");
        var text = reportDownloadButton.GetAttribute("href");
        // driver.Manage().Timeouts().ImplicitWait = System.TimeSpan.FromSeconds(15);

        WebClient client = new WebClient();
        // Save the file to desktop for debugging
        var desktop = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop);
        string fileName = desktop + "\\myfile.pdf";
        client.DownloadFile(text, fileName);

但是网页似乎有点棘手。我得到了

System.Net.WebException: '远程服务器返回错误: (401) 未经授权。'

调试器指向:

client.DownloadFile(text, fileName);

我觉得应该真的是模拟右键和链接另存为,否则这个下载就不行了。此外,如果我只是单击按钮,它会在新的 Chrome 选项卡中打开 PDF。


EDIT3:

应该是这样吗?

using System.Linq;
using OpenQA.Selenium.Chrome;

namespace WebDriverTest
{
    class Program
    {
        static void Main(string[] args)
        {

    // declare chrome options with prefs
    var options = new ChromeOptionsWithPrefs();
    options.AddArguments("headless"); // we add headless here

    // declare prefs
        options.prefs = new Dictionary<string, object>
        {
            { "download.default_directory", downloadFilePath }
        };

    // declare driver with these options
    //driver = new ChromeDriver(options); we don't need this because we already declare driver below.

            // Initialize the Chrome Driver // chromeOptions
            using (var driver = new ChromeDriver(options))
            {
                // Go to the home page
                driver.Navigate().GoToUrl("www.link.com");
                driver.Manage().Timeouts().ImplicitWait = System.TimeSpan.FromSeconds(15);
                // Get the page elements
                var userNameField = driver.FindElementById("loginForm:username");
                var userPasswordField = driver.FindElementById("loginForm:password");
                var loginButton = driver.FindElementById("loginForm:loginButton");

                // Type user name and password
                userNameField.SendKeys("username");
                userPasswordField.SendKeys("password");

                // and click the login button
                loginButton.Click();

                driver.Navigate().GoToUrl("www.link.com");
                driver.Manage().Timeouts().ImplicitWait = System.TimeSpan.FromSeconds(15);

                var reportSearchField = driver.FindElementByClassName("form-control");

                reportSearchField.SendKeys("company");

                var reportSearchButton = driver.FindElementById("search_filter_button");
                reportSearchButton.Click();

                driver.Manage().Timeouts().ImplicitWait = System.TimeSpan.FromSeconds(15);
                driver.Navigate().GoToUrl("www.link.com");

                // click the link to download
                var reportDownloadButton = driver.FindElementById("company_report_link");
                reportDownloadButton.Click();

                // if clicking does not work, get href attribute and call GoToUrl() -- this may trigger download
                var href = reportDownloadButton.GetAttribute("href");
                driver.Navigate().GoToUrl(href);

                }
            }
        }

    }
}

【问题讨论】:

  • 有多种方法,但如果您使用我在上一个答案中提供的代码,而不是写“.\”(意思是这个文件夹),而不是写你的路径。使下载路径为“C:\temp\” & FileName(只需确保目录存在,然后再下载)
  • 出现错误 (System.Net.WebException),您似乎需要一些凭据才能发送下载文件的请求,如果 Web 服务没有,这可能是不可能的API 或获取凭据的简单方法。如果您只是使用 Selenium 单击或导航到下载链接并设置 download.default_directory ChromeDriver 设置,则不应抛出此错误。
  • 是的,我现在只是在测试它。好像和你说的一样。 WebClient 解决方案似乎不起作用。我得到了链接,它工作正常。但是client.DownloadFile(text, fileName); 不起作用。为另一个 PDF 文件测试了我的脚本,它可以工作。所以我必须让你的解决方案发挥作用。
  • run your code here 只是意味着运行脚本所需的任何步骤才能到达下载按钮——我认为这些步骤已经在你的问题中,但我想让答案简明扼要为什么我这样做。我在您的问题中更新了您在EDIT 3 下的代码示例以解决一些问题——ChromeDriver 被声明了两次,我们可以在ChromeOptionsWithPrefs 中将headless 选项与download.default_directory 结合起来——您最初有两组声明的选项以及两个 ChromeDrivers。您的代码示例现在应该可以测试了。
  • 我之前尝试过类似的方法,但现在遇到了错误。调试器指向using (var driver = new ChromeDriver(options)) 中的“选项”。说Severity Code Description Project File Line Suppression State Error CS1503 Argument 1: cannot convert from 'WebDriverTest.ChromeOptionsWithPrefs' to 'OpenQA.Selenium.Chrome.ChromeOptions' Scraper C:\Users\PC\source\repos\Scraper\Program.cs 28 Active

标签: c# selenium selenium-webdriver web-scraping


【解决方案1】:

您可以尝试设置download.default_directory Chrome 驱动程序首选项:

// declare chrome options with prefs
var options = new ChromeOptionsWithPrefs();

// declare prefs
    options.prefs = new Dictionary<string, object>
    {
        { "download.default_directory", downloadFilePath }
    };

// declare driver with these options
driver = new ChromeDriver(options);


// ... run your code here ...

// click the link to download
var reportDownloadButton = driver.FindElementById("company_report_link");
reportDownloadButton.Click();

// if clicking does not work, get href attribute and call GoToUrl() -- this may trigger download
var href = reportDownloadButton.GetAttribute("href");
driver.Navigate().GoToUrl(href);

如果reportDownloadButton 是触发下载的链接,则文件应下载到您在download.default_directory 中设置的filePath

这些线程都不是在 C# 中,但他们谈到了类似的问题:

How to control the download of files with Selenium + Python bindings in Chrome

How to use chrome webdriver in selenium to download files in python?

【讨论】:

  • 谢谢你!我明天测试一下
  • 感谢您帮助我。我只是不明白// ... run your code here ... 之前的部分应该在哪里?我已经有了一个无头选项。如何添加另一个下载选项
【解决方案2】:

您可以为此使用WebClient.DownloadFile

【讨论】:

  • 如何从中获取链接作为字符串? var reportDownloadButton = driver.FindElementById("company_report_link");
  • 我不知道“company_report_link”是什么,但通常你可以访问url所在的属性或innertext。
猜你喜欢
  • 1970-01-01
  • 2015-09-19
  • 2015-03-17
  • 1970-01-01
  • 1970-01-01
  • 2015-06-01
  • 2021-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多