LINUX.ORG.RU

Selenium-webdriver не работает переключение по id

 ,


0

1

Столкнулся с неожиданным поведением Webdriver’a: При попытке передать константу в frame() в команде driver.switchTo().frame() Он выдаёт ошибку что id не может быть строкой. Хотя в документации селениума как раз передаётся строка и должно работать

https://imgur.com/oLGHFds - код

https://imgur.com/vC0B61p - ошибка

Есть идеи куда копать?


сначала читать до просветления. потом копать. везде. от первой зацепки до последней. что-то да и сыграет

https://stackoverflow.com/questions/20069737/how-to-identify-and-switch-to-the-frame-in-selenium-webdriver-when-frame-does-no

https://stackoverflow.com/questions/47467518/is-it-possible-to-switch-to-an-element-in-a-frame-without-using-driver-switchto/47472200

anonymous
()
Ответ на: комментарий от anonymous

Спасибо,конечно за попытку помочь, но там по сути проблема в другом. Даже там в решении показывают, что в параметр id передаётся строка, и ятоже передаю строку и явно пробовал и в виде переменной, но Селениум почему-то на это ругается.

«потом копать. везде. от первой зацепки до последней»

я сейчас как раз на этой стадии

DJem
() автор топика
Ответ на: комментарий от vedowi6419

я и кавычил его, и шаблонную строку с переменой вставлял, но он ругается что это строка, хотя там и должна быть строка, вот в чём косяк!

DJem
() автор топика
Ответ на: комментарий от DJem

сложно сказать без куска кода. switchTo().frame() всю жизнь работал как надо, так что либо в жаваскриптовой реализации кто-то накосячил (сомнительно) либо твой код не совсем код. что мешает выложить тебе исходник целиком и выхлоп целиком вместо скриншотов?

vedowi6419
()
Ответ на: комментарий от vedowi6419

Да ничего не мешает, вот он

const {Builder, By, WebElement} = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const path = require('path');
const fs = require('fs');

let opts = new chrome.Options()
    opts.setMobileEmulation({
        deviceMetrics: {
            width: 320,
            height: 480,
            pixelRatio: 2.0,
        },
        enableTouchEvents: true 
        })


 async function getAds() {
    let driver = await new Builder()
        .forBrowser('chrome')
        .setChromeOptions(opts)
        .build();

    try {
        // await driver.manage().window().setRect({ width: 1280, height: 800 });
        await driver.get('https://www.w3schools.com/html/default.asp')                                                            //url
        await driver.sleep(15000)
        await driver.executeScript("window.scrollTo(0, document.body.scrollHeight)")
        await driver.sleep(10000)
            
        let newAd = await driver.findElement(By.css('*[data-google-query-id]'))   
        let getIframe = await newAd.findElement(By.css('iframe'))
        let iframeName = await getIframe.getAttribute('name')
        console.log(iframeName);
        let currentIframe = driver.switchTo().frame(iframeName)
            console.log(await currentIframe)
          
        let getIFrameHtml = await driver.findElement(By.css('html'))
        let iframeHtml = await getIFrameHtml.getAttribute('outerHTML')
        console.log(await iframeHtml);

    } catch(err) {
        throw new Error(err.message);
    }
};
getAds()
DJem
() автор топика
Ответ на: комментарий от vedowi6419

Конечно, это ж первый, и по сути, единственный дословный случай. Но там другой движок, и решение под моё никак не подходит. Я пробовал

DJem
() автор топика
Ответ на: комментарий от DJem

движок в данном случае не так важен — это прокидывается ошибка от вебдрайвера, инвалид аргумент со странным текстом

ну если экранирование не помогает (хотя моя ставка была на него, все-таки там и слэши и всякое барахло в name) — могу посоветовать только играть с версиями.

vedowi6419
()
Ответ на: комментарий от DJem

так, погуглил. узнал про w3c mode, прочувствовал много чужой боли. попробуй

1. откатить хромдрайвер на 75- версию, попробовать в ней, потом попробовать в FF

2. попробовать (всё-таки) на фрейме с менее заковыристым неймом

3. передать не нейм, а элемент целиком

vedowi6419
()
Последнее исправление: vedowi6419 (всего исправлений: 1)
Ответ на: комментарий от vedowi6419

В name кстати нормальная строка приходит. Я пробовал её явно задавать как в документации и в других туториалах описано. Всё равно пишет, что id не может быть строкой

DJem
() автор топика
Ответ на: комментарий от DJem

ну мне name = «google_ads_iframe_/22152718/sws-hb//w3schools.com//main_leaderboard_1» активно не нравится, но тут, скорее всего, не в нем дело

vedowi6419
()
Ответ на: комментарий от vedowi6419

1 находил это решение, пробовал откатить, там всё с гемороем — это ничего не дало, да и браузер нужен актуальный по проекту. Файрфокс тоже к сожалению не подойдёт из-за проекта. 2 неймы всякие передавал и явно и через переменную — тот же результат. 3 единственное, что хоть как-то давало результат: Я передавал вместо iframeName всё значение

await newAd.findElement(By.css('iframe'))

На одном сайте скрипт работает дальше и выдаёт конечный html, Но на большинстве через такой способ пишет, что нет элементов с тегом iframe, хотя их родителя он находит через предыдущий идентификатор

DJem
() автор топика
Ответ на: комментарий от DJem

1 — это не как постоянное решение, а для локализации проблемы. если это работает в FF и не работает с хромдрайвером — то скорее всего проблема в w3c моде, от этого уже можно плясать

3 — ты путаешь теплое с мягким — если у тебя не резолвится getIframe на каких-то сайтах — то это вопрос уже поиска, не переключения. получение iframe никогда не было простым, тут уж ничего не поделаешь, пока оно подгрузится (в отличие от родителя, он-то на отрендеренной странице уже есть).

сорян, сам бы проверил, но ничего вебдрайвероподобного на компе давно нет, приходится дебажить по памяти.

vedowi6419
()
Ответ на: комментарий от vedowi6419

На счёт первого понял а с третьим смотри какое дело. Если использовать вот этот код

let newAd = await driver.findElements(By.css('*[data-google-query-id]'))   
    for(let e of newAd ) {                     
        res.push(await e.getAttribute('outerHTML')) 
       }

То он находит мне все нужные мне iframe(либо сразу, либо в родительском блоке div), но, на большинстве сайтов, он не выкачивает их внутрений html т.е. по поиску он нормально работает и находит их, эти элементы там есть.

А когда использую через тот костыльный метод он начинает ругаться, что iframe там нет.
И вот почему с переключением на фреймы такие заморочки не понимаю

DJem
() автор топика
Ответ на: комментарий от DJem

потому что фреймы — порождение сотоны, это если кратко. ты скриншоты делаешь, когда фрейм не находится — он в браузере уже есть? если есть (и у тебя нет проблемы с тем, что страница не успевает целиком загрузиться) — то не вижу проблемы с тем, чтобы в него свичнуться: дождись что у тебя придет IFrameHtml, попутно избавься от let и сделай для него нормальный пейджобжект с проверкой, а то в let у тебя может быть что угодно. когда пейджобжект точно есть — переключайся в него через driver.switchTo().frame(FuckingAdFrame IFrameHtml)

насколько я понял проблему — в хромдрайвере переписали метод switchTo и в нем проблемы с авторезолвом айдишника, но топорная передача объекта должна работать (хотя надо глянуть код, это ересь какая-то)

vedowi6419
()
Ответ на: комментарий от vedowi6419

Понял, спасибо большое за помощь и советы. Буду пробовать

DJem
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.