Вложение асинхронных функций с использованием NodeJS и Puppeteer - PullRequest
0 голосов
/ 04 июня 2018

Я создаю небольшой скребок, который очищает страницу результатов поиска для ссылок, а затем нажимает на каждую ссылку, чтобы очистить детали с получившейся страницы.Так что пока у меня есть два скребка.Один очищает страницу результатов, другой очищает страницу одного результата.Это усеченный скребок для страницы результатов:

const puppeteer = require('puppeteer');
var URLList = new Array;
let scrapeResults = async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('www.******.com/search_result');
    await page.waitFor(1000);

    const RESULT_SELECTOR ='#innerLeft ';
    const RESULT_CLASS = 'dspListings2';
    // scrape result page for URLs and put them in global URLList for further processing    
    URLList.push(results);
 browser.close();
};
scrapeResults();

, а это скребок для отдельной страницы результатов (после нажатия ссылки):

var details=''; //to be populated by scrapeListings function
const puppeteer = require('puppeteer');
URLList = [url1, url2, url3] // URLList is populated by the scrapeResults() function

URLList.forEach(async (url) => {
  const scrapeResultDetails = async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();

    await page.goto(url);
    await page.waitFor(1000);

    const RESULT_DETAILS_SELECTOR = '#details_layout > p';
    // scrape for  result details
    // assign result details to global details variable for further processing
    details = resultDetails;
 browser.close();
};
scrapeResultDetails();
});

Страница результатов возвращает списокURL-адреса, которые я затем хочу передать второму скребку, чтобы цикл forEach открывал каждый URL-адрес в списке для очистки деталей.

ПРОБЛЕМА Проблема в том, что я не могу вызватьвторой скребок, как это в первом.Оба имеют async wait, и это вызывает ошибки.Например, это то, что я пытался, и это не работает:

const puppeteer = require('puppeteer');
var URLList = new Array;
var details=''; //to be populated by scrapeListings function

let scrapeResults = async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('www.******.com/search_result');
    await page.waitFor(1000);

    const RESULT_SELECTOR ='#innerLeft ';
    const RESULT_CLASS = 'dspListings2';
    // scrape result page for URLs and put them in global URLList for further processing    
    URLList.push(results);

browser.close();

    URLList.forEach(async (url) => {
      const scrapeResultDetails = async () => {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();
        await page.goto(url);
        await page.waitFor(1000);
        const RESULT_DETAILS_SELECTOR = '#details_layout > p';
        // scrape for  result details
        // assign result details to global details variable for further processing
        details = resultDetails;
     browser.close();
    };
    scrapeResultDetails();
    });


};
scrapeResults();

Любые идеи ???Кроме того, это где я должен объявить свои глобальные переменные для циклов?

1 Ответ

0 голосов
/ 24 июня 2018

Вам нужно переключиться на [for-of][1] цикл вместо .forEach, потому что он отлично работает с асинхронными вызовами.Также вы пропустили пару await операторов.

  • Я настоятельно рекомендую вам прекратить использовать глобальные переменные и просто возвращать данные из функций.

Пожалуйста, смотрите мои комментарии:

const puppeteer = require('puppeteer');

var URLList = [];

var details=''; //to be populated by scrapeListings function

const scrapeResultDetails = async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(url);
    await page.waitFor(1000);
    const RESULT_DETAILS_SELECTOR = '#details_layout > p';

    //TODO: Global variables are bad, consider returning details from a function.
    details = resultDetails;

    //TODO: `await` was missing here
    await browser.close();
};

let scrapeResults = async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('www.******.com/search_result');
    await page.waitFor(1000);

    const RESULT_SELECTOR ='#innerLeft ';
    const RESULT_CLASS = 'dspListings2';

    URLList.push(results);

    // TODO: `await` has been missing.
    await browser.close();

    // TODO: Please use for-of loop here, you won't have any async prolems then
    for (let url of URLList) {
        // TODO: `details` is going to be populated after each iterration.
        // TODO: Although consider having `const details = await scrapeResultDetails(); here.
        await scrapeResultDetails();
    }
};
...