Как я могу сказать моему скрипту Python дождаться появления диалогового окна «Сохранить как» в хроме перед выполнением следующего блока кода?

Я использовал selenium и pyautogui для загрузки изображений с веб-сайта. Логика моего кода работает с использованием селена для навигации по страницам нужных мне ссылок. И с помощью pyautogui я могу объединить их для совместной работы, чтобы автоматически щелкнуть правой кнопкой мыши и загрузить изображение (хотя и не идеально) и ввести его имя файла. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что диалоговое окно для сохранения изображения появляется слишком долго. Pyautogui не может ждать, пока оно всплывет, и просто вводит текст, который должен был быть введен вслепую. Мне трудно найти это и выяснить, как обнаружить всплывающее диалоговое окно. И я в настоящее время застрял с этой проблемой. Есть ли реальный способ заставить мою программу ждать, пока она не появится в самом селене? Или мне нужно использовать другой модуль в этом отношении? В таком случае, какой модуль я могу использовать?

Код для воспроизведения проблемы:

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()

Дополнительные примечания. В коде используется браузер Chrome с настройками по умолчанию.

Версии:

Питон → 3.8.5

PyAutoGUI → 0.9.50

селен → 3.141.0

Прошу прощения, если я что-то не так сделал, спрашивая. Это мой первый вопрос здесь на сайте. Также я новичок в python.


person 14thDovePin    schedule 10.10.2020    source источник


Ответы (1)


Я решил проблему. Я использовал модуль под названием 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

person 14thDovePin    schedule 13.10.2020