Не могу наскрести и распечатать ссылки на лету - PullRequest
0 голосов
/ 09 октября 2018

Я написал сценарий на node.js для удаления links различных заголовков с веб-страницы.Когда я выполняю свой следующий скрипт, я получаю undefined, напечатанный на консоли вместо links, который я ищу.Мои определенные селекторы точны.

Я не хочу помещать links в массив и возвращать результаты;скорее, я хочу напечатать их на лету.Поскольку я очень новичок в написании сценариев, использующих node.js в сочетании с puppeteer, я не могу понять, какую ошибку я совершаю.

Это мой сценарий ( Ссылка на этоsite ):

const puppeteer = require('puppeteer');
function run () {
    return new Promise(async (resolve, reject) => {
        try {
            const browser = await puppeteer.launch();
            const page = await browser.newPage();
            await page.goto("https://stackoverflow.com/questions/tagged/web-scraping");
            let url = await page.evaluate(() => {
                let items = document.querySelectorAll('a.question-hyperlink');
                items.forEach((item) => {
                    //would like to keep the following line intact 
                    console.log(item.getAttribute('href'));
                });
            })
            browser.close();
            return resolve(url);
        } catch (e) {
            return reject(e);
        }
    })
}
run().then(console.log).catch(console.error);

Следующий скрипт прекрасно работает, если я решу объявить пустой массив results, сохранить в нем очищенные ссылки и, наконец, вернуть results, ноЯ не хочу идти так.Я хотел бы придерживаться того, что я попробовал выше, как при печати результата на лету.

const puppeteer = require('puppeteer');
function run () {
    return new Promise(async (resolve, reject) => {
        try {
            const browser = await puppeteer.launch();
            const page = await browser.newPage();
            await page.goto("https://stackoverflow.com/questions/tagged/web-scraping");
            let urls = await page.evaluate(() => {
                let results = [];
                let items = document.querySelectorAll('a.question-hyperlink');
                items.forEach((item) => {
                    results.push({
                        url:  item.getAttribute('href'),
                    });
                });
                return results;
            })
            browser.close();
            return resolve(urls);
        } catch (e) {
            return reject(e);
        }
    })
}
run().then(console.log).catch(console.error);

Еще раз: мой вопрос, как я могу напечататьссылка типа console.log(item.getAttribute('href')); на лету без сохранения ее в массиве?

Ответы [ 3 ]

0 голосов
/ 10 октября 2018

На заметку,

  • async функция вернет обещание.
  • new Promise также вернет обещание.

ВклВ этой заметке вы можете просто использовать события .console, чтобы распечатать их на лету.Использование,

page.on("console", msg => console.log(msg.text()));
await page.evaluate(async => {
  console.log("I will be printed on node console too")
})

Расширенное использование обсуждалось на этот ответ .

0 голосов
/ 11 октября 2018

Чтобы запустить console.log() внутри evaluate(), просто скопируйте строку ниже, где вы определяете страницу

page.on('console', obj => console.log(obj._text));

, так что теперь весь фрагмент будет выглядеть следующим образом

const puppeteer = require('puppeteer');
function run () {
    return new Promise(async (resolve, reject) => {
        try {
            const browser = await puppeteer.launch();
            const page = await browser.newPage();
            page.on('console', obj => console.log(obj._text));
            await page.goto("https://stackoverflow.com/questions/tagged/web-scraping");
            let url = await page.evaluate(() => {
                let items = document.querySelectorAll('a.question-hyperlink');
                items.forEach((item) => {
                    //would like to keep the following line intact 
                    console.log(item.getAttribute('href'));
                });
            })
            browser.close();
            return resolve(url);
        } catch (e) {
            return reject(e);
        }
    })
}
run().then(console.log).catch(console.error);

Надеюсь, что эта помощь

0 голосов
/ 09 октября 2018

Библиотека выглядит немного неловко в использовании, но нашла правильный способ получить href из этого потока на github- https://github.com/GoogleChrome/puppeteer/issues/628

Рабочий код, который у меня есть, должен использовать await page.$$eval

async function getStackoverflowLinks(){
  return new Promise(async(resolve, reject)=>{
    console.log(`going to launch chromium via puppeteer`)
    const browser = await puppeteer.launch()
    console.log(`creating page/tab`)
    const page = await browser.newPage()
    await page.goto('https://stackoverflow.com/questions/tagged/web-scraping')
    console.log("fetched SO web-scraping, now parsing link href")

    let matches = await page.$$eval('a.question-hyperlink', hrefs=>hrefs.map((a)=>{
      return a.href
    })) // $$eval and map version, $$eval returns an array
    console.log("matches = ", matches.length)

    await browser.close()
    resolve(matches)
  })
}

getStackoverflowLinks()
.then(hrefs=>{
  console.log("hrefs: ", hrefs)
}) 
...