Bla*_*mba 9 selenium python-3.x selenium-chromedriver
我通过chromewebdriver(windows)使用selenium和python,以便自动执行从不同页面下载大量文件的任务.我的代码有效,但解决方案远非理想:下面的函数点击启动java脚本函数的网站按钮,生成PDF文件然后下载它.
我不得不使用一个静态等待,以等待下载完成(丑陋的),我不能为了验证检查文件系统时,下载完成,因为我使用多线程(下载来自不同页面的文件很多的一次)并且文件的名称也是在网站本身动态生成的.
我的代码:
def file_download(num, drivervar):
Counter += 1
try:
drivervar.get(url[num])
download_button = WebDriverWait(drivervar, 20).until(EC.element_to_be_clickable((By.ID, 'download button ID')))
download_button.click()
time.sleep(10)
except TimeoutException: # Retry once
print('Timeout in thread number: ' + str(num) + ', retrying...')
.....
Run Code Online (Sandbox Code Playgroud)
是否可以在webdriver中确定下载完成?我想避免使用time.sleep(x).
非常感谢.
Flo*_* B. 20
您可以通过chrome://downloads/驱动程序导航获取每次下载的状态.
等待所有下载完成并列出所有路径:
def every_downloads_chrome(driver):
if not driver.current_url.startswith("chrome://downloads"):
driver.get("chrome://downloads/")
return driver.execute_script("""
var items = downloads.Manager.get().items_;
if (items.every(e => e.state === "COMPLETE"))
return items.map(e => e.fileUrl || e.file_url);
""")
# waits for all the files to be completed and returns the paths
paths = WebDriverWait(driver, 120, 1).until(every_downloads_chrome)
print(paths)
Run Code Online (Sandbox Code Playgroud)
我遇到了同样的问题并找到了解决方案。您可以检查 .crdownload 是否在您的下载文件夹中。如果下载文件夹中有 0 个扩展名为 .crdownload 的文件实例,则所有下载都已完成。我认为这仅适用于铬和铬。
def downloads_done():
while True:
for filename in os.listdir("/downloads"):
if ".crdownload" in i:
time.sleep(0.5)
downloads_done()
Run Code Online (Sandbox Code Playgroud)
每当您调用 downloads_done() 时,它都会自行循环,直到所有下载完成。如果您正在下载 80 GB 之类的大文件,那么我不建议这样做,因为该函数可以达到最大递归深度。
2020年编辑:
def wait_for_downloads():
print("Waiting for downloads", end="")
while any([filename.endswith(".crdownload") for filename in
os.listdir("/downloads")]):
time.sleep(2)
print(".", end="")
print("done!")
Run Code Online (Sandbox Code Playgroud)
print() 中的“end”关键字参数通常包含一个换行符,但我们将其替换。虽然 /downloads 文件夹中没有以 .crdownload 结尾的文件名休眠 2 秒并打印一个没有换行符的点到控制台
在发现请求后,我真的不建议再使用 selenium,但如果它是一个非常严密保护的站点,有 cloudflare 和验证码等,那么你可能不得不求助于 selenium。
使用 Chrome 80,我不得不通过以下代码更改@florent-b 的答案:
def every_downloads_chrome(driver):
if not driver.current_url.startswith("chrome://downloads"):
driver.get("chrome://downloads/")
return driver.execute_script("""
return document.querySelector('downloads-manager')
.shadowRoot.querySelector('#downloadsList')
.items.filter(e => e.state === 'COMPLETE')
.map(e => e.filePath || e.file_path || e.fileUrl || e.file_url);
""")
Run Code Online (Sandbox Code Playgroud)
我相信这是复古兼容的,我的意思是这将适用于旧版本的 Chrome。
在无头模式下运行 Chrome 时出现打开问题chrome://downloads/。
以下函数使用复合方法,无论模式是否为无头,都可以工作,并选择每种模式中可用的更好方法。
它假设调用者在file_download_path每次调用此函数后清除所有下载的文件。
import os
import logging
from selenium.webdriver.support.ui import WebDriverWait
def wait_for_downloads(driver, file_download_path, headless=False, num_files=1):
max_delay = 60
interval_delay = 0.5
if headless:
total_delay = 0
done = False
while not done and total_delay < max_delay:
files = os.listdir(file_download_path)
# Remove system files if present: Mac adds the .DS_Store file
if '.DS_Store' in files:
files.remove('.DS_Store')
if len(files) == num_files and not [f for f in files if f.endswith('.crdownload')]:
done = True
else:
total_delay += interval_delay
time.sleep(interval_delay)
if not done:
logging.error("File(s) couldn't be downloaded")
else:
def all_downloads_completed(driver, num_files):
return driver.execute_script("""
var items = document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList').items;
var i;
var done = false;
var count = 0;
for (i = 0; i < items.length; i++) {
if (items[i].state === 'COMPLETE') {count++;}
}
if (count === %d) {done = true;}
return done;
""" % (num_files))
driver.execute_script("window.open();")
driver.switch_to_window(driver.window_handles[1])
driver.get('chrome://downloads/')
# Wait for downloads to complete
WebDriverWait(driver, max_delay, interval_delay).until(lambda d: all_downloads_completed(d, num_files))
# Clear all downloads from chrome://downloads/
driver.execute_script("""
document.querySelector('downloads-manager').shadowRoot
.querySelector('#toolbar').shadowRoot
.querySelector('#moreActionsMenu')
.querySelector('button.clear-all').click()
""")
driver.close()
driver.switch_to_window(driver.window_handles[0])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9102 次 |
| 最近记录: |