← back to Wine Finder Next
lib/services/wineBidScraper.js
108 lines
const axios = require('axios');
/**
* WineBid Auction Scraper
* Fetches live auction data and historical sale prices
*/
class WineBidScraper {
constructor() {
this.baseUrl = 'https://www.winebid.com';
}
async search(query) {
try {
// WineBid search endpoint
const searchUrl = `${this.baseUrl}/BuyWine/Search`;
const response = await axios.get(searchUrl, {
params: {
searchText: query,
pageSize: 50
},
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'application/json'
},
timeout: 10000
});
const wines = [];
const items = response.data.items || [];
for (const item of items) {
wines.push({
name: item.lotTitle || item.name,
price: parseFloat(item.currentBid || item.startingBid || 0),
highestBid: parseFloat(item.currentBid || 0),
startingBid: parseFloat(item.startingBid || 0),
estimatedValue: parseFloat(item.estimatedValue || 0),
vintage: item.vintage,
winery: item.producer,
region: item.region,
country: item.country,
lotNumber: item.lotNumber,
auctionEndDate: item.endDate,
bidsCount: item.bidCount || 0,
source: 'WineBid',
type: 'auction',
url: `${this.baseUrl}/Lot/${item.lotNumber}`,
image: item.imageUrl,
availability: item.endDate ? `Ends ${new Date(item.endDate).toLocaleDateString()}` : 'Live Auction',
bottleSize: item.bottleSize,
quantity: item.quantity || 1
});
}
return {
success: true,
wines,
count: wines.length,
source: 'WineBid'
};
} catch (error) {
console.error('WineBid scraper error:', error.message);
return {
success: false,
wines: [],
count: 0,
error: error.message,
source: 'WineBid'
};
}
}
async getHistoricalPrices(wineName, vintage) {
try {
// Fetch historical auction results
const response = await axios.get(`${this.baseUrl}/api/historical`, {
params: {
wine: wineName,
vintage: vintage
},
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
const history = response.data.map(sale => ({
date: sale.saleDate,
price: parseFloat(sale.hammerPrice),
quantity: sale.quantity,
bottleSize: sale.bottleSize,
auction: sale.auctionHouse
}));
return {
success: true,
history,
averagePrice: history.reduce((sum, h) => sum + h.price, 0) / history.length,
highestPrice: Math.max(...history.map(h => h.price)),
lowestPrice: Math.min(...history.map(h => h.price))
};
} catch (error) {
return { success: false, history: [], error: error.message };
}
}
}
module.exports = new WineBidScraper();