skip to Main Content

Using Node.js, I’m scraping a few different websites.
I can’t retrieve all the information I need on all the pages
I have little knowledge of Puppeteer, yet I tried to do it, watch lots of tutorials/forums
Can you help me?

const puppeteer = require('puppeteer');
const { MongoClient } = require('mongodb');

let queue = [
  'https://www.maxiscoot.com/fr/moto-50cc/haut-moteur/kit-cylindre/',
  'https://www.maxiscoot.com/fr/moto-50cc/haut-moteur/kit-cylindre/?p=1',
  'https://www.maxiscoot.com/fr/moto-50cc/haut-moteur/kit-cylindre/?p=2',
  'https://www.maxiscoot.com/fr/moto-50cc/haut-moteur/kit-cylindre/?p=3',
]

async function scrapeData() {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  let url
  while(url = queue.shift()){
    await page.goto(url)
  }

  // Naviguer vers la page cible
 // await page.goto('https://www.maxiscoot.com/fr/moto-50cc/haut-moteur/kit-cylindre/');

  // Attendre que les éléments contenant les données des produits soient chargés sur la page
  await page.waitForSelector('.element_artikel__price');
  await page.waitForSelector('.element_artikel__img');
  await page.waitForSelector('.element_artikel__description');
  await page.waitForSelector('.element_artikel__availability');
  await page.waitForSelector('.element_artikel__brand');
  await page.waitForSelector('.element_artikel__sku');

  // Extraire les données des produits en utilisant une fonction de la page
  const productsData = await page.evaluate(() => {
    const priceElements = document.querySelectorAll('.element_artikel__price');
    const imageElements = document.querySelectorAll('.element_artikel__img');
    const titleElements = document.querySelectorAll('.element_artikel__description');
    const stockElements = document.querySelectorAll('.element_artikel__availability');
    const brandElements = document.querySelectorAll('.element_artikel__brand');
    const referenceElements = document.querySelectorAll('.element_artikel__sku');

    const products = [];

    for (let i = 0; i < priceElements.length; i++) {
      const price = priceElements[i].textContent;
      const imageUrl = imageElements[i].getAttribute('src');
      const title = titleElements[i].textContent;
      const instock = stockElements[i].textContent;
      const brand = brandElements[i].textContent;
      const reference = referenceElements[i].textContent;

      products.push({ price, imageUrl, title, instock, brand, reference });
    }

    return products;
  });

  // Fermer le navigateur
  await browser.close();

  return productsData;
}
[1,2,3].map(() => scrapeData())

// Fonction pour enregistrer les données dans MongoDB
async function saveDataToMongoDB(data) {
  const uri = 'mongodb://127.0.0.1:27017'; // Changez cette URL en fonction de votre configuration MongoDB
  const client = new MongoClient(uri);

  try {
    await client.connect();
    console.log('Connecté à MongoDB');

    const database = client.db('scraped_data');
    const collection = database.collection('testing');

    // Supprimer les données existantes dans la collection
    await collection.deleteMany({});

    // Insérer les données dans la collection
    await collection.insertMany(data);

    console.log('Données enregistrées avec succès dans MongoDB');
  } catch (error) {
    console.error('Une erreur est survenue lors de la connexion ou de l'enregistrement dans MongoDB:', error);
  } finally {
    // Fermer la connexion MongoDB
    await client.close();
  }
}

// Appeler la fonction de scraping, enregistrer les données dans MongoDB et afficher les données des produits
scrapeData()
  .then((data) => {
    saveDataToMongoDB(data);
    console.log(data);
  })
  .catch((error) => console.error('Une erreur est survenue lors du scraping:', error));

I have tried almost everything and would like to retrieve information such as price, product title, part number, and image URL, and store everything on a database (MongoDB).

Edit :
it’s fine on all pages, but it doesn’t save all the information I need in my database

const puppeteer = require('puppeteer');
const { MongoClient } = require('mongodb');
process.setMaxListeners(0)

const BASE_URL = "https://www.maxiscoot.com/fr/moto-50cc/haut-moteur/kit-cylindre";

const PAGES = 4;

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

  //await page.goto(url)

  for (let i = 0; i < PAGES; i++) {
    await page.goto(`${BASE_URL}${i === 0 ? "/" : `/?p=${i}`}`);
    await page.waitForTimeout(6 * 1000);
  }
  

  // Naviguer vers la page cible
 // await page.goto('https://www.maxiscoot.com/fr/moto-50cc/haut-moteur/kit-cylindre/');

  // Attendre que les éléments contenant les données des produits soient chargés sur la page
  await page.waitForSelector('.element_artikel__price');
  await page.waitForSelector('.element_artikel__img');
  await page.waitForSelector('.element_artikel__description');
  await page.waitForSelector('.element_artikel__availability');
  await page.waitForSelector('.element_artikel__brand');
  await page.waitForSelector('.element_artikel__sku');

  // Extraire les données des produits en utilisant une fonction de la page
  const productsData = await page.evaluate(() => {
    const priceElements = document.querySelectorAll('.element_artikel__price');
    const imageElements = document.querySelectorAll('.element_artikel__img');
    const titleElements = document.querySelectorAll('.element_artikel__description');
    const stockElements = document.querySelectorAll('.element_artikel__availability');
    const brandElements = document.querySelectorAll('.element_artikel__brand');
    const referenceElements = document.querySelectorAll('.element_artikel__sku');

    const products = [];

    for (let i = 0; i < priceElements.length; i++) {
      const price = priceElements[i].textContent;
      const imageUrl = imageElements[i].getAttribute('src');
      const title = titleElements[i].textContent;
      const instock = stockElements[i].textContent;
      const brand = brandElements[i].textContent;
      const reference = referenceElements[i].textContent;

      products.push({ price, imageUrl, title, instock, brand, reference });
    }

    return products;
  });

  // Fermer le navigateur
  await browser.close();

  return productsData;
}


// Fonction pour enregistrer les données dans MongoDB
async function saveDataToMongoDB(data) {
  const uri = 'mongodb://127.0.0.1:27017'; // Changez cette URL en fonction de votre configuration MongoDB
  const client = new MongoClient(uri);

  try {
    await client.connect();
    console.log('Connecté à MongoDB');

    const database = client.db('scraped_data');
    const collection = database.collection('testing');

    // Supprimer les données existantes dans la collection
    await collection.deleteMany({});

    // Insérer les données dans la collection
    await collection.insertMany(data);

    console.log('Données enregistrées avec succès dans MongoDB');
  } catch (error) {
    console.error('Une erreur est survenue lors de la connexion ou de l'enregistrement dans MongoDB:', error);
  } finally {
    // Fermer la connexion MongoDB
    await client.close();
  }
}

// Appeler la fonction de scraping, enregistrer les données dans MongoDB et afficher les données des produits
scrapeData()
  .then((data) => {
    saveDataToMongoDB(data);
    console.log(data);
  })
  .catch((error) => console.error('Une erreur est survenue lors du scraping:', error));

2

Answers


  1. I think you are giving your function too much responsibility at the moment by keeping track of the URL. I would move this out of the function and save the base URL in a variable to prevent duplication:

    const BASE_URL =
      "https://www.maxiscoot.com/fr/moto-50cc/haut-moteur/kit-cylindre";
    
    const PAGES = 4;
    
    async function scrapeData(url) {
      // await page.goto(url)
    }
    
    for (let i = 0; i < PAGES; i++) {
      await scrapeData(`${BASE_URL}${i === 0 ? "/" : `/?p=${i}`}`);
    }
    
    Login or Signup to reply.
  2. Tried your code, it either brings me random number of elements between 7 and 60, out of the 200 it should return, so here is a re-write of your code, pay attention to notes in the scrapeData function

    Code : result

    const puppeteer = require('puppeteer');
    const { MongoClient } = require("mongodb");
    
    let browser;
    (async () => {
    
    
        async function scrapeData(url) {
            const browser = await puppeteer.launch();
            const page = await browser.newPage();
    
            await page.goto(url, { waitUntil: "networkidle2", timeout: 30000 });
            await page.waitForSelector(".element_product_grid"); // wait for the grid with products to load
    
            // if there is a accept cookies popup accept it 
            let cookie = await page.waitForSelector(".cmptxt_btn_yes");
            (!! cookie) ? await cookie.click() : null; 
    
            // get last page number
            let pages = await page.$eval("a.element_sr2__page_link:last-of-type", el => el.textContent.trim());
            pages = +pages - 1; // 4 pages but -1 as you're on the first page.
    
            let productsData = [];
            for (let i = 0; i <= pages; i++) {
    
                if (i != 0) { // dont need to goto page as it is the url were passing in.
                    await page.goto(`${url}?p=${i}`, { waitUntil: "networkidle2", timeout: 30000 });
                    await page.waitForSelector(".element_product_grid");
                }
    
                // get the repeating part
                let products = await page.$$("a.element_artikel");
    
                for (let product of products) {
                    // get data for each product
                    const price = await product.$eval('.element_artikel__price', el => el.textContent.trim());
                    const imageUrl = await product.$eval('.element_artikel__img', el => el.getAttribute("src"));
                    const title = await product.$eval('.element_artikel__description', el => el.textContent.trim());
                    const instock = await product.$eval('.element_artikel__availability', el => el.textContent.trim());
                    const brand = await product.$eval('.element_artikel__brand', el => el.textContent.trim());
                    const reference = await product.$eval('.element_artikel__sku', el => el.textContent.replace('Référence: ',''));
    
                    // pass the product data into our productsData array.
                    productsData.push({ price, imageUrl, title, instock, brand, reference });
                }            
            }
    
            await browser.close(); //close the browser.
            return productsData;
    
        }
    
    
        async function saveDataToMongoDB(data) {
            const uri = 'mongodb://127.0.0.1:27017'; // Changez cette URL en fonction de votre configuration MongoDB
            const client = new MongoClient(uri);
    
            try {
                await client.connect();
                console.log('Connecté à MongoDB');
    
                const database = client.db('scraped_data');
                const collection = database.collection('testing');
    
                // Supprimer les données existantes dans la collection
                await collection.deleteMany({});
    
                // Insérer les données dans la collection
                await collection.insertMany(data);
    
                console.log('Données enregistrées avec succès dans MongoDB');
            } catch (error) {
                console.error('Une erreur est survenue lors de la connexion ou de l'enregistrement dans MongoDB:', error);
            } finally {
                // Fermer la connexion MongoDB
                await client.close();
            }
        }
    
    
    
        
        let result = await scrapeData('https://www.maxiscoot.com/fr/moto-50cc/haut-moteur/kit-cylindre/')
    
        console.log(result);
        console.log(result.length);
    
        await saveDataToMongoDB(result);
    
        
    
    })().catch(err => console.error(err)); 
    
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search