我们有一个Selenium流程,可以从我们的数据提供者处获取数据以进行进一步处理。该过程试图获取所有历史数据,并且由于我们没有可靠地过滤掉最近编辑过的数据的功能,因此我们必须不时获得完整的数据转储以确保不丢弃任何记录。
Selenium进程是作为Python脚本编写的。它进入特定网站,登录,按下触发报告生成的按钮,然后下载报告。问题是,对于完整转储报告,报告生成开始花费的时间超过默认的Selenium超时。
我们使用Google Chrome驱动程序,但如果其他驱动程序能够完全禁用超时,则会愿意更改浏览器/驱动程序。
以下是代码的简化版本,其中只包含适当描述此问题所需的简单内容。标记超出报告超时的位置。点击按钮后,它正在等待网站的回复。如何禁用它,为什么我们目前所做的事情(可以在下面看到)是不够的?
from selenium import webdriver
def selectPopUp(driver, main_window_handle, maxWait=100):
"""
Selects a pop-up window. If no pop-up window appears, raises an
Exception.
:param maxWait: how long to wait (in seconds) before raising the error?
"""
popup_window_handle = None
i = 0
while (not popup_window_handle) and (i < maxWait):
for handle in driver.window_handles:
if handle != main_window_handle:
popup_window_handle = handle
break
# Wait a litle and re-iterate.
time.sleep(1)
i += 1
if popup_window_handle != None:
driver.switch_to.window(popup_window_handle)
return popup_window_handle
else:
raise Exception("No pop-up window appeared although the program was expecting one.")
def selectOption(dropdown, option, possibilities):
"""
Validates and selects an option from a drop-down.
:param dropdown: the Selenium reference to the dropdown selection.
:param option: the name of the option we'll select
:param possibilities: the possibilities we allow to choose from --
will raise an Exception
if `option` is not in `possibilities`.
:returns: Selenium selection.
"""
# Select the default Excel option
if option in possibilities:
return dropdown.find_element_by_xpath("//option[@value='" + option + "']")\
.click()
else:
raise Exception("Invalid choice! Use one of the following: \n\n " + \
"\n ".join(possibilities))
chromeOptions = webdriver.ChromeOptions()
prefs = {"download.default_directory" : DOWNLOAD_DIRECTORY}
chromeOptions.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(executable_path=settings.chromeDriver,
chrome_options=chromeOptions)
# Set an infite timeout time so that the slow Crystal reports
# would stand a chance of not timing out too.
driver.set_page_load_timeout(9999999999)
driver.set_script_timeout(9999999999)
# We go to the relevant website - that part is edited out.
# Once in the website, we select the current window handle
# to be able to come back to it after navigating through pop-ups.
main_window_handle = driver.current_window_handle
reportDropDown = driver.find_element_by_id(REPORT_ELEMENT_ID)
selectedReport = reportDropDown.find_element_by_xpath("//option[@value='" + SELCTED_REPORT_TITLE + "']")
selectedReport.click()
########################################################################
# >>>>>>>> The first place where the process keeps timing out. <<<<<<< #
########################################################################
# Click on the export button to open export pop-up.
exportButton = driver.find_element_by_name(r'crytlViewer$ctl02$ctl00')
exportButton.click()
# Now a pop-up with a download button appears. Select it.
popUpHandle = selectPopUp(driver, main_window_handle)
# Now, select a particular download format.
formatDropDown = driver.find_element_by_id("exportFormatList")
selectedFormat = selectOption(formatDropDown, reportFormat, REPORT_FORMAT_LIST)
# Download the report.
driver.find_element_by_id("submitexport").click()
#########################################################################
# >>>>>>>> The second place where the process keeps timing out. <<<<<<< #
#########################################################################
我们得到的错误消息的代表示例如下:
Traceback (most recent call last):
File "/home/ubuntu/main/oodle/core/utils.py", line 296, in repeatUntilSuccess
return func()
File "/home/ubuntu/main/oodle/salesforce/data_feed.py", line 277, in <lambda>
cleanUp=True),
File "/home/ubuntu/main/oodle/salesforce/data_feed.py", line 322, in pushReports
'liveEnvironment': self.liveEnvironment}]\
File "/home/ubuntu/main/oodle/core/reporting.py", line 1160, in __getitem__
self.handlers[name].PreparePandas(**paramDict)
File "/home/ubuntu/main/oodle/reports/vienna_salesforce_data_feed/Salesforce_LoanObject_Parsed.py", line 38, in PreparePandas
loan = self.manager.handlers[crystalReport].PreparePandas()
File "/home/ubuntu/main/oodle/core/reporting.py", line 1231, in PreparePandas
return self.TransformRaw(self.GetRaw(fileFrom))
File "/home/ubuntu/main/oodle/core/reporting.py", line 1387, in GetRaw
self.PrepareExcel(fileFrom)
File "/home/ubuntu/main/oodle/core/reporting.py", line 1367, in PrepareExcel
fileTo=fileTo)
File "/home/ubuntu/main/oodle/vienna/crystal.py", line 293, in downloadReport
self.downloadReport_no_error_handling(reportTitle, reportFormat, fileTo)
File "/home/ubuntu/main/oodle/vienna/crystal.py", line 247, in downloadReport_no_error_handling
self.driver.find_element_by_id("submitexport").click()
File "/home/ubuntu/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 77, in click
self._execute(Command.CLICK_ELEMENT)
File "/home/ubuntu/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 493, in _execute
return self._parent.execute(command, params)
File "/home/ubuntu/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 256, in execute
self.error_handler.check_response(response)
File "/home/ubuntu/.local/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 194, in check_response
raise exception_class(message, screen, stacktrace)
TimeoutException: Message: timeout
(Session info: chrome=60.0.3112.78)
(Driver info: chromedriver=2.29.461571 (8a88bbe0775e2a23afda0ceaf2ef7ee74e822cc5),platform=Linux 4.4.0-1052-aws x86_64)
在Alexey Dolgopolov建议的编辑后,我们收到以下错误消息,与前一个略有不同:
Traceback (most recent call last):
File "/home/ubuntu/main/oodle/core/utils.py", line 296, in repeatUntilSuccess
return func()
File "/home/ubuntu/main/oodle/salesforce/data_feed.py", line 277, in <lambda>
cleanUp=True),
File "/home/ubuntu/main/oodle/salesforce/data_feed.py", line 322, in pushReports
'liveEnvironment': self.liveEnvironment}]\
File "/home/ubuntu/main/oodle/core/reporting.py", line 1160, in __getitem__
self.handlers[name].PreparePandas(**paramDict)
File "/home/ubuntu/main/oodle/reports/vienna_salesforce_data_feed/Salesforce_LoanObject_Parsed.py", line 38, in PreparePandas
loan = self.manager.handlers[crystalReport].PreparePandas()
File "/home/ubuntu/main/oodle/core/reporting.py", line 1231, in PreparePandas
return self.TransformRaw(self.GetRaw(fileFrom))
File "/home/ubuntu/main/oodle/core/reporting.py", line 1387, in GetRaw
self.PrepareExcel(fileFrom)
File "/home/ubuntu/main/oodle/core/reporting.py", line 1367, in PrepareExcel
fileTo=fileTo)
File "/home/ubuntu/main/oodle/vienna/crystal.py", line 318, in downloadReport
try:
File "/home/ubuntu/main/oodle/vienna/crystal.py", line 254, in downloadReport_no_error_handling
exportButton.click()
File "/home/ubuntu/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 77, in click
self._execute(Command.CLICK_ELEMENT)
File "/home/ubuntu/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webelement.py", line 494, in _execute
return self._parent.execute(command, params)
File "/home/ubuntu/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 236, in execute
self.error_handler.check_response(response)
File "/home/ubuntu/.local/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 192, in check_response
raise exception_class(message, screen, stacktrace)
TimeoutException: Message: timeout
(Session info: chrome=60.0.3112.78)
(Driver info: chromedriver=2.29.461571 (8a88bbe0775e2a23afda0ceaf2ef7ee74e822cc5),platform=Linux 4.10.0-26-generic x86_64)
答案 0 :(得分:0)
当find_element_by_<whatever>
发生implicitly_wait超时时。默认值为0.
我想,你不需要禁用超时。尝试使用显式等待。阅读http://selenium-python.readthedocs.io/waits.html和https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.wait.html#module-selenium.webdriver.support.wait。
使用类似的东西:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
...
selectedReport.click()
exportButton = WebDriverWait(driver, 9999, 5).until(
EC.visibility_of_element_located(
(By.NAME, r'crytlViewer$ctl02$ctl00')
)