Usuwam dane z Facebook Marketplace. Chcę użyć Puppeteer, aby: 1) Utworzyć listę węzłów wszystkich moich nazw ofert 2) Użyj pętli for, aby kliknąć nazwę oferty, aby wyświetlić dodatkowe okienko informacyjne 3) Zeskanuj dane z wyskakującego okienka i zapisz je do tablicy 4) Zamknij wyskakujące okienko 5) Powtórz proces dla każdego wpisu, aby zwrócić dane tablicy
Oto mój kod, który obecnie nie działa:
const postClick = async (page) => {
await page.evaluate(() => {
//Capture the nodelist of listing names
let buttons = document.querySelectorAll('#marketplace-modal-dialog-title');
//If the nodelist of listings exist
if(buttons.length) {
//Loop through all listing names
for(let i = 0; i < buttons.length; i++) {
let button = buttons[i];
//click the listing
button.click();
//wait for the X button to appear
async (page) => {
await page.waitForSelector("button._3-9a._50zy._50-1._50z_._5upp._42ft");
await page.waitFor(5000)
await page.evaluate(() =>{
//click the X button
document.querySelector('button._3-9a._50zy._50-1._50z_._5upp._42ft').click();
});
}
}
}
});
}
Następnie wzywam to tuż przed zamknięciem przeglądarki tutaj:
await postClick(page);
Nie otrzymuję błędu, ale kod nie działa. Jak tylko wyjmę pętlę for i pozwolę przycisk = przyciski [0]; kod działa tylko dla pierwszej pozycji.
1 odpowiedź
#marketplace-modal-dialog-title
przechwytywanie elementu według identyfikatora sugeruje, że na stronie istnieje tylko 1 element, ponieważ identyfikator powinien być unikalny ... Nie wiem, dlaczego facebook ma wiele elementów z tym samym identyfikatorem, ale być może js reaguje na to i przechwytuje 1 element tylko
Spróbuj przechwytywać przyciski według klasy
let buttons = await page.$$('._50f4._50f7');
Lub jakikolwiek odpowiednik tego document.querySelectorAll
(możesz przechwycić wiele elementów do tablicy za pomocą page.$$
)
Również buttons.length
zwraca liczbę przez if(buttons.length)
sprawdzasz true
lub false
, a nie liczbę, więc powinno być if(buttons.length > 0)
, chociaż niektóre języki biorą pod uwagę {{X5 }} jako fałszywe i to działa, ale ogólnie nie jest to dobry pomysł
Nie mogę teraz przetestować tego kodu, mogą wystąpić błędy Soem, ale tak bym zrobił
// capture all the items in the marketplacee
let elements = await page.$$('._7yc._4e36');
// loop trough items
for (let i = 0; i < elements.length; i++) {
// capturing button and its text
let button = await elements[i].$('._50f4._50f7');
let button_text = await page.evaluate(el => el.innerText, button);
console.log(button_text);
// click the button
await button.click();
// wait for the popup to show up
await page.waitForSelector('.uiLayer' , { visible: true , timeout: 0 });
//close the popup
await page.click('._3-9a._50zy');
}
Zauważyłem również, że adres URL strony zmienia się po otwarciu wyskakującego okienka, co może powodować problemy i powodować błąd Execution context was destroyed
... więc może być konieczne zebranie wszystkich linków i otwarcie ich w nowych kartach
page.$$
zwraca tablicę ElementHandle
. spójrz na dokumentację lalkarza github.com/ lalkarz/lalkarz/blob/v2.0.0/docs/….
for(int i = 0; i < buttons.length; i++) { let button = buttons[i];
var i; for (i = 0; i < buttons.length; i++) { let button = buttons[i];