first commit
This commit is contained in:
@@ -0,0 +1,350 @@
|
||||
// Interencheres.js
|
||||
'use strict';
|
||||
const { platform } = require('os');
|
||||
const {Scraper} = require('../Scraper');
|
||||
const DrouotData = require('./DrouotData');
|
||||
|
||||
class Drouot extends Scraper {
|
||||
|
||||
constructor(Url) {
|
||||
super(Url);
|
||||
|
||||
this.platformData = new DrouotData();
|
||||
|
||||
this.platformData.getUrlInfo(Url).then((data) => {
|
||||
if(data.lotID == 0 && data.saleID == 0){
|
||||
throw new Error('Invalid URL');
|
||||
}
|
||||
});
|
||||
|
||||
this._Name = 'drouot'
|
||||
this._PAGE_MAIN = "https://drouot.com/fr/"
|
||||
this._PAGE_LOGIN = "https://auth.drouot.com/login"
|
||||
|
||||
this._USER = "jp.ranu@cogip.de"
|
||||
this._PWD = "LYPYRKDUsSMH5BaWQxvH#"
|
||||
this._PATH_SESSION_FILE = ".session/session_drouot.json"
|
||||
}
|
||||
|
||||
getPictures = async ({ page, data}) => {
|
||||
|
||||
const PictList = await this.platformData.getPictures(page, this.Url);
|
||||
console.log('PictList : '+PictList)
|
||||
return PictList
|
||||
}
|
||||
|
||||
getLotInfos = async ({ page, data}) => {
|
||||
|
||||
console.log("getLotInfos "+this._Name+": "+this.Url)
|
||||
|
||||
// Navigate the page to a URL
|
||||
await page.goto(this.Url);
|
||||
|
||||
let idLot = await this.platformData.getLotID(this.Url);
|
||||
console.log('idLot : '+idLot)
|
||||
|
||||
// ## LotNumber
|
||||
let lotNumber = await this.platformData.getLotNumber(page);
|
||||
console.log('lotNumber : '+lotNumber)
|
||||
|
||||
// ## Title
|
||||
let title = await this.platformData.getLotTitle(page);
|
||||
console.log('title : '+title)
|
||||
|
||||
// ## Estimate
|
||||
let {EstimateLow, EstimateHigh} = await this.platformData.getEstimate(page);
|
||||
console.log('EstimateLow : '+EstimateLow)
|
||||
|
||||
// ## Description
|
||||
let Description = await this.platformData.getDescription(page);
|
||||
//console.log('Description : '+Description)
|
||||
|
||||
// ## Fees
|
||||
let {feesText, fees} = await this.platformData.getFees(page);
|
||||
|
||||
console.log('feesText : '+feesText)
|
||||
console.log('fees : '+fees)
|
||||
|
||||
// ################
|
||||
// ### SALE
|
||||
|
||||
let {id_sale, urlSale} = await this.platformData.getSaleID(page);
|
||||
|
||||
console.log('SellNumber : '+id_sale)
|
||||
|
||||
|
||||
console.log('url : '+urlSale)
|
||||
|
||||
let LotInfos = {
|
||||
idPlatform: idLot,
|
||||
platform : this._Name,
|
||||
url: this.Url,
|
||||
title: title,
|
||||
lotNumber: lotNumber,
|
||||
EstimateLow: EstimateLow,
|
||||
EstimateHigh: EstimateHigh,
|
||||
Description: Description,
|
||||
feesText: feesText,
|
||||
fees: fees,
|
||||
saleInfo: {
|
||||
idSale: id_sale,
|
||||
url: urlSale
|
||||
}
|
||||
}
|
||||
|
||||
console.log('LotInfos : '+LotInfos)
|
||||
|
||||
return LotInfos
|
||||
}
|
||||
|
||||
getSaleInfos = async ({ page, data}) => {
|
||||
console.log("getSaleInfos "+this._Name+": "+this.Url)
|
||||
|
||||
// Navigate the page to a URL
|
||||
await page.goto(this.Url);
|
||||
|
||||
let {saleID, urlSale} = await this.platformData.getUrlInfo(this.Url);
|
||||
|
||||
console.log('saleID : '+saleID)
|
||||
console.log('urlSale : '+urlSale)
|
||||
|
||||
// ## Title
|
||||
let title = await this.platformData.getSaleTitle(page);
|
||||
console.log('title : '+title)
|
||||
|
||||
// ## Date
|
||||
let date = await this.platformData.getSaleDate(page);
|
||||
console.log('date : '+date)
|
||||
|
||||
// ## Location
|
||||
let location = await this.platformData.getSaleLocation(page);
|
||||
console.log('location : '+location)
|
||||
|
||||
// ## SaleHouseName
|
||||
let saleHouseName = await this.platformData.getSaleHouseName(page);
|
||||
console.log('saleHouseName : '+saleHouseName)
|
||||
|
||||
// ## Status
|
||||
// ready : ready to be followed
|
||||
// following : sale is followed by the AuctionAgent
|
||||
// askStop : sale is followed by the AuctionAgent and the user ask to stop following
|
||||
// pause : the Sale is stopped by the Auction House and ready to restart
|
||||
// end : the Sale is ended
|
||||
|
||||
let status = 'ready'
|
||||
|
||||
let SaleInfo = {
|
||||
idPlatform: saleID,
|
||||
platform : this._Name,
|
||||
url: urlSale,
|
||||
title: title,
|
||||
date: date,
|
||||
location: location,
|
||||
saleHouseName: saleHouseName,
|
||||
status: status
|
||||
}
|
||||
|
||||
console.log('SaleInfo : ', JSON.stringify(SaleInfo, null, 2));
|
||||
return SaleInfo
|
||||
}
|
||||
|
||||
getLotList = async ({ page, data}) => {
|
||||
console.log("getLotList "+this._Name+": "+this.Url)
|
||||
|
||||
// Navigate the page to a URL
|
||||
await page.goto(this.Url);
|
||||
|
||||
const LotList = await this.platformData.getLotList(page);
|
||||
console.log('LotList : '+LotList)
|
||||
return LotList
|
||||
}
|
||||
|
||||
async CheckAndConnect(page) {
|
||||
|
||||
return new Promise(async (resolve, reject) => {
|
||||
|
||||
await page.goto(this._PAGE_MAIN);
|
||||
|
||||
//get the Connexion button
|
||||
const [Connexion] = await page.$x("//div[contains(@class, 'btn') and contains(@class, 'ghost') and contains(text(), 'Connexion')]");
|
||||
console.log(Connexion)
|
||||
|
||||
// if Connection button found => Login
|
||||
if (Connexion) {
|
||||
console.log("-- Login --")
|
||||
|
||||
await page.goto(this._PAGE_LOGIN);
|
||||
|
||||
//get the Email field
|
||||
//console.log("-- get Email Input --")
|
||||
await page.type('#email', this._USER);
|
||||
|
||||
//console.log("-- get password Input --")
|
||||
await page.type("#password", this._PWD);
|
||||
|
||||
//console.log("-- get ConnexionButton --")
|
||||
const [ConnexionButton] = await page.$x("//button[contains(text(), 'Connexion')]");
|
||||
await ConnexionButton.evaluate(b => b.click());
|
||||
|
||||
//console.log("-- Login wait --")
|
||||
await page.waitForTimeout(1000);
|
||||
//resolve(page)
|
||||
|
||||
const [ConnexionOK] = await page.$x("//button[contains(text(), 'Continuer en tant que')]");
|
||||
if (ConnexionOK) {
|
||||
console.log("-- Connection OK --")
|
||||
await ConnexionOK.evaluate(b => b.click());
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await this._saveSession(page)
|
||||
|
||||
// const sessionData = await page.session.dumpString({
|
||||
// storageProviders: [
|
||||
// StorageProviderName.Cookie,
|
||||
// StorageProviderName.LocalStorage,
|
||||
// StorageProviderName.SessionStorage,
|
||||
// StorageProviderName.IndexedDB,
|
||||
// ],
|
||||
// })
|
||||
// fs.writeFileSync(this._PATH_SESSION_FILE, sessionData);
|
||||
// console.log("-- Connection OK --")
|
||||
resolve(page)
|
||||
} else {
|
||||
console.error("-- !!!! Connection ERROR !!!! --");
|
||||
reject()
|
||||
}
|
||||
|
||||
// Allready connected
|
||||
} else {
|
||||
console.log("-- Allready connected --")
|
||||
resolve(page)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
Live = async (browser) => {
|
||||
|
||||
console.log("Live "+this._Name+": "+this.Url)
|
||||
|
||||
const page = await browser.newPage();
|
||||
|
||||
page = await this.CheckAndConnect(page);
|
||||
|
||||
let CheckAskStop = null;
|
||||
let Socket = null;
|
||||
const StopLive = async (params) => {
|
||||
clearInterval(CheckAskStop);
|
||||
Socket.off('Network.webSocketFrameReceived', listener);
|
||||
page.close()
|
||||
}
|
||||
|
||||
const listener = async (params) => {
|
||||
let payload = params.response.payloadData
|
||||
if(payload.length>1 && payload.substring(0, 2) == '42'){
|
||||
payload = JSON.parse(payload.substring(2))
|
||||
//console.log(payload)
|
||||
|
||||
const type = payload[0];
|
||||
const payloadData = payload[1];
|
||||
|
||||
switch (type) {
|
||||
|
||||
case 'startSale':
|
||||
break;
|
||||
case 'listAuctionedItems':
|
||||
break;
|
||||
|
||||
case 'joinedSale':
|
||||
await this.JucunduNextItem(
|
||||
payloadData.sale_id,
|
||||
payloadData.timestamp,
|
||||
payloadData.item_id,
|
||||
payloadData.order_number.primary,
|
||||
payloadData.title,
|
||||
payloadData.description,
|
||||
payloadData.pricing.estimates.min,
|
||||
payloadData.pricing.estimates.max,
|
||||
payloadData
|
||||
);
|
||||
break;
|
||||
|
||||
case 'auctionedItem':
|
||||
await this.JucunduAuctionedItem(
|
||||
payloadData.item_id,
|
||||
payloadData.timestamp,
|
||||
payloadData.auctioned.amount,
|
||||
payloadData.auctioned.sold,
|
||||
payloadData.auctioned.type
|
||||
);
|
||||
break;
|
||||
|
||||
case 'nextItem':
|
||||
await this.JucunduNextItem(
|
||||
payloadData.sale_id,
|
||||
payloadData.timestamp,
|
||||
payloadData.item_id,
|
||||
payloadData.order_number.primary,
|
||||
payloadData.title,
|
||||
payloadData.description,
|
||||
payloadData.pricing.estimates.min,
|
||||
payloadData.pricing.estimates.max,
|
||||
payloadData
|
||||
);
|
||||
break;
|
||||
|
||||
case 'bid':
|
||||
await this.JucundusBid(
|
||||
payloadData.item_id,
|
||||
payloadData.timestamp,
|
||||
payloadData.amount,
|
||||
payloadData.auctioned_type
|
||||
);
|
||||
break;
|
||||
|
||||
case 'pauseSale':
|
||||
console.error('** Pause **');
|
||||
console.log(payloadData);
|
||||
// await this.JucundusEndSale()
|
||||
// StopLive()
|
||||
break;
|
||||
|
||||
case 'endSale':
|
||||
// await this.JucundusEndSale()
|
||||
// StopLive()
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error('Unknown data type:', type);
|
||||
console.log(payloadData);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try{
|
||||
await page.goto(this.Url);
|
||||
Socket = await page.target().createCDPSession();
|
||||
await Socket.send('Network.enable');
|
||||
await Socket.send('Page.enable');
|
||||
Socket.on('Network.webSocketFrameReceived', listener);
|
||||
console.log('Listener set up for Network.webSocketFrameReceived event');
|
||||
|
||||
// check if stop was asked
|
||||
CheckAskStop = setInterval(async () => {
|
||||
this.JucundusCheckStop()
|
||||
.then(AskStop => {
|
||||
if(AskStop){
|
||||
StopLive()
|
||||
}
|
||||
})
|
||||
}, 10000); // 10000 milliseconds = 10 seconds
|
||||
|
||||
}catch(e){
|
||||
console.log('Error : '+e)
|
||||
throw new Error('Error: '+e)
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Drouot
|
||||
@@ -0,0 +1,185 @@
|
||||
// Drouot.js
|
||||
'use strict';
|
||||
const {Scraper} = require('../Scraper');
|
||||
|
||||
class Drouot extends Scraper {
|
||||
|
||||
constructor(Url) {
|
||||
super(Url);
|
||||
|
||||
this._Name = 'drouot'
|
||||
this._PAGE_MAIN = "https://drouot.com/fr/"
|
||||
this._PAGE_LOGIN = "https://auth.drouot.com/login"
|
||||
|
||||
this._USER = "jp.ranu@cogip.de"
|
||||
this._PWD = "LYPYRKDUsSMH5BaWQxvH#"
|
||||
|
||||
this._PATH_SESSION_FILE = ".session/session_drouot.json"
|
||||
}
|
||||
|
||||
getPictures = async ({ page, data}) => {
|
||||
|
||||
console.log("getPictures "+this._Name+": "+this.Url)
|
||||
|
||||
//add the picture to the list
|
||||
let PictList = []
|
||||
page.on('response', async response => {
|
||||
|
||||
const url = response.url();
|
||||
if (response.request().resourceType() === 'image' && url.match("size=fullHD")) {
|
||||
response.buffer().then(file => {
|
||||
console.log("push "+url)
|
||||
PictList.push(url)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function checkDup() {
|
||||
const toFindDuplicates = array => array.filter((item, index) => array.indexOf(item) !== index)
|
||||
const duplicateElements = toFindDuplicates(PictList);
|
||||
|
||||
// if dupplicate pictures added in the array
|
||||
if (duplicateElements.length > 0) {
|
||||
|
||||
// remove diplucated content
|
||||
PictList = PictList.filter(function (elem, pos) {
|
||||
return PictList.indexOf(elem) == pos;
|
||||
})
|
||||
|
||||
// stop the process
|
||||
return false
|
||||
|
||||
// no dupplicated picture
|
||||
} else {
|
||||
|
||||
// continue the process
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Navigate the page to a URL
|
||||
await page.goto(this.Url);
|
||||
console.log("goto "+this.Url)
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
//get the Next link
|
||||
const [ButtonNext] = await page.$x("//*[@id='next']");
|
||||
|
||||
if (ButtonNext) {
|
||||
let condition = true
|
||||
do {
|
||||
console.log("click")
|
||||
await ButtonNext.evaluate(b => b.click());
|
||||
await page.waitForTimeout(500);
|
||||
condition = checkDup();
|
||||
} while (condition);
|
||||
}
|
||||
|
||||
return PictList
|
||||
|
||||
}
|
||||
|
||||
async CheckAndConnect(page) {
|
||||
|
||||
return new Promise(async (resolve, reject) => {
|
||||
|
||||
await page.goto(this._PAGE_MAIN);
|
||||
|
||||
//get the Connexion button
|
||||
const [Connexion] = await page.$x("//div[contains(@class, 'btn') and contains(@class, 'ghost') and contains(text(), 'Connexion')]");
|
||||
console.log(Connexion)
|
||||
|
||||
// if Connection button found => Login
|
||||
if (Connexion) {
|
||||
console.log("-- Login --")
|
||||
|
||||
await page.goto(this._PAGE_LOGIN);
|
||||
|
||||
//get the Email field
|
||||
//console.log("-- get Email Input --")
|
||||
await page.type('#email', this._USER);
|
||||
|
||||
//console.log("-- get password Input --")
|
||||
await page.type("#password", this._PWD);
|
||||
|
||||
//console.log("-- get ConnexionButton --")
|
||||
const [ConnexionButton] = await page.$x("//button[contains(text(), 'Connexion')]");
|
||||
await ConnexionButton.evaluate(b => b.click());
|
||||
|
||||
//console.log("-- Login wait --")
|
||||
await page.waitForTimeout(1000);
|
||||
//resolve(page)
|
||||
|
||||
const [ConnexionOK] = await page.$x("//button[contains(text(), 'Continuer en tant que')]");
|
||||
if (ConnexionOK) {
|
||||
console.log("-- Connection OK --")
|
||||
await ConnexionOK.evaluate(b => b.click());
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await this._saveSession(page)
|
||||
|
||||
// const sessionData = await page.session.dumpString({
|
||||
// storageProviders: [
|
||||
// StorageProviderName.Cookie,
|
||||
// StorageProviderName.LocalStorage,
|
||||
// StorageProviderName.SessionStorage,
|
||||
// StorageProviderName.IndexedDB,
|
||||
// ],
|
||||
// })
|
||||
// fs.writeFileSync(this._PATH_SESSION_FILE, sessionData);
|
||||
// console.log("-- Connection OK --")
|
||||
resolve(page)
|
||||
} else {
|
||||
console.error("-- !!!! Connection ERROR !!!! --");
|
||||
reject()
|
||||
}
|
||||
|
||||
// Allready connected
|
||||
} else {
|
||||
console.log("-- Allready connected --")
|
||||
resolve(page)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
getSellNumberFromURL = function (Url) {
|
||||
const match = Url.match(/\/(\d+)-/);
|
||||
if (match) {
|
||||
const extractedNumber = parseInt(match[1], 10); // Convert the matched string to an integer
|
||||
if (!isNaN(extractedNumber)) {
|
||||
return match[1];
|
||||
} else {
|
||||
console.log("Invalid number in the URL");
|
||||
}
|
||||
} else {
|
||||
console.log("Number not found in the URL.");
|
||||
}
|
||||
}
|
||||
|
||||
async Live() {
|
||||
|
||||
this.Url = "https://drouot.com/fr/v/147085-fine-asian-european--islamic-works-of-art"
|
||||
|
||||
const page = await this._getPage(true);
|
||||
|
||||
await this.CheckAndConnect(page)
|
||||
|
||||
await page.goto(this.Url);
|
||||
const [LiveOn] = await page.$x("//span[contains(text(), 'Live en cours')]");
|
||||
|
||||
if (LiveOn) {
|
||||
const SellNumber = this.getSellNumberFromURL(this.Url)
|
||||
const UrlLive = "https://drouot.com/live/bidlive/" + SellNumber
|
||||
await page.goto(UrlLive);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// get the Live Link
|
||||
|
||||
//await browser.close();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Drouot
|
||||
@@ -0,0 +1,378 @@
|
||||
// interencheresData.js
|
||||
const {ScraperTools} = require('../Scraper');
|
||||
const urlModule = require('url');
|
||||
const moment = require('moment-timezone');
|
||||
const { Console } = require('console');
|
||||
const { title } = require('process');
|
||||
|
||||
class InterencheresData extends ScraperTools {
|
||||
|
||||
_Name = 'drouot'
|
||||
|
||||
getUrlInfo = async (url) => {
|
||||
|
||||
// URL Lot : https://drouot.com/fr/l/25184163-john-conde-17651794-britanniqu
|
||||
// https://drouot.com/fr/{{v: Vente/ l: Lot}}/{{LotID}}-john-conde-{{????}}-britanniqu
|
||||
|
||||
// URL Sale : https://drouot.com/fr/v/152658-fine-paintings-and-frames
|
||||
// https://drouot.com/fr/{{v: Vente/ l: Lot}}/{{SaleID}}-fine-paintings-and-frames
|
||||
|
||||
|
||||
let parsedUrl = new urlModule.URL(url);
|
||||
let pathParts = parsedUrl.pathname.split('/').filter(Boolean);
|
||||
|
||||
// if sale URL
|
||||
let saleID = 0
|
||||
let lotID = 0
|
||||
let TypeUrl = ''
|
||||
let urlSale = ''
|
||||
let urlLot = ''
|
||||
|
||||
if(pathParts[1] == 'v'){
|
||||
TypeUrl = 'Sale'
|
||||
saleID = pathParts[2].split('-')[0];
|
||||
urlSale = parsedUrl.origin + parsedUrl.pathname
|
||||
}else if(pathParts[1] == 'l'){
|
||||
TypeUrl = 'Lot'
|
||||
lotID = pathParts[2].split('-')[0];
|
||||
urlLot = parsedUrl.origin + parsedUrl.pathname
|
||||
}
|
||||
|
||||
|
||||
|
||||
return {
|
||||
'TypeUrl': TypeUrl,
|
||||
'saleID': saleID,
|
||||
'lotID': lotID,
|
||||
'urlSale': urlSale,
|
||||
'urlLot': urlLot
|
||||
}
|
||||
}
|
||||
|
||||
// ## Lot
|
||||
|
||||
getPictures = async (page, Url) => {
|
||||
|
||||
console.log("getPictures "+this._Name+": "+Url)
|
||||
|
||||
//add the picture to the list
|
||||
let PictList = []
|
||||
page.on('response', async response => {
|
||||
|
||||
const url = response.url();
|
||||
if (response.request().resourceType() === 'image' && url.match("size=fullHD")) {
|
||||
response.buffer().then(file => {
|
||||
console.log("push "+url)
|
||||
PictList.push(url)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function checkDup() {
|
||||
const toFindDuplicates = array => array.filter((item, index) => array.indexOf(item) !== index)
|
||||
const duplicateElements = toFindDuplicates(PictList);
|
||||
|
||||
// if dupplicate pictures added in the array
|
||||
if (duplicateElements.length > 0) {
|
||||
|
||||
// remove diplucated content
|
||||
PictList = PictList.filter(function (elem, pos) {
|
||||
return PictList.indexOf(elem) == pos;
|
||||
})
|
||||
|
||||
// stop the process
|
||||
return false
|
||||
|
||||
// no dupplicated picture
|
||||
} else {
|
||||
|
||||
// continue the process
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Navigate the page to a URL
|
||||
await page.goto(Url);
|
||||
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
//get the Next link
|
||||
const [ButtonNext] = await page.$x("//*[@id='next']");
|
||||
|
||||
if (ButtonNext) {
|
||||
let condition = true
|
||||
do {
|
||||
console.log("click")
|
||||
await ButtonNext.evaluate(b => b.click());
|
||||
await page.waitForTimeout(500);
|
||||
condition = checkDup();
|
||||
} while (condition);
|
||||
}
|
||||
|
||||
return PictList
|
||||
}
|
||||
|
||||
getLotNumber = async (page) => {
|
||||
|
||||
const lotNumberXPath = [
|
||||
'/html/body/div[1]/div[4]/div[2]/div/div/div/div[3]/div/div[1]/div[2]/div[1]/span/span',
|
||||
]
|
||||
let lotNumberString = await this.getTextContent(lotNumberXPath, page, 'lotNumberXPath')
|
||||
let lotNumber = '';
|
||||
if(lotNumberString != ''){
|
||||
lotNumber = lotNumberString.replace('Lot ', '');
|
||||
}
|
||||
|
||||
return lotNumber
|
||||
}
|
||||
|
||||
getLotTitle = async (page) => {
|
||||
|
||||
const lotTitleXPath = [
|
||||
'/html/body/div[1]/div[4]/div[2]/div/div/div/div[3]/div/div[1]/div[2]/div[5]/h1',
|
||||
]
|
||||
let lotTitleString = await this.getTextContent(lotTitleXPath, page, 'lotTitleXPath')
|
||||
if (lotTitleString.length > 90) {
|
||||
lotTitleString = lotTitleString.substring(0, 90) + '...';
|
||||
}
|
||||
|
||||
return lotTitleString
|
||||
}
|
||||
|
||||
getEstimate = async (page) => {
|
||||
const EstimateXPath = [
|
||||
'/html/body/div[1]/div[4]/div[2]/div/div/div/div[3]/div/div[1]/div[2]/div[7]/div/div[1]/span/span',
|
||||
]
|
||||
|
||||
let EstimateString = await this.getTextContent(EstimateXPath, page, 'EstimateXPath')
|
||||
//console.log('EstimateString : '+EstimateString)
|
||||
|
||||
let EstimateLow = 0
|
||||
let EstimateHigh = 0
|
||||
if(EstimateString != ''){
|
||||
let matches = EstimateString.match(/(\d{1,3}(?:\s\d{3})*)/g);
|
||||
|
||||
if (matches) {
|
||||
if (matches.length >= 2) {
|
||||
EstimateLow = parseInt(matches[0].replace(/\s/g, ''), 10);
|
||||
EstimateHigh = parseInt(matches[1].replace(/\s/g, ''), 10);
|
||||
|
||||
console.log('Low:', EstimateLow);
|
||||
console.log('High:', EstimateHigh);
|
||||
} else
|
||||
if(matches.length == 1){
|
||||
EstimateLow = parseInt(matches[0].replace(/\s/g, ''), 10);
|
||||
EstimateHigh = 0;
|
||||
} else {
|
||||
console.error('Could not extract numbers.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {EstimateLow, EstimateHigh}
|
||||
}
|
||||
|
||||
getDescription = async (page) => {
|
||||
const DescriptionXPath = [
|
||||
'//h3[contains(@class, "descriptionLineWrap")]',
|
||||
]
|
||||
let Description = await this.getTextContent(DescriptionXPath, page, 'DescriptionXPath')
|
||||
|
||||
return Description
|
||||
}
|
||||
|
||||
getFees = async (page) => {
|
||||
let feesText = ''
|
||||
let fees = 0
|
||||
|
||||
const FeesXPath = [
|
||||
'/html/body/div[1]/div[4]/div[2]/div/div/div/div[3]/div/div[1]/div[2]/div[7]/div/div[3]/a/span',
|
||||
]
|
||||
feesText = await this.getTextContent(FeesXPath, page, 'FeesXPath')
|
||||
|
||||
// detect digit
|
||||
if (!/\d/.test(feesText)) {
|
||||
const FeesXPath = [
|
||||
'/html/body/div[1]/div[4]/div[2]/div/div/div/div[3]/div/div[1]/div[2]/div[7]/div/div[2]/a/span',
|
||||
]
|
||||
feesText = await this.getTextContent(FeesXPath, page, 'FeesXPath')
|
||||
}
|
||||
|
||||
|
||||
feesText = feesText.replace(/[\n]/g, '').replace(/\s+/g, ' ').trim();
|
||||
let matches = feesText.match(/(\d+(\.\d+)?)/)
|
||||
if (matches) {
|
||||
fees = matches[0];
|
||||
}
|
||||
|
||||
return {feesText, fees}
|
||||
}
|
||||
|
||||
getLotID = async (url) => {
|
||||
|
||||
let UrlInfo = await this.getUrlInfo(url);
|
||||
let id_lot = UrlInfo.lotID
|
||||
return id_lot
|
||||
}
|
||||
|
||||
getSaleID = async (page) => {
|
||||
|
||||
const UrlCatalogueXPath = [
|
||||
'/html/body/div[1]/div[4]/div[2]/div/div/div/div[3]/div/div[1]/div[2]/div[10]/div/div[2]/div[3]/a[1]',
|
||||
]
|
||||
let UrlCatalogue = await this.getAttribute(UrlCatalogueXPath, page, "href", "UrlCatalogueXPath")
|
||||
console.log('UrlCatalogue : '+UrlCatalogue)
|
||||
|
||||
UrlCatalogue = UrlCatalogue.substring(0,1) == '/' ? 'https://drouot.com'+UrlCatalogue : UrlCatalogue
|
||||
|
||||
|
||||
let UrlInfo = await this.getUrlInfo(UrlCatalogue);
|
||||
let id_sale = UrlInfo.saleID
|
||||
let urlSale = UrlInfo.urlSale
|
||||
|
||||
return {id_sale, urlSale}
|
||||
}
|
||||
|
||||
// ## Lot List
|
||||
_getLotInfoList = async (page, Elements) => {
|
||||
let LotList = [];
|
||||
for (let element of Elements) {
|
||||
let Lot = {}
|
||||
try{
|
||||
let LotnameXPath = [
|
||||
'.//a/div/div/div[5]/div/div[1]',
|
||||
'.//a/div/div/div[4]/div/div[1]',
|
||||
]
|
||||
let Lotname = await this.getTextContentElement(LotnameXPath, page, element, 'LotnameXPath')
|
||||
|
||||
// idPlatform from the url
|
||||
let LotUrlXPath = [
|
||||
'.//a'
|
||||
]
|
||||
let urlLot = await this.getAttributeElement(LotUrlXPath, page, element, 'href', 'UrlListLot')
|
||||
let match = urlLot.match(/lot-(.*).html/);
|
||||
let idPlatform = match[1];
|
||||
|
||||
Lot = {
|
||||
title: Lotname,
|
||||
idPlatform: idPlatform,
|
||||
platform: this._Name,
|
||||
lotNumber: Lotname.split('Lot ')[1]
|
||||
}
|
||||
}catch(e){
|
||||
console.error(e)
|
||||
}
|
||||
//console.log(LotList)
|
||||
LotList.push(Lot);
|
||||
};
|
||||
|
||||
return LotList;
|
||||
}
|
||||
|
||||
getLotList = async (page) => {
|
||||
|
||||
let LotList = []
|
||||
|
||||
let NextBtn = false
|
||||
do {
|
||||
|
||||
// extract Lot List
|
||||
const LotListXPath = [
|
||||
'//div[contains(@class, "sale-item-wrapper")]',
|
||||
]
|
||||
let Elements = await page.$x(LotListXPath[0]);
|
||||
|
||||
if (Elements.length > 0) {
|
||||
LotList = [].concat(LotList, await this._getLotInfoList(page, Elements))
|
||||
}
|
||||
|
||||
// search for the Button Next (only if enabled)
|
||||
let NextPageButtonXPath = "//button[contains(@aria-label, 'Page suivante') and not(contains(@class, 'v-pagination__navigation--disabled'))]"
|
||||
let NextPageButton = await page.$x(NextPageButtonXPath);
|
||||
if (NextPageButton.length > 0) {
|
||||
NextBtn = true
|
||||
await NextPageButton[0].evaluate(b => b.click());
|
||||
await page.waitForTimeout(1000);
|
||||
console.log('Next Page')
|
||||
}else{
|
||||
NextBtn = false
|
||||
}
|
||||
|
||||
|
||||
} while (NextBtn);
|
||||
|
||||
return LotList
|
||||
}
|
||||
|
||||
|
||||
// ## Sale
|
||||
|
||||
getSaleTitle = async (page) => {
|
||||
const SaleTitleXPath = [
|
||||
'/html/body/div/div[4]/div[2]/div/div/div/div/div[3]/div/div[2]/div[1]/div/h1',
|
||||
]
|
||||
let SaleTitle = await this.getTextContent(SaleTitleXPath, page, 'SaleTitleXPath')
|
||||
return SaleTitle
|
||||
}
|
||||
|
||||
getSaleDate = async (page) => {
|
||||
|
||||
// Test if Live Sale
|
||||
let BoolLive = false;
|
||||
try {
|
||||
// const VideoXPath = [
|
||||
// '//*[@id="streaming-subscriber"]',
|
||||
// ]
|
||||
// let VideoExists = await this.ElementExists(VideoXPath, page, 'VideoXPath')
|
||||
// console.log('VideoExists : '+VideoExists)
|
||||
// BoolLive = VideoExists
|
||||
|
||||
} catch (error) {}
|
||||
|
||||
let SaleDate;
|
||||
|
||||
// if futur sale
|
||||
if(!BoolLive){
|
||||
|
||||
await page.waitForTimeout(400);
|
||||
const SaleDateXPath = [
|
||||
'/html/body/div/div[4]/div[2]/div/div/div/div/div[3]/div/div[2]/div[1]/div/div[1]/div',
|
||||
]
|
||||
let SaleDateString = await this.getTextContent(SaleDateXPath, page, 'SaleDateXPath')
|
||||
SaleDateString = SaleDateString.trim()
|
||||
|
||||
let cleanStr = SaleDateString.replace(/\\s|\\n/g, ' ').replace(/\s+/g, ' ');
|
||||
|
||||
SaleDate = moment.tz(cleanStr, 'dddd D MMMM à HH:mm (z)', 'fr', 'Europe/Paris').format();
|
||||
|
||||
// Live Sale
|
||||
}else{
|
||||
SaleDate = moment.tz('Europe/Paris').format();
|
||||
}
|
||||
|
||||
console.log('SaleDate : '+SaleDate)
|
||||
return SaleDate
|
||||
|
||||
}
|
||||
|
||||
getSaleLocation = async (page) => {
|
||||
const SaleLocationXPath = [
|
||||
'/html/body/div/div[4]/div[2]/div/div/div/div/div[3]/div/div[2]/div[1]/div/div[4]',
|
||||
]
|
||||
let SaleLocation = await this.getTextContent(SaleLocationXPath, page, 'SaleLocationXPath')
|
||||
return SaleLocation.trim()
|
||||
}
|
||||
|
||||
getSaleHouseName = async (page) => {
|
||||
const SaleHouseNameXPath = [
|
||||
'/html/body/div/div[4]/div[2]/div/div/div/div/div[3]/div/div[2]/div[1]/div/h4/a[1]/span',
|
||||
]
|
||||
let SaleHouseName = await this.getTextContent(SaleHouseNameXPath, page, 'SaleHouseNameXPath')
|
||||
|
||||
SaleHouseName = SaleHouseName.replace(/[\n]/g, '').replace(/\s+/g, ' ').trim();
|
||||
return SaleHouseName.trim()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = InterencheresData
|
||||
Reference in New Issue
Block a user