Puppeteer: очистка нескольких URL-адресов

Используя Node.js, я просматриваю несколько разных веб-сайтов. Я не могу получить всю необходимую мне информацию на всех страницах У меня мало знаний о Puppeteer, но я пытался это сделать, просмотрел много туториалов/форумов Вы можете помочь мне?

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.info('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.info('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.info(data);
  })
  .catch((error) => console.error('Une erreur est survenue lors du scraping:', error));

Я пробовал почти все и хотел бы получить информацию, такую ​​​​как цена, название продукта, номер детали и URL-адрес изображения, и сохранить все в базе данных (MongoDB).

Редактировать : это нормально на всех страницах, но не сохраняет всю необходимую мне информацию в моей базе данных

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.info('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.info('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.info(data);
  })
  .catch((error) => console.error('Une erreur est survenue lors du scraping:', error));

🤔 А знаете ли вы, что...
JavaScript позволяет создавать расширения для веб-браузеров, улучшая их функциональность.


50
2

Ответы:

Я думаю, что в данный момент вы возлагаете на свою функцию слишком большую ответственность, отслеживая URL-адрес. Я бы убрал это из функции и сохранил базовый URL в переменной, чтобы предотвратить дублирование:

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}`}`);
}

Решено

Попробовал ваш код, он либо приносит мне случайное количество элементов от 7 до 60, из 200 он должен возвращаться, так что вот переписывание вашего кода, обратите внимание на примечания в функции scrapeData

Код : новый результат

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

let browser;
(async () => {

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

        await page.goto(url, { waitUntil: "networkidle2", timeout: 30000 });
        await page.waitForSelector(".element_product_grid");

        // if there is a popup accept it 
        let cookie = await page.waitForSelector(".cmptxt_btn_yes");
        (!! cookie) ? await cookie.click() : null; 

        let pages = 0; // set page to zero if page doesn't exist        
        let selector = "a.element_sr2__page_link:last-of-type";
        if (!! await page.$(selector)) { // does this element exist?
            pages = await page.$eval(selector, el => el.textContent.trim()); // get last page number
            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) { // skip page 1
                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 link = await product.evaluate(el => el.getAttribute('href'));
                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: ',''));

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

        await browser.close();
        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.info('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.info('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();
        }
    }

    async function getLinks(url) {
        const browser = await puppeteer.launch({ headless: "new" });
        const page = await browser.newPage();

        await page.goto(url, { waitUntil: "networkidle2", timeout: 30000 });
        await page.waitForSelector("header");

        // get links
        let links = await page.$$eval("a.sb_dn_flyout_menu__link", el => el.map( x => {return {link : x.getAttribute('href'), keyword : x.textContent.trim()}}));
        // filter links
        let filterArr = ["/haut-moteur/"]; // you need to manually write all sections you need to this array eg. look at the links on the site e.g. /pot-d-echappement/..        
        links = links.filter(x => {return filterArr.some(el => x.link.includes(el))});
        return links;
    }


    let urls = await getLinks("https://www.maxiscoot.com/fr/"); //get all relative links

    let allResults = []; 
    for (let url of urls) { // process the links
        let result = await scrapeData(url.link);
        allResults.push(result);
    }

    allResults = allResults.flat(); // flatten array

    console.info(allResults);
    console.info(allResults.length);

    await saveDataToMongoDB(allResults);

})().catch(err => console.error(err)); 

примечание: вышеперечисленное занимает некоторое время, чтобы получить продукты, всего 5694 для /haut-moteur/