【问题标题】:Click a download link with Python and Selenium's Firefox Webdriver单击 Python 和 Selenium 的 Firefox Webdriver 的下载链接
【发布时间】:2019-03-09 02:28:27
【问题描述】:

我正在尝试从您将光标悬停在页面上的链接持续下载历史股票数据。目前我有以下代码似乎找不到 css_selector,也没有下载 .csv 文件。

#!/usr/bin/env python3.6

## Import Libraries
import os, sys
import time

from selenium import webdriver
import selenium.webdriver.firefox.options
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC 

## Declare Variables
ticker = 'CAT'
period1 = '1262332800'
period2 = '1537945200'
download_path = os.getcwd()
css_selector = "a.Fl\(end\):nth-child(1)"

## Configure Firefox Options
profile = webdriver.FirefoxProfile()
profile.set_preference("browser.download.folderList", 2) # 0 means to download to the desktop, 1 means to download to the default "Downloads" directory, 2 means to use the directory 
profile.set_preference("browser.download.dir", download_path)
profile.set_preference("browser.download.manager.showWhenStarting", False)
profile.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/x-gzip/text/csv")

## Firefox driver loads historical data page
driver = webdriver.Firefox(firefox_profile=profile)
driver.get("https://finance.yahoo.com/quote/{}/history?period1={}&period2={}&interval=1d&filter=history&frequency=1d"
           .format(ticker, period1, period2))

## Click on 'Download Data' Link
try:
    input_element = driver.find_element_by_css_selector(css_selector).click()
    print('Success!')

except:
    print('Failed!!!!!')

finally:
    driver.quit()
    print('Kill Driver!')

示例网站是: https://finance.yahoo.com/quote/CAT/history?period1=1262332800&period2=1538118000&interval=1d&filter=history&frequency=1d

css_selector, "a.Fl(end):nth-child(1)", 在 HTML 的这个部分找到:

<svg class="Va(m)! Mend(5px) Stk($c-fuji-blue-1-b)! Fill($c-fuji-blue-1-b)! Cur(p)" width="15" height="15" viewBox="0 0 48 48" data-icon="download" style="fill: rgb(0, 129, 242); stroke: rgb(0, 129, 242); stroke-width: 0; vertical-align: bottom;"><path d="M43.002 43.002h-38c-1.106 0-2.002-.896-2.002-2v-11c0-1.105.896-2 2.002-2 1.103 0 1.998.895 1.998 2v9h34.002v-9c0-1.105.896-2 2-2s2 .895 2 2v11c0 1.103-.896 2-2 2m-19-8L11.57 23.307c-.75-.748-.75-1.965 0-2.715.75-.75 1.965-.75 2.715 0l7.717 7.716V2h4v26.308l7.717-7.716c.75-.75 1.964-.75 2.714 0s.75 1.967 0 2.715L24.002 35.002z"></path></svg><span>Download Data</span>

我的问题是:

  • 有没有更简单的方法来点击链接?路径?部分链接?
  • 我是否尝试单击正确的 css_selector?
  • 是否需要将鼠标悬停在文本上才能点击下载数据链接?
  • 如何在网站加载时找到该元素?该网站永远不会完成下载,因为会不断调用广告服务器。

使用 .find_element_by_link_text() 方法会导致 TimeoutException:

TimeoutException Traceback(最近 最后调用) in ()
21 ## 前往首页查看历史数据
22 driver.get("https://finance.yahoo.com/quote/{}/history?period1={}&period2={}&interval=1d&filter=history&frequency=1d"

---> 23 .format(ticker, period1, period2) )
24
25 print('.get() 完成!')

~/virtualenvs/demo/lib/python3.6/site-packages/selenium/webdriver/remote/webdriver.py 在获取(自我,网址)
331 在当前浏览器会话中加载网页。
第332章 --> 333 self.execute(Command.GET, {'url': url})
334
第335章 在执行(自我,driver_command,参数)
319 响应 = self.command_executor.execute(driver_command, params)
320 如果响应:
--> 321 self.error_handler.check_response(响应)
322 响应['value'] = self._unwrap_value(
323 response.get('value',无))

~/virtualenvs/demo/lib/python3.6/site-packages/selenium/webdriver/remote/errorhandler.py 在 check_response(self, response)
240 alert_text = value['alert'].get('text')
241 引发异常类(消息、屏幕、堆栈跟踪、警报文本)
--> 242 引发异常类(消息、屏幕、堆栈跟踪)
243
244 def_value_or_default(self, obj, key, default):

TimeoutException:消息:300000 毫秒后加载页面超时

我对此的解释是网站没有完成加载,所以 try/except/finally 逻辑永远不会执行。

【问题讨论】:

  • 其实css_selector = "a.Fl\(end\):nth-child(1)"选择器是正确的。你能分享异常或当前的输出/行为描述吗?
  • 感谢您的回复,我正在尝试同时运行两者。目前,@dbachhav 的解决方案 link_text 已经工作过一次,但似乎没有第二次或第三次工作。该网站继续加载广告,我想知道这是否会阻碍驱动程序的进度。
  • 您的意思是当您尝试访问同一页面时,它的行为会有所不同?或者您需要处理许多页面并且通过链接文本搜索并不适用于所有页面?
  • 请注意,您得到TimeoutException 不是因为使用find_by_link_text(),而是因为使用driver.set_page_load_timeout(3)。这意味着您应该得到TimeoutException,以防页面在 3 秒内未加载。你真的需要那个吗?注释掉该行并再次检查
  • 不知道为什么您从异常日志中删除了driver.set_page_load_timeout(3) 行,但TimeoutException: Message: Timeout loading page after 300000ms 说明了一切:WebDriver 未能加载页面,但并非未能找到元素!

标签: python-3.x selenium selenium-webdriver


【解决方案1】:
  • 有没有更简单的方法可以点击链接?

    通过链接文本选择应该可以正常工作:

    driver.find_element_by_link_text('Download Data').click()
    
  • 我是否尝试点击正确的 css_selector?

    是的,选择器似乎是正确的

  • 是否需要将鼠标悬停在文本上才能点击下载数据链接?

    不,您不需要将鼠标悬停在链接上

更新

如果您需要停止页面加载,请尝试以下解决方案:

from selenium.common.exceptions import TimeoutException

driver.set_page_load_timeout(10)
try:
    driver.get("https://finance.yahoo.com/quote/{}/history?period1={}&period2={}&interval=1d&filter=history&frequency=1d"
           .format(ticker, period1, period2))
except TimeoutException:
    driver.execute_script("window.stop();")
driver.find_element_by_link_text('Download Data').click()

10秒内未加载,页面加载将被强制停止

【讨论】:

  • 原来问题是第三方广告下载。一旦站点被强行停止, .find_element_by_link_text() 方法就会与多个代码一致地工作。太感谢了。我打错了仗。
【解决方案2】:

请尝试以下选项

 1. download = driver.find_element_by_xpath(".//*[@id='Col1-1-HistoricalDataTable-Proxy']/section/div[1]/div[2]/span[2]/a")
    download.click()
 2. download = driver.find_element_by_link_text('Download Data')
    download.click()
 3. download = driver.find_element_by_partial_link_text('Download')
    download.click()

【讨论】:

  • 1.不要建议从浏览器开发工具复制 XPath 表达式:它们非常不可靠,并且很难维护这样的选择器。 2.与我的解决方案完全相同。 3. 如果可以通过完整的链接文本搜索,那么使用部分链接文本有什么意义?
  • @Andersson 如果你仔细看,即使他从浏览器复制了 xpath,它的 id 是唯一的,并且在这种情况下说不可靠是不正确的。不值得投反对票。
  • @TimaGegewepe ,它不是链接的ID,甚至不是父ID,而是祖先。请注意,如果对祖先进行任何修改,outerHTML 选择器就会损坏,并且很难理解它到底出了什么问题
  • @Andersson 我知道你的意思,但在你的解决方案中我可以这么说。由于元素本身没有唯一标识符,所以它总是这样。
  • @TimaGegewepe 没有定位器会不受所有更改的影响。最不可能改变的是链接文本。他们将不得不添加另一个具有完全相同文本的按钮,这可能不太可能。使用具有 6 个级别和 3 个索引的定位器更容易变得脆弱。两者不一样……甚至不接近。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-30
  • 1970-01-01
  • 2013-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多