我如何让我的 python 脚本在执行下一个代码块之前等待 "save as" 对话框在 chrome 中弹出?

How can I tell my python script to wait for the "save as" dialogue box to pop out in chrome before executing the next block of the code?

我用selenium和pyautogui从一个网站下载图片。我的代码逻辑通过使用 selenium 来浏览我想要的链接的页面来工作。通过使用 pyautogui,我可以将它们组合在一起以自动右键单击并下载图像(虽然不是很完美)并输入它的文件名。我现在面临的问题是,如果保存图片的对话框时间过长无法弹出。 Pyautogui 没有能力等待它弹出并只是盲目地输入它应该输入的文本。我很难查找它并想出一种方法来检测弹出的对话。我目前遇到了这个问题。有什么真正的方法可以告诉我的程序等待它在 selenium 中弹出?还是我必须为此使用另一个模块?在那种情况下我可以使用什么模块?

重现问题的代码:

import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pyautogui as auto


driver = webdriver.Chrome()

urls = [  # Sample urls.
    'https://unsplash.com/photos/MAqmEdUCq4k',
    'https://unsplash.com/photos/s7PhRjUJNeA',
]

# Declaring img_xpath and x for loop counting.
img_xpath = '//*[@id="app"]/div/div[2]/div/div[1]/div[3]/div/div/button/div[2]/img'
x = 0

for url in urls:  # Loops through urls.
    x += 1
    time.sleep(2)
    driver.get(url)

    # Waits for the image element of the site to load.
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.XPATH, img_xpath))
    )

    # Calculates current browser center relative to screen position.
    win_pos = driver.get_window_position()
    win_size = driver.get_window_size()
    bcs = [  # bcs stands for Browser Center on Screen.
        win_pos['x'] + int(win_size['width'] / 2),
        win_pos['y'] + int(win_size['height'] / 2),
    ]

    # Using pyautogui to save image.
    auto.moveTo(bcs[0], bcs[1])
    auto.click()
    time.sleep(1)
    auto.rightClick()
    auto.moveTo(bcs[0] + 25, bcs[1] + 35)
    auto.click()
    time.sleep(2)  # Comment out this line to reproduce the problem if your system is too fast.
    auto.typewrite(f'Sample_{str(x)}')
    auto.press('enter')
time.sleep(3)
driver.close()

额外的 notes.The 代码使用具有默认设置的 Chrome 浏览器。

版本:

Python → 3.8.5

PyAutoGUI → 0.9.50

硒 → 3.141.0

如果我问的有什么不对的地方,我深表歉意。这是我在网站上的第一个问题。另外我对 python.

很陌生

我已经解决了这个问题。我使用了一个名为“pywinauto”的模块并使用了应用程序模块。然后我们进入一个循环,使用 connect() 方法连接到浏览器,并使用 exists() 方法判断对话框是否存在。我将这两种方法都放在循环中以每秒左右更新一次。一旦对话被检测到,我们就继续剩下的过程。该模块还有其他方法可以判断对话框是否存在以及是否位于屏幕顶部。但是这个解决方案对我有用。

代码:

import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pyautogui as auto
from pywinauto.application import Application as App
import warnings  # Import module to remove warnings


driver = webdriver.Chrome()

urls = [  # Sample urls.
    'https://unsplash.com/photos/MAqmEdUCq4k',
    'https://unsplash.com/photos/s7PhRjUJNeA',
]

# Declaring img_xpath and x for loop counting.
img_xpath = '//*[@id="app"]/div/div[2]/div/div[1]/div[3]/div/div/button/div[2]/img'
x = 0

# Ignore UserWarning.
warnings.simplefilter('ignore', category=UserWarning)

for url in urls:  # Loops through urls.
    x += 1
    time.sleep(2)
    driver.get(url)

    # Waits for the image element of the site to load.
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.XPATH, img_xpath))
    )

    # Declaring program path.
    chrome = r'C:\Program Files\Google\Chrome\Application\chrome.exe'

    # Calculates current browser center relative to screen position.
    win_pos = driver.get_window_position()
    win_size = driver.get_window_size()
    bcs = [  # bcs stands for Browser Center on Screen.
        win_pos['x'] + int(win_size['width'] / 2),
        win_pos['y'] + int(win_size['height'] / 2),
    ]

    # Using pyautogui to save image.
    auto.moveTo(bcs[0], bcs[1])
    auto.click()
    time.sleep(1)
    auto.moveTo(bcs[0], bcs[1])
    auto.rightClick()
    auto.moveTo(bcs[0] + 25, bcs[1] + 35)
    auto.click()
    y = 0
    while y != 10:
        y += 1
        time.sleep(1)
        app = App().connect(path=chrome)  # Connects script to Chrome.
        if app['Save As'].exists():  # Checks dialog box 'Save As' existence.
            auto.typewrite(f'Sample_{str(x)}')
            auto.press('enter')
            break

time.sleep(3)
driver.close()

补充说明。我对代码进行了一点点重构,使其工作更流畅。而且所有的预设和设置都几乎相同。

pywinauto 版本 → 0.6.8