【问题标题】:How to scrape multi-level links using puppeteer js?如何使用 puppeteer js 抓取多级链接?
【发布时间】:2018-07-29 14:16:52
【问题描述】:

我正在使用 Puppeteer 抓取网站页面的表格行。我有代码来抓取内容并将它们分配给表中每个对象的对象。在每个表格行中,我需要在新页面(puppeteer)中打开一个链接,然后抓取特定元素,然后将其分配给同一个对象,并将带有新键的整个对象返回给 puppeteer。 Puppeteer 怎么可能?

async function run() {
    const browser = await puppeteer.launch({
        headless: false
    })
    const page = await browser.newPage()

    await page.goto('https://tokenmarket.net/blockchain/', {waitUntil: 'networkidle0'})
    await page.waitFor(5000)
    var onlink = ''
    var result = await page.$$eval('table > tbody tr .col-actions a:first-child', (els) => Array.from(els).map(function(el) {

        //running ajax requests to load the inner page links.
     $.get(el.children[0].href, function(response) {
            onlink = $(response).find('#page-wrapper > main > div.container > div > table > tbody > tr > td:nth-child(2)').text()
        })



        return {
            icoImgUrl: el.children[0].children[0].children[0].currentSrc,
            icoDate: el.children[2].innerText.split('\n').shift() === 'To be announced' ? null : new Date( el.children[2].innerText.split('\n').shift() ).toISOString(),
            icoName:el.children[1].children[0].innerText,
            link:el.children[1].children[0].children[0].href,
            description:el.children[3].innerText,
            assets :onlink
        }

    }))

    console.log(result)

    UpcomingIco.insertMany(result, function(error, docs) {})


    browser.close()
}

run()

【问题讨论】:

    标签: node.js web-scraping puppeteer


    【解决方案1】:

    如果您尝试同时为每个 ICO 页面打开一个新选项卡,您最终可能会同时加载 100 多个页面。

    所以你能做的最好的事情就是先收集 URL,然后循环访问它们。

    这也使代码保持简单易读。

    例如(请看我的 cmets):

    const browser = await puppeteer.launch({ headless: false });
    
    const page = await browser.newPage();
    
    await page.goto('https://tokenmarket.net/blockchain/');
    
    // Gather assets page urls for all the blockchains
    const assetUrls = await page.$$eval(
      '.table-assets > tbody > tr .col-actions a:first-child',
      assetLinks => assetLinks.map(link => link.href)
    );
    
    const results = [];
    
    // Visit each assets page one by one
    for (let assetsUrl of assetUrls) {
      await page.goto(assetsUrl);
    
      // Now collect all the ICO urls.
      const icoUrls = await page.$$eval(
        '#page-wrapper > main > div.container > div > table > tbody > tr > td:nth-child(2) a',
        links => links.map(link => link.href)
      );
    
      // Visit each ICO one by one and collect the data.
      for (let icoUrl of icoUrls) {
        await page.goto(icoUrl);
    
        const icoImgUrl = await page.$eval('#asset-logo-wrapper img', img => img.src);
        const icoName = await page.$eval('h1', h1 => h1.innerText.trim());
        // TODO: Gather all the needed info like description etc here.
    
        results.push([{
          icoName,
          icoUrl,
          icoImgUrl
        }]);
      }
    }
    
    // Results are ready
    console.log(results);
    
    browser.close();
    

    【讨论】:

    • 这很完美!但是,我还不清楚一件事。有没有办法将浏览器上下文中的异步内容返回到我的程序?考虑我代码的 $$eval 中的异步获取请求。在我的示例中,我将如何从 ajax 请求的成功处理程序中返回内容?回调、承诺或任何其他方式有可能吗?我认为,在使用 node.js 时可能会出现这种情况。
    • 正如文档所说,您可以从评估返回承诺,它会等到承诺解决。请参阅:github.com/GoogleChrome/puppeteer/blob/master/docs/…@SmokingSheriff
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    • 2017-12-24
    • 1970-01-01
    • 1970-01-01
    • 2019-08-21
    • 1970-01-01
    • 2021-06-22
    相关资源
    最近更新 更多