Skocz do zawartości
PL
Szukaj na Pecetowiczu
  • Utwórz konto

Node.js - webscraping problem z pętlą Promise'ów


Rekomendowane odpowiedzi

Witajcie

W wolnej chwili ogarniam sobie node.js i aktualnie kminię sobie webscraper piosenek z róznych stacji radiowych.

Posiadam takie bloki kodów:

Pobranie listy piosenek:

Spoiler

async function generateEskaJSON(){
    let singleSongs = [];

    await Axios.get("https://www.eska.pl/goraca20/")
    .then((response) => {
        if( response.status == 200 ){
            const $ = cheerio.load(response.data);

            $(".single-hit").find(".single-hit__title").each(async (i, el) => {
            // $(".single-hit").eq(10).find(".single-hit__title").each(async (i, el) => {
            // $(".single-hit:nth-child(1), .single-hit:nth-child(2), .single-hit:nth-child(3), .single-hit:nth-child(4), .single-hit:nth-child(5)").find(".single-hit__title").each(async (i, el) => {

                let item = $(el);
                if( item.text() != "Radio ESKA" ){
                    let title = item.text();
                    let authors = [];

                    item.next().find("a").map((a_i, a_el) => {
                        authors.push( $(a_el).text() );
                    });

                    authors = authors.join(" ");

                    singleSongs.push({
                        "id": i,
                        "title": title,
                        "authors": authors,
                        "video": {}
                    });
                }
            });
        }
    })
    .then(() => {
        let promises = [];
        singleSongs.forEach((el, i) => {
            promises.push( getYoutubeInfo(`${el.title} ${el.authors}`) );
        });
        
        Promise.all(promises).then((val) => {
            val.forEach((el, i) => {
                singleSongs[i].video = el;
            });

            fs.writeFile('eska.json', JSON.stringify(singleSongs), function (err) {
                if (err) return console.log(err);
                console.log('eska.json saved!');
            });
        });
    }).catch((err) => {
        console.error("############################# ERR0R:\n", err);
    });
}

 

Pobranie linków z Youtube (i innych dodatkowych danych):

Spoiler

async function getYoutubeInfo(query){
    console.log(query, "searching...");
    query = query.escapeDiacritics();
    query = query.split(" ").join("+");
    
    let url = "https://html.duckduckgo.com/html/?q=" + query + "+site:youtube.com";
    console.log(url);

    return await Axios.get(url, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.2; rv:20.0) Gecko/20121202 Firefox/21.0' }  })
    .then((response) => {

        if( response.status == 200 ){
            const $ = cheerio.load(response.data);

            let video = $(".result").eq(0).find(".result__url").text();
            video = video.trim();

            let video_id = video.split("?v=").pop();

            let thumbnails = {
                "big": `https://img.youtube.com/vi/${video_id}/hqdefault.jpg`,
                "medium": `https://img.youtube.com/vi/${video_id}/mqdefault.jpg`,
                "small": `https://img.youtube.com/vi/${video_id}/sddefault.jpg`,
            };

            return {
                "url": video,
                "id": video_id,
                "thumbnails": thumbnails
            };
        }
        else{
            return false;
        }

    }).catch((err) => {
        console.log("");
        console.error("############################# ERROR WITH QUERY:", url, "\nREASON:", err.response.status, err.response.statusText);
    });
}

 

I o ile pierwszy blok kodu działa poprawnie, to już pojawiają się problemy przy pobraniu informacji z YT.

W terminalu wygląda to tak:

Spoiler

obraz.png

Można zauważyć że po iluś zapytaniach wyskakuje 403 - i stąd pytanie czy to moja wina czy zabezpieczenie duckducka przed spamem/ddosem?

A jeśli zabezpieczenie to jak ogarnąć spowolnienie wywołania wszystkich promisów przy pomocy Promise.all? Jest ktoś w stanie nakierować bo internet mi nie pomaga (chyba przez moje zmęczenie)?

Z góry dzięki za odpowiedzi o7

Odnośnik do komentarza
Udostępnij na innych stronach

Możesz spróbować setInterval i scrapować po XYZ ms dany url.

Odnośnik do komentarza
Udostępnij na innych stronach

(edytowane)

Co do opoznienia akcji https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep

A i mala uwaga co do kodu z pobieraniem linkow do yt jak uzywasz async/await to juz nie potrzebnie uzywasz then. 

Wklejam link do pastebina, bo z niewiadomych mi przyczyn nie moge zapisac posta jak dodaje ten kod https://pastebin.pl/view/74251479

 
Edytowane przez Qwizi
Odnośnik do komentarza
Udostępnij na innych stronach

Dzięki chłopaki za odpowiedzi, w wolnej chwili sprawdzę co i jak i dam znać (może nawet z gotowcem) dla przyszłych pokoleń 😉

Odnośnik do komentarza
Udostępnij na innych stronach

Kontynuuj dyskusję

Dołącz do Pecetowicza, aby kontynuować dyskusję w tym wątku.

  • Dodaj nową pozycję...
  • Dodaj nową pozycję...