- Estrazione dei dati da Amazon
- Ciclo di Estrapolazione di tutti i prodotti ed aggiornamento dei campi scraped e scraped_updated - Creazione file CSV con i campi modificati.
This commit is contained in:
@@ -5,6 +5,9 @@ const Product = require('../models/product');
|
||||
const ProductInfo = require('../models/productInfo');
|
||||
|
||||
const tools = require('../tools/general');
|
||||
const shared_consts = require('../tools/shared_nodejs');
|
||||
|
||||
const fs = require('fs').promises; // 👈 Usa il modulo promises
|
||||
|
||||
class AmazonBookScraper {
|
||||
constructor() {
|
||||
@@ -23,7 +26,7 @@ class AmazonBookScraper {
|
||||
// altri header se necessario
|
||||
},
|
||||
});
|
||||
return data;
|
||||
return { html: data, url };
|
||||
} catch (err) {
|
||||
console.error(`Errore fetching ISBN ${isbn10}:`, err.message);
|
||||
return null;
|
||||
@@ -57,7 +60,7 @@ class AmazonBookScraper {
|
||||
}
|
||||
}
|
||||
|
||||
async extractData(myproduct, html) {
|
||||
async extractData(myproduct, html, url) {
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
const productInfo = await ProductInfo.findOne({ _id: myproduct.idProductInfo }).lean();
|
||||
@@ -107,99 +110,258 @@ class AmazonBookScraper {
|
||||
return {
|
||||
titolo: title,
|
||||
...(titoloOriginale ? { titoloOriginale } : {}),
|
||||
...(sottotitolo ? { sottotitolo } : {sottotitolo: ''}),
|
||||
numpagine,
|
||||
misure,
|
||||
edizione,
|
||||
data_pubblicazione,
|
||||
editore: publisher,
|
||||
...(sottotitolo ? { sottotitolo } : { sottotitolo: '' }),
|
||||
...(numpagine ? { numpagine } : {}),
|
||||
...(misure ? { misure } : {}),
|
||||
...(edizione ? { edizione } : {}),
|
||||
...(data_pubblicazione ? { data_pubblicazione } : {}),
|
||||
...(publisher ? { editore: publisher } : {}),
|
||||
url: `<a href="${url}" target="_blank">URL</a>`,
|
||||
};
|
||||
}
|
||||
|
||||
async scrapeISBN(myproduct, isbn, options) {
|
||||
const isbn10 = this.isbn13to10(isbn);
|
||||
const html = await this.fetchPageISBN10(isbn10);
|
||||
if (!html) return null;
|
||||
try {
|
||||
const isbn10 = this.isbn13to10(isbn);
|
||||
const res = await this.fetchPageISBN10(isbn10);
|
||||
if (!res) {
|
||||
await Product.findOneAndUpdate(
|
||||
{ _id: myproduct._id },
|
||||
{ $set: { scraped: true, scraped_error: true } },
|
||||
{ upsert: true, new: true, includeResultMetadata: true }
|
||||
).lean();
|
||||
|
||||
const data = await this.extractData(myproduct, html);
|
||||
return null;
|
||||
}
|
||||
const html = res.html;
|
||||
if (!html) return null;
|
||||
|
||||
if (!options?.update) return data;
|
||||
let updated = null;
|
||||
let risupdate = null;
|
||||
|
||||
const arrvariazioni = myproduct.arrvariazioni || [];
|
||||
let index = -1;
|
||||
const data = await this.extractData(myproduct, html, res.url);
|
||||
|
||||
if (arrvariazioni.length === 1) {
|
||||
index = 0;
|
||||
} else {
|
||||
index = arrvariazioni.findIndex((v) => v.versione === shared_consts.PRODUCTTYPE.NUOVO);
|
||||
if (index < 0) index = 0;
|
||||
if (!options?.update) return data;
|
||||
|
||||
let recModificato = {};
|
||||
|
||||
const arrvariazioni = myproduct.arrvariazioni || [];
|
||||
let index = -1;
|
||||
|
||||
if (arrvariazioni.length === 1) {
|
||||
index = 0;
|
||||
} else {
|
||||
index = arrvariazioni.findIndex((v) => v.versione === shared_consts.PRODUCTTYPE.NUOVO);
|
||||
if (index < 0) index = 0;
|
||||
}
|
||||
|
||||
const productInfo = {};
|
||||
let aggiornaDataPubb = false;
|
||||
|
||||
let aggiornaPages = false;
|
||||
let aggiornaMisure = false;
|
||||
let aggiornaEdizione = false;
|
||||
|
||||
let aggiornaProductInfo = false;
|
||||
let aggiornaSottotitolo = false;
|
||||
|
||||
if (index !== -1) {
|
||||
const variante = arrvariazioni[index];
|
||||
|
||||
// Determina se aggiornare pagine
|
||||
aggiornaPages = (!options.aggiornasoloSeVuoti || !variante.pagine || variante.pagine === 0) && data.numpagine;
|
||||
if (aggiornaPages) {
|
||||
variante.pagine = Number(data.numpagine);
|
||||
recModificato['pagine'] = variante.pagine;
|
||||
}
|
||||
|
||||
// Determina se aggiornare misure
|
||||
aggiornaMisure = (!options.aggiornasoloSeVuoti || !variante.misure) && data.misure;
|
||||
if (aggiornaMisure) {
|
||||
variante.misure = data.misure;
|
||||
recModificato['misure'] = variante.misure;
|
||||
}
|
||||
|
||||
// Determina se aggiornare edizione
|
||||
aggiornaEdizione = (!options.aggiornasoloSeVuoti || !variante.edizione) && data.edizione;
|
||||
if (aggiornaEdizione) {
|
||||
variante.edizione = data.edizione;
|
||||
recModificato['edizione'] = variante.edizione;
|
||||
}
|
||||
}
|
||||
|
||||
// Determina se aggiornare data pubblicazione
|
||||
const currentDatePub = myproduct.idProductInfo.date_pub;
|
||||
aggiornaDataPubb =
|
||||
(!options.aggiornasoloSeVuoti || !tools.isDateValid(currentDatePub)) &&
|
||||
tools.isDateValid(data.data_pubblicazione);
|
||||
if (aggiornaDataPubb && data.data_pubblicazione) {
|
||||
productInfo.date_pub = new Date(data.data_pubblicazione);
|
||||
}
|
||||
|
||||
aggiornaSottotitolo = (!options.aggiornasoloSeVuoti || !myproduct.idProductInfo.sottotitolo) && data.sottotitolo;
|
||||
if (aggiornaSottotitolo && data.sottotitolo) {
|
||||
productInfo.sottotitolo = data.sottotitolo;
|
||||
}
|
||||
|
||||
aggiornaSottotitolo = false; // !! PER ORA LO DISATTIVO PERCHE' non esiste sempre il sottotitolo in un libro.
|
||||
|
||||
// Aggiorna arrvariazioni se pagine o misure sono cambiati
|
||||
const aggiornadati = aggiornaPages || aggiornaMisure || aggiornaEdizione;
|
||||
|
||||
aggiornaProductInfo = aggiornaDataPubb || aggiornaSottotitolo;
|
||||
|
||||
if (aggiornadati) {
|
||||
updated = await Product.findOneAndUpdate(
|
||||
{ _id: myproduct._id },
|
||||
{ $set: { arrvariazioni, scraped: true, scraped_updated: true, scraped_date: new Date() } },
|
||||
{ upsert: true, new: true, includeResultMetadata: true }
|
||||
);
|
||||
} else if (aggiornaProductInfo) {
|
||||
if (!tools.isObjectEmpty(productInfo)) {
|
||||
// Aggiorna il flag che ho modificato i dati
|
||||
updated = await Product.findOneAndUpdate(
|
||||
{ _id: myproduct._id },
|
||||
{ $set: { scraped: true, scraped_updated: true, scraped_date: new Date() } },
|
||||
{ upsert: true, new: true, includeResultMetadata: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!updated) {
|
||||
const upd = await Product.findOneAndUpdate(
|
||||
{ _id: myproduct._id },
|
||||
{ $set: { scraped: true, scraped_date: new Date() } },
|
||||
{ upsert: true, new: true, returnDocument: 'after' }
|
||||
);
|
||||
console.log('upd', upd);
|
||||
}
|
||||
|
||||
if (aggiornaProductInfo) {
|
||||
// Aggiorna productInfo se contiene dati
|
||||
if (!tools.isObjectEmpty(productInfo)) {
|
||||
risupdate = await ProductInfo.findOneAndUpdate(
|
||||
{ _id: myproduct.idProductInfo },
|
||||
{ $set: productInfo },
|
||||
{ new: true, upsert: true, includeResultMetadata: true }
|
||||
).lean();
|
||||
}
|
||||
// console.log('risupdate', risupdate);
|
||||
}
|
||||
|
||||
const concatenatedProduct = {
|
||||
...recModificato,
|
||||
...productInfo,
|
||||
};
|
||||
|
||||
if (updated) {
|
||||
console.log(' DATI AGGIORNATI:', JSON.stringify(concatenatedProduct));
|
||||
}
|
||||
|
||||
return { data, updated: this.isRecordAggiornato(updated) || this.isRecordAggiornato(risupdate) };
|
||||
} catch (error) {
|
||||
console.error('Errore in scrapeISBN:', error?.message);
|
||||
return { data: null, updated: false, error: 'Errore in scrapeISBN:' + error?.message };
|
||||
}
|
||||
|
||||
const productInfo = {};
|
||||
let aggiornaDataPubb = false;
|
||||
|
||||
let aggiornaPages = false;
|
||||
let aggiornaMisure = false;
|
||||
let aggiornaEdizione = false;
|
||||
|
||||
if (index !== -1) {
|
||||
const variante = arrvariazioni[index];
|
||||
|
||||
// Determina se aggiornare pagine
|
||||
aggiornaPages = !options.aggiornasoloSeVuoti || !variante.pagine || variante.pagine === 0;
|
||||
if (aggiornaPages) variante.pagine = Number(data.numpagine);
|
||||
|
||||
// Determina se aggiornare misure
|
||||
aggiornaMisure = !options.aggiornasoloSeVuoti || !variante.misure;
|
||||
if (aggiornaMisure) variante.misure = data.misure;
|
||||
|
||||
// Determina se aggiornare edizione
|
||||
aggiornaEdizione = !options.aggiornasoloSeVuoti || !variante.edizione;
|
||||
if (aggiornaEdizione) variante.edizione = data.edizione;
|
||||
}
|
||||
|
||||
// Determina se aggiornare data pubblicazione
|
||||
const currentDatePub = productInfo.date_pub;
|
||||
aggiornaDataPubb = !options.aggiornasoloSeVuoti || !tools.isDateValid(currentDatePub);
|
||||
if (aggiornaDataPubb && data.data_pubblicazione) {
|
||||
productInfo.date_pub = new Date(data.data_pubblicazione);
|
||||
}
|
||||
|
||||
// Aggiorna arrvariazioni se pagine o misure sono cambiati
|
||||
const aggiornadati = aggiornaPages || aggiornaMisure || aggiornaEdizione;
|
||||
|
||||
if (aggiornadati) {
|
||||
await Product.findOneAndUpdate(
|
||||
{ _id: myproduct._id },
|
||||
{ $set: { arrvariazioni, scraped: true, scraped_date: new Date() } },
|
||||
{ upsert: true, new: true, includeResultMetadata: true }
|
||||
);
|
||||
}
|
||||
|
||||
// Aggiorna productInfo se contiene dati
|
||||
if (!tools.isObjectEmpty(productInfo)) {
|
||||
const risupdate = await ProductInfo.findOneAndUpdate(
|
||||
{ _id: myproduct.idProductInfo },
|
||||
{ $set: productInfo, scraped: true, scraped_date: new Date() },
|
||||
{ new: true, upsert: true, returnOriginal: false }
|
||||
).lean();
|
||||
console.log('risupdate', risupdate) ;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async scrapeMultiple(isbnList, options) {
|
||||
const results = [];
|
||||
for (const isbn of isbnList) {
|
||||
console.log(`Scraping ISBN: ${isbn}`);
|
||||
const myproduct = null;
|
||||
/// myproduct...
|
||||
const data = await this.scrapeISBN(myproduct, isbn, options);
|
||||
results.push({ isbn, ...data });
|
||||
// Per evitare blocchi, metti una pausa (es. 2 secondi)
|
||||
await new Promise((r) => setTimeout(r, 2000));
|
||||
isRecordAggiornato(updatedDoc) {
|
||||
try {
|
||||
if (updatedDoc) {
|
||||
const wasUpserted = updatedDoc.lastErrorObject.upserted !== undefined;
|
||||
return updatedDoc.lastErrorObject.n === 1 && !wasUpserted;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('error isRecordAggiornato', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
numeroValido(num) {
|
||||
return !isNaN(num) && num !== null && num !== '' && num > 0;
|
||||
}
|
||||
|
||||
datiMancanti(product) {
|
||||
let datimancanti = false;
|
||||
|
||||
if (product.arrvariazioni?.length > 0) {
|
||||
const arrvar = product.arrvariazioni[0];
|
||||
if (!this.numeroValido(arrvar.pagine)) {
|
||||
datimancanti = true;
|
||||
}
|
||||
if (!arrvar.misure) {
|
||||
datimancanti = true;
|
||||
}
|
||||
if (!arrvar.edizione) {
|
||||
datimancanti = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (product.idProductInfo) {
|
||||
if (!tools.isDateValid(product.idProductInfo.date_pub)) datimancanti = true;
|
||||
}
|
||||
|
||||
return datimancanti;
|
||||
}
|
||||
|
||||
getRemainingTimeToTheEnd(dataorainizio, index, numrecord) {
|
||||
// calcola il tempo stimato rimanente (ore e minuti), tenendo conto che sono arrivato a index, e devo raggiongere "numrecord", e sono partito alla data "dataorainizio"
|
||||
const differenza = ((new Date().getTime() - dataorainizio.getTime()) / (index + 1)) * (numrecord - index);
|
||||
|
||||
// Se la differenza è negativa, restituisce 0
|
||||
if (differenza <= 0) {
|
||||
return 'COMPLETATO !';
|
||||
}
|
||||
|
||||
// Calcola ore, minuti, secondi rimanenti
|
||||
const ore = Math.floor(differenza / (1000 * 60 * 60));
|
||||
const minuti = Math.floor((differenza % (1000 * 60 * 60)) / (1000 * 60));
|
||||
|
||||
// Restituisci il tempo rimanente in formato ore:minuti:secondi
|
||||
return `Stimato: ${ore} ore e ${minuti} min`;
|
||||
}
|
||||
|
||||
includiNelControlloIlRecProduct(product) {
|
||||
return product.idProductInfo && [1, 4, 34, 45, 46].includes(product.idProductInfo.idStatoProdotto);
|
||||
}
|
||||
|
||||
async scrapeMultiple(products, options) {
|
||||
const results = [];
|
||||
let quanti = 0;
|
||||
let mylog = '';
|
||||
console.log(`scrapeMultiple INIZIATO...`);
|
||||
let dataorainizio = new Date();
|
||||
|
||||
for (let i = 0; i < 100 && i < products.length; i++) {
|
||||
const product = products[i];
|
||||
let isbn = product.isbn;
|
||||
|
||||
if (this.includiNelControlloIlRecProduct(product)) {
|
||||
if (this.datiMancanti(product)) {
|
||||
// console.log(`${quanti} / ${products.length} - Scraping: ${product.idProductInfo.name}`);
|
||||
const data = await this.scrapeISBN(product, isbn, options);
|
||||
|
||||
if (data?.updated) {
|
||||
results.push({ isbn, ...data });
|
||||
quanti++;
|
||||
}
|
||||
|
||||
if (i % 1 === 0) {
|
||||
const percentuale = ((quanti / products.length) * 100).toFixed(2);
|
||||
console.log(
|
||||
`Scraping: ${product.isbn} - ${product.idProductInfo.name} - ${quanti} su ${i + 1} / ${
|
||||
products.length
|
||||
} - [${percentuale}%] - ${this.getRemainingTimeToTheEnd(dataorainizio, i, products.length)}`
|
||||
);
|
||||
}
|
||||
|
||||
// Per evitare blocchi, metti una pausa (es. 2 secondi)
|
||||
await new Promise((r) => setTimeout(r, 3000));
|
||||
}
|
||||
}
|
||||
}
|
||||
mylog += `RECORD AGGIORNATI: ${results.length - 1} su ${quanti}`;
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -220,30 +382,238 @@ class AmazonBookScraper {
|
||||
return html;
|
||||
}
|
||||
|
||||
async ScraperDataAmazon(idapp, options) {
|
||||
static async ScraperAzzeraFlagProducts(idapp, options) {
|
||||
// aggiorna tutti i record di Product (con idapp) scraped: false
|
||||
|
||||
await Product.updateMany({ idapp, scraped: true }, { $set: { scraped: false } });
|
||||
await Product.updateMany({ idapp, scraped_updated: true }, { $set: { scraped_updated: false } });
|
||||
}
|
||||
|
||||
static async removeDuplicateVariations(idapp, options) {
|
||||
let mylog = 'removeDuplicateVariations...\n';
|
||||
|
||||
// Fase 1: Troviamo i documenti che hanno almeno due elementi in arrvariazioni,
|
||||
// uno con `versione` e uno senza.
|
||||
const result = await Product.aggregate([
|
||||
{ $match: { idapp } }, // Seleziona il prodotto in base a idapp
|
||||
{
|
||||
$unwind: '$arrvariazioni', // Esplodi l'array `arrvariazioni` in documenti separati
|
||||
},
|
||||
{
|
||||
$group: {
|
||||
_id: '$_id', // Gruppo per _id del prodotto
|
||||
arrvariazioni: { $push: '$arrvariazioni' }, // Ricostruisci l'array arrvariazioni
|
||||
// Trova se c'è almeno un elemento con `versione` e uno senza
|
||||
hasVersione: {
|
||||
$sum: { $cond: [{ $ifNull: ['$arrvariazioni.versione', false] }, 1, 0] },
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$match: {
|
||||
hasVersione: { $gt: 0 }, // Se c'è almeno un record con `versione`
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// Ora possiamo rimuovere i duplicati
|
||||
for (let doc of result) {
|
||||
// Filtra gli oggetti dentro `arrvariazioni` per mantenere quelli con versione
|
||||
const arrvariazioniWithVersione = doc.arrvariazioni.filter((item) => item.versione);
|
||||
|
||||
// Rimuovi gli elementi che non hanno versione ma hanno gli stessi altri campi
|
||||
const cleanedArr = arrvariazioniWithVersione.filter(
|
||||
(item, index, self) =>
|
||||
index ===
|
||||
self.findIndex(
|
||||
(t) =>
|
||||
t.active === item.active &&
|
||||
t.status === item.status &&
|
||||
t.price === item.price &&
|
||||
t.sale_price === item.sale_price &&
|
||||
t.quantita === item.quantita &&
|
||||
t.pagine === item.pagine &&
|
||||
t.misure === item.misure &&
|
||||
t.edizione === item.edizione &&
|
||||
t.ristampa === item.ristampa &&
|
||||
t.formato === item.formato &&
|
||||
t.tipologia === item.tipologia &&
|
||||
t.idTipologia === item.idTipologia &&
|
||||
t.idTipoFormato === item.idTipoFormato &&
|
||||
t.preOrderDate === item.preOrderDate &&
|
||||
t.addtocart_link === item.addtocart_link &&
|
||||
t.eta === item.eta
|
||||
)
|
||||
);
|
||||
|
||||
if (doc.arrvariazioni.length - cleanedArr.length > 0) {
|
||||
const logtemp = `Elaborato ${doc._id} con ${arrvariazioniWithVersione.length} elementi\n`;
|
||||
logtemp += `Rimossi ${doc.arrvariazioni.length - cleanedArr.length} duplicati\n`;
|
||||
console.log(logtemp);
|
||||
mylog += logtemp;
|
||||
|
||||
// Aggiorna il documento eliminando i duplicati
|
||||
await Product.updateOne({ _id: doc._id }, { $set: { arrvariazioni: cleanedArr } });
|
||||
}
|
||||
}
|
||||
|
||||
return { mylog };
|
||||
}
|
||||
|
||||
static async queryArrVariazioni(idapp) {
|
||||
const result = await Product.aggregate([
|
||||
{ $match: { idapp, 'arrvariazioni.0': { $exists: true }, 'arrvariazioni.1': { $exists: true } } },
|
||||
{ $project: { arrvariazioni: 1, _id: 0 } },
|
||||
]);
|
||||
console.log('result', result);
|
||||
}
|
||||
|
||||
static async ScraperGeneraCSV(idapp, options, res) {
|
||||
// Dichiara le intestazioni del CSV
|
||||
const headers = ['isbn', 'titolo', 'pagine', 'misure', 'edizione', 'date_pub' /*'sottotitolo'*/];
|
||||
|
||||
try {
|
||||
// Trova i prodotti e popula 'idProductInfo'
|
||||
const products = await Product.find({ idapp, scraped_updated: true })
|
||||
.populate({ path: 'idProductInfo', select: 'date_pub name sottotitolo' })
|
||||
.lean();
|
||||
|
||||
|
||||
// Funzione per "appiattire" i dati
|
||||
const flattenData = (data) => {
|
||||
return data.map((item) => {
|
||||
const flattened = { ...item };
|
||||
|
||||
// Se arrvariazioni esiste, prendi solo il primo elemento o elabora come richiesto
|
||||
if (item.arrvariazioni && item.arrvariazioni.length > 0) {
|
||||
const variation = item.arrvariazioni[0]; // Usa il primo elemento o modifica se necessario
|
||||
flattened.pagine = variation.pagine || ''; // Usa '' se pagine non esiste
|
||||
flattened.misure = variation.misure || '';
|
||||
flattened.edizione = variation.edizione || '';
|
||||
flattened.ristampa = variation.ristampa || '';
|
||||
}
|
||||
|
||||
// Assicurati che 'idProductInfo' esista prima di usarlo
|
||||
flattened.date_pub = item.idProductInfo ? item.idProductInfo.date_pub : '';
|
||||
flattened.titolo = item.idProductInfo ? item.idProductInfo.name : '';
|
||||
// flattened.sottotitolo = item.idProductInfo ? item.idProductInfo.sottotitolo : '';
|
||||
|
||||
return flattened;
|
||||
});
|
||||
};
|
||||
|
||||
// Appiattisci i dati
|
||||
const records = flattenData(products);
|
||||
|
||||
// Prepara le righe del CSV
|
||||
const rows = records.map((item) => {
|
||||
// Se 'date_pub' è valido, convertilo in formato data, altrimenti metti una stringa vuota
|
||||
const formattedDate = item.date_pub
|
||||
? item.date_pub.toLocaleDateString('it-IT', { year: 'numeric', month: '2-digit', day: '2-digit' })
|
||||
: '';
|
||||
return [
|
||||
item.isbn || '', // Assicurati che ISBN sia sempre una stringa, anche vuota
|
||||
item.titolo || '',
|
||||
//item.sottotitolo || '',
|
||||
item.pagine || '', // Gestisci il caso in cui 'pagine' non esiste
|
||||
item.misure || '',
|
||||
item.edizione || '',
|
||||
formattedDate, // La data formattata
|
||||
];
|
||||
});
|
||||
|
||||
// Aggiungi l'intestazione al CSV
|
||||
rows.unshift(headers);
|
||||
|
||||
// Unisci tutte le righe con il delimitatore "|"
|
||||
const csvData = rows.map((row) => row.join('|')).join('\n');
|
||||
|
||||
// Scrivi il file CSV in modo asincrono
|
||||
// Ritorna la stringa CSV come oggetto per eventuali elaborazioni future
|
||||
return { data: csvData };
|
||||
} catch (e) {
|
||||
console.error('Error in ScraperGeneraCSV:', e);
|
||||
return { error: e.message };
|
||||
}
|
||||
}
|
||||
|
||||
static async ScraperDataAmazon(idapp, options) {
|
||||
const scraper = new AmazonBookScraper();
|
||||
const isbn = options.isbn;
|
||||
|
||||
try {
|
||||
const myproduct = await Product.getProductByIsbn(isbn);
|
||||
const data = await scraper.scrapeISBN(myproduct, isbn, options);
|
||||
const ris = await scraper.scrapeISBN(myproduct, isbn, options);
|
||||
|
||||
// let html = this.generateHtmlTableFromObject(data);
|
||||
|
||||
console.log(data);
|
||||
return res.status(200).send({ code: server_constants.RIS_CODE_OK, data, html });
|
||||
console.log(ris?.data);
|
||||
return res.status(200).send({ code: server_constants.RIS_CODE_OK, data: ris?.data, html });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: '' });
|
||||
}
|
||||
}
|
||||
|
||||
async ScraperMultipleDataAmazon(idapp, options) {
|
||||
static async ScraperMultipleDataAmazon(idapp, options) {
|
||||
const scraper = new AmazonBookScraper();
|
||||
const isbnList = ['8850224248']; // metti i tuoi ISBN qui
|
||||
|
||||
try {
|
||||
const books = await scraper.scrapeMultiple(isbnList);
|
||||
// Prendi solo quelli che non sono ancora stati scraped !
|
||||
const products = await Product.aggregate([
|
||||
// Filtro di base sui campi idapp, isbn, scraped, e scraped_error
|
||||
{
|
||||
$match: {
|
||||
idapp,
|
||||
isbn: { $exists: true, $ne: '' },
|
||||
scraped: { $ne: true }, // Escludi direttamente i record con scraped = true
|
||||
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
|
||||
$or: [{ scraped_error: { $exists: false } }, { scraped_error: { $exists: true, $eq: false } }],
|
||||
},
|
||||
},
|
||||
// Popoliamo il campo idProductInfo
|
||||
{
|
||||
$lookup: {
|
||||
from: 'productinfos', // Nome della collezione per 'idProductInfo'
|
||||
localField: 'idProductInfo', // Campo del documento corrente (Product)
|
||||
foreignField: '_id', // Campo di riferimento in ProductInfo
|
||||
as: 'idProductInfo', // Campo in cui verranno inseriti i dati popolati
|
||||
},
|
||||
},
|
||||
// De-strutturiamo l'array idProductInfo, se è un array
|
||||
{
|
||||
$unwind: {
|
||||
path: '$idProductInfo',
|
||||
preserveNullAndEmptyArrays: true, // Mantieni i documenti anche se idProductInfo è null o vuoto
|
||||
},
|
||||
},
|
||||
{
|
||||
$match: {
|
||||
'idProductInfo.idStatoProdotto': { $in: [1, 4, 34, 45, 46] }, // Condizione su idStatoProdotto
|
||||
},
|
||||
},
|
||||
// Proiettiamo solo i campi necessari
|
||||
{
|
||||
$project: {
|
||||
scraped: 1,
|
||||
scraped_updated: 1,
|
||||
isbn: 1,
|
||||
title: 1,
|
||||
sottotitolo: 1,
|
||||
arrvariazioni: 1,
|
||||
'idProductInfo._id': 1,
|
||||
'idProductInfo.date_pub': 1,
|
||||
'idProductInfo.name': 1,
|
||||
'idProductInfo.sottotitolo': 1,
|
||||
'idProductInfo.idStatoProdotto': 1,
|
||||
'idProductInfo.link_macro': 1,
|
||||
'idProductInfo.imagefile': 1,
|
||||
},
|
||||
},
|
||||
// A questo punto, puoi aggiungere altre operazioni di aggregazione se necessario (e.g., ordinamento)
|
||||
]);
|
||||
|
||||
// console.log(products);
|
||||
|
||||
const books = await scraper.scrapeMultiple(products, options);
|
||||
console.log(books);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
Reference in New Issue
Block a user