Как дождаться полной загрузки изображения?

python
selenium
Теги: #<Tag:0x00007fedba1d85d0> #<Tag:0x00007fedba1d8490>

(тест Тестович) #1

Ребят, подскажите пожалуйста (опыта у меня совсем нет), каким способом можно дождаться загрузки изображения, если у изображения есть атрибут alt (из-за этого размеры изображения больше 0, да и размеры самого изображения заданы инлайного)? Получается, что селениум видит данное изображение, до того как оно загрузилось, скринит и идет дальше. В результате чего, скрин производится до загрузки изображения с отображением значения атрибута alt. А мне как раз важен скрин с корртекным изображением


(Дмитрий Мирошник) #2

Можно попробовать отловить GET запрос данной картинки и дождаться его завершения.
Не факт, что самый оптимальный способ.


(Bolatbek) #3

Или попробовать этот рецепт


(Sergei Chipiga) #4

Привет!

Думаю, что в реализации selenium-клиента почти на всех языках есть методы типа waitUntil & execute (executeScript). Можно попробовать их использовать, чтобы опрашивать страницу браузера, загрузились ли картинки или нет. Н-р на JS я бы сделал приблизительно так:

var timeout = 60000; // ms
var errMsg = `Images aren't loaded after waiting ${timeout} ms`;

webdriver.waitUntil(function () {
    return webdriver.execute(function () {
        /* executed in browser context */
        for (var img of document.getElementsByTagName("img")) {
            if (img.complete !== true) return false;
        };
        return true;
    });
}, timeout, errMsg);

Cудя по документации на python это будет примерно так:

from selenium.webdriver.support.ui import WebDriverWait

WebDriverWait(driver, 60).until(
    return driver.execute_script('''
        for (var img of document.getElementsByTagName("img")) {
            if (img.complete !== true) return false;
        };
        return true;    
    ''')
)

(тест Тестович) #6

спасибо всем, надо видимо почитать документацию по работе с DOM


(Bolatbek) #7

По ссылке более универсальный вариант:

public static void waitUntilVisible(WebDriver webDriver, By locator) {
    WebDriverWait driverWait = new WebDriverWait(webDriver, TIMEOUT);
    WebElement el = webDriver.findElement(locator);
    driverWait.until(
        new Predicate<WebDriver>() {
            public boolean apply(WebDriver driver) {
                return ((JavascriptExecutor)driver).executeScript("return arguments[0].complete", el);
            }
        }
    );
}

(Sergei Chipiga) #8

@Mes А чем он универсальнее? Он возвращает этот статус для одного объекта типа img, и не опрашивает все элементы. И кроме того он требует на один запрос больше, чтобы извлечь элемент по селектору.

Если говорить про универсальность, то нужно сделать что-то вроде, чтобы обеспечить опциональную проброску селектора или последовательности селекторов:

webdriver.waitUntil(function () {
    return webdriver.execute(function (selectors) {
        /* executed in browser context */
        if (selectors && selectors.length) {
            for (var sel of selectors) {
                for (var el of document.querySelectorAll(sel)) {
                    if (el.complete !== true) return false;
                };
            };
        } else {
            for (var img of document.getElementsByTagName("img")) {
                if (img.complete !== true) return false;
            };
        };
        return true;
    }, selectors);
}, timeout, errMsg);

(Bolatbek) #9

Опс, я похоже задачу изначально неверно воспринял. Ваша правда.