Используя 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 схож с синтаксисом языка программирования Java, но они не связаны.
Я думаю, что в данный момент вы возлагаете на свою функцию слишком большую ответственность, отслеживая 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/