Вопрос или проблема
Прежде чем объяснить свой код, хочу отметить, что он работал последние три года… так что что-то изменилось либо в последнем обновлении pup, либо на самом сайте.
Целевой URL: https://ecomm.one-line.com/one-ecom/manage-shipment/cargo-tracking
Целевой Iframe: document.querySelector(“#IframeCurrentEcom”)
Я пробовал:
попытка 1
const frame = await page.waitForFrame("https://ecomm.one-line.com/ecom/CUP_HOM_3301.do")
попытка 2, которую я использовал и которая больше не работает
const frame = await page.waitForSelector("#IframeCurrentEcom")
const iframeContext = frame.contentFrame();
попытка 3
const frame = await page.$("#IframeCurrentEcom");
const handle = frame.frameElement();
попытка 4: [3], потому что это целевой iframe среди всех iframes на этой странице
page.frames()[3]
Все вышеперечисленное может получить объект Iframe, но при попытке использовать evaluate, type… это просто не взаимодействует.
Единственный способ, который я нашел, чтобы это работало, был следующим
const cleanedReferences="123";
await parent.page.evaluate((cleanedReference) => {
const frame = document.getElementById("IframeCurrentEcom") as HTMLIFrameElement;
// @ts-ignore
frame.contentWindow.document.querySelector("#searchName").value = cleanedReference;
// @ts-ignore
frame.contentWindow.document.querySelector("#btnSearch").click();
// console.log(frame.contentWindow.document.querySelector("#searchName"))
}, cleanedReference)
Это означает, что мне придется извлекать все данные внутрь evaluate. У меня с этим нет проблем, но я хотел бы понять, что не так со всеми другими подходами…
Ответ или решение
Проблема, с которой вы столкнулись, связана с изменениями, которые могли произойти как в Puppeteer, так и на целевом веб-сайте. Ниже приведены возможные причины, почему ваш код не работает, и решения для исправления ситуации.
Возможные причины проблемы
-
Изменения на сайте: Существует вероятность, что сам веб-сайт изменил структуру или поведение своих iframe. Например, может измениться URL iframe или запрещены некоторые кросс-доменные запросы.
-
Изменения в версии Puppeteer: Если вы обновили Puppeteer, возможно, произошли изменения в API или в способах работы с iframe.
-
CORS и политика безопасности контента: Если iframe загружает страницу с другого домена, могут возникнуть проблемы с политикой кросс-доменных запросов (CORS), что может ограничивать доступ к контенту iframe.
Решения
1. Проверка доступности iframe и его контента
Попробуйте проверить, загружается ли iframe корректно. Вы можете использовать следующий код, чтобы убедиться, что iframe доступен:
const frame = await page.frames().find(f => f.url().includes("CUP_HOM_3301.do"));
if (frame) {
// Доступ к iframe.
} else {
console.error("Iframe не найден или недоступен.");
}
2. Исправление метода доступа к iframe
Если iframe загружается, но вы не можете взаимодействовать с его элементами, попробуйте использовать waitForSelector
на самом iframe, а затем доступ к нему через contentFrame
:
const frameHandle = await page.waitForSelector('#IframeCurrentEcom');
const frame = await frameHandle.contentFrame();
if (frame) {
const searchInput = await frame.waitForSelector("#searchName");
await searchInput.type("123");
const searchButton = await frame.waitForSelector("#btnSearch");
await searchButton.click();
} else {
console.error("Не удалось получить контекст iframe.");
}
3. Задержка перед взаимодействием
Иногда элементы внутри iframe загружаются с задержкой. Убедитесь, что вы дожидаетесь завершения загрузки страницы или определенных элементов:
await frame.waitForNavigation(); // Или waitForSelector для конкретного элемента
4. Запуск скрипта в контексте iframe
Если ничего не помогает, как вы уже сделали, можно выполнить код непосредственно внутри контекста iframe с помощью page.evaluate
. Обратите внимание, что это ограничивает доступ к переменным вне этого контекста, однако для простых операций это может быть наилучшим решением.
await page.evaluate((cleanedReference) => {
const frame = document.getElementById("IframeCurrentEcom");
const innerDoc = frame.contentDocument || frame.contentWindow.document;
innerDoc.querySelector("#searchName").value = cleanedReference;
innerDoc.querySelector("#btnSearch").click();
}, cleanedReferences);
Заключение
Ваша проблема, скорее всего, связана с изменениями на сайте или в Puppeteer. Проверяйте доступность iframe, используйте корректный метод взаимодействия с его контентом и не забывайте про задержки загрузки. Если ничего не помогает, взаимодействие через evaluate
остается рабочим решением. Надеюсь, это поможет вам разобраться с вашей проблемой!