114 lines
3.9 KiB
TypeScript
114 lines
3.9 KiB
TypeScript
import { firefox } from 'playwright';
|
|
import { getRandomProxy } from './src/utils/proxyManager.js';
|
|
|
|
async function main() {
|
|
const productUrl = 'https://dutchie.com/embedded-menu/AZ-Deeply-Rooted/product/easy-tiger-live-rosin-aio-pete-s-peach';
|
|
|
|
console.log('🔍 Investigating Product with Sale Price...\n');
|
|
console.log(`URL: ${productUrl}\n`);
|
|
|
|
const proxyConfig = await getRandomProxy();
|
|
if (!proxyConfig) {
|
|
throw new Error('No proxy available');
|
|
}
|
|
console.log(`🔐 Using proxy: ${proxyConfig.server}\n`);
|
|
|
|
const browser = await firefox.launch({
|
|
headless: true,
|
|
proxy: proxyConfig
|
|
});
|
|
|
|
const context = await browser.newContext({
|
|
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0'
|
|
});
|
|
|
|
const page = await context.newPage();
|
|
|
|
try {
|
|
console.log('📄 Loading product page...');
|
|
await page.goto(productUrl, {
|
|
waitUntil: 'domcontentloaded',
|
|
timeout: 60000
|
|
});
|
|
|
|
await page.waitForTimeout(3000);
|
|
console.log('✅ Page loaded\n');
|
|
|
|
// Get the full page HTML for inspection
|
|
const html = await page.content();
|
|
|
|
// Look for price-related elements
|
|
const priceData = await page.evaluate(() => {
|
|
// Try JSON-LD structured data
|
|
const scripts = Array.from(document.querySelectorAll('script[type="application/ld+json"]'));
|
|
let jsonLdData: any = null;
|
|
|
|
for (const script of scripts) {
|
|
try {
|
|
const data = JSON.parse(script.textContent || '');
|
|
if (data['@type'] === 'Product') {
|
|
jsonLdData = data;
|
|
break;
|
|
}
|
|
} catch (e) {}
|
|
}
|
|
|
|
// Look for price elements in various ways
|
|
const priceElements = Array.from(document.querySelectorAll('[class*="price"], [class*="Price"]'));
|
|
const priceTexts = priceElements.map(el => ({
|
|
className: el.className,
|
|
textContent: el.textContent?.trim().substring(0, 100)
|
|
}));
|
|
|
|
// Get all text containing dollar signs
|
|
const pageText = document.body.textContent || '';
|
|
const priceMatches = pageText.match(/\$\d+\.?\d*/g);
|
|
|
|
// Look for strikethrough prices (often used for original price when there's a sale)
|
|
const strikethroughElements = Array.from(document.querySelectorAll('s, del, [style*="line-through"]'));
|
|
const strikethroughPrices = strikethroughElements.map(el => el.textContent?.trim());
|
|
|
|
// Look for elements with "sale", "special", "discount" in class names
|
|
const saleElements = Array.from(document.querySelectorAll('[class*="sale"], [class*="Sale"], [class*="special"], [class*="Special"], [class*="discount"], [class*="Discount"]'));
|
|
const saleTexts = saleElements.map(el => ({
|
|
className: el.className,
|
|
textContent: el.textContent?.trim().substring(0, 100)
|
|
}));
|
|
|
|
return {
|
|
jsonLdData,
|
|
priceElements: priceTexts.slice(0, 10),
|
|
priceMatches: priceMatches?.slice(0, 20) || [],
|
|
strikethroughPrices: strikethroughPrices.slice(0, 5),
|
|
saleElements: saleTexts.slice(0, 10)
|
|
};
|
|
});
|
|
|
|
console.log('💰 Price Data Found:');
|
|
console.log(JSON.stringify(priceData, null, 2));
|
|
|
|
// Take a screenshot for visual reference
|
|
await page.screenshot({ path: '/tmp/sale-price-product.png', fullPage: true });
|
|
console.log('\n📸 Screenshot saved to /tmp/sale-price-product.png');
|
|
|
|
// Save a snippet of the HTML around price elements
|
|
const priceHtmlSnippet = await page.evaluate(() => {
|
|
const priceElements = Array.from(document.querySelectorAll('[class*="price"], [class*="Price"]'));
|
|
if (priceElements.length > 0) {
|
|
return priceElements.slice(0, 3).map(el => el.outerHTML).join('\n\n');
|
|
}
|
|
return 'No price elements found';
|
|
});
|
|
|
|
console.log('\n📝 Price HTML Snippet:');
|
|
console.log(priceHtmlSnippet);
|
|
|
|
} catch (error: any) {
|
|
console.error('❌ Error:', error.message);
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
}
|
|
|
|
main().catch(console.error);
|