【问题标题】:How to iterate through a supermarket website and getting the product name and prices?如何遍历超市网站并获取产品名称和价格?
【发布时间】:2020-10-11 01:04:15
【问题描述】:

我试图从超市网站的所有类别中获取所有产品名称和价格,我发现的所有教程都只针对一个 const url,我需要遍历所有这些。到目前为止,我已经得到了这个

const puppeteer = require('puppeteer');

async function scrapeProduct(url) {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(url);

    const [el2] = await page.$x('//*[@id="product-nonfood-page"]/main/div/div/div[1]/div[1]/div/div[2]/h1/div');
    const text2 = await el2.getProperty('textContent');
    const name = await text2.jsonValue();

    const [el] = await page.$x('//*[@id="product-nonfood-page"]/main/div/div/div[1]/div[1]/div/div[2]/div[2]/div[1]/div[2]/p[1]/em[2]/strong/text()');
    const text = await el.getProperty('textContent');
    const price = await text.jsonValue();

    console.log({name,price});

    await browser.close();
}

scrapeProduct('https://www.jumbo.com.ar/gaseosa-sprite-sin-azucar-lima-limon-1-25-lt/p'); 

只适用于一个人。我正在使用 nodejs 和 puppeteer。我怎样才能做到这一点?

【问题讨论】:

    标签: html node.js web-scraping puppeteer


    【解决方案1】:

    您可以尝试for...of 循环,使用单个浏览器实例和单个页面,这样爬虫就不会使服务器过载:

    const puppeteer = require('puppeteer');
    
    (async function main() {
      try {
        const browser = await puppeteer.launch();
        const [page] = await browser.pages();
    
        const urls = [
          'https://www.jumbo.com.ar/gaseosa-sprite-sin-azucar-lima-limon-1-25-lt/p',
          // ...
        ];
    
        for (const url of urls) {
          await page.goto(url);
    
          const [el2] = await page.$x('//*[@id="product-nonfood-page"]/main/div/div/div[1]/div[1]/div/div[2]/h1/div');
          const text2 = await el2.getProperty('textContent');
          const name = await text2.jsonValue();
    
          const [el] = await page.$x('//*[@id="product-nonfood-page"]/main/div/div/div[1]/div[1]/div/div[2]/div[2]/div[1]/div[2]/p[1]/em[2]/strong/text()');
          const text = await el.getProperty('textContent');
          const price = await text.jsonValue();
    
          console.log({name,price});
        }
    
        await browser.close();
      } catch (err) {
        console.error(err);
      }
    })();
    

    【讨论】:

    • 我真的很喜欢这种方法,有没有办法获取所有产品的所有 url 并将它们存储在数组中?还是会太慢/太消耗内存?
    • 通常抓取要么很慢(如果请求是连续的,如上例所示),要么占用内存/CPU,并且(通常)滥用服务器(如果所有或部分请求是并行的)。如果您使用连续的请求,您可以将任意数量的 URL 存储在一个数组中并逐个处理它们。如果需要提速,可以试试puppeteer-cluster
    【解决方案2】:

    你可以使用一个url数组和forEach:

    const puppeteer = require('puppeteer');
    
    const urls = [ 'https://www.jumbo.com.ar/gaseosa-sprite-sin-azucar-lima-limon-1-25-lt/p' ];
    
    urls.forEach(scrapeProduct);
    
    async function scrapeProduct(url) {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();
        await page.goto(url);
    
        const [el2] = await page.$x('//*[@id="product-nonfood-page"]/main/div/div/div[1]/div[1]/div/div[2]/h1/div');
        const text2 = await el2.getProperty('textContent');
        const name = await text2.jsonValue();
    
        const [el] = await page.$x('//*[@id="product-nonfood-page"]/main/div/div/div[1]/div[1]/div/div[2]/div[2]/div[1]/div[2]/p[1]/em[2]/strong/text()');
        const text = await el.getProperty('textContent');
        const price = await text.jsonValue();
    
        console.log({name,price});
    
        await browser.close();
    }
    

    【讨论】:

    • 这不是一个正确的答案。如果urls 数组中有一百个 URL,会发生什么?它们将同时运行。
    • @Vaviloff,是的,这是正确的。它们将同时运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    • 2023-03-09
    • 2021-01-07
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    相关资源
    最近更新 更多