Created
December 17, 2024 18:37
-
-
Save fsndzomga/c078c68533fc41e37826da606758722d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const puppeteer = require('puppeteer'); | |
const fs = require('fs'); | |
const path = require('path'); | |
const OpenAI = require('openai'); | |
const dotenv = require('dotenv'); | |
dotenv.config(); | |
// Initialize OpenAI Client | |
const client = new OpenAI({ | |
baseURL: 'https://api.studio.nebius.ai/v1/', | |
apiKey: process.env.NEBIUS_API_KEY, | |
}); | |
// Function to capture a screenshot | |
async function captureScreenshot(url, outputFolder, outputFileName) { | |
const browser = await puppeteer.launch({ | |
headless: false, | |
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-cache'] | |
}); | |
const page = await browser.newPage(); | |
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'); | |
try { | |
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 }); // Increase timeout to 60 seconds | |
} catch (err) { | |
console.error('Page navigation failed:', err); | |
await browser.close(); | |
return; | |
} | |
await page.setViewport({ width: 1920, height: 1080 }); | |
const outputPath = path.join(outputFolder, outputFileName); | |
await page.screenshot({ path: outputPath }); | |
await browser.close(); | |
console.log(`Screenshot saved to ${outputPath}`); | |
} | |
// Function to extract product info from image | |
async function extractProductInfo(imageBase64) { | |
const imageBase64WithPrefix = 'data:image/png;base64,' + imageBase64; | |
const response = await client.chat.completions.create({ | |
"temperature": 0, | |
"model": "Qwen/Qwen2-VL-72B-Instruct", | |
"messages": [ | |
{ | |
"role": "user", | |
"content": [ | |
{ | |
"type": "text", | |
"text": "Extract product information from the image, title, price, description, and image URL. Format your response as a JSON object inside a <data> tag. For example: <data>{\"title\": \"Product Title\", \"price\": \"$10.99\", \"description\": \"Product Description\", \"image_url\": \"https://example.com/image.jpg\"}</data>" | |
}, | |
{ | |
"type": "image_url", | |
"image_url": { | |
"url": imageBase64WithPrefix | |
} | |
} | |
] | |
} | |
] | |
}); | |
console.log('Response:', response.choices[0].message.content); | |
const dataTagRegex = /<data>(.*?)<\/data>/s; | |
// or just look at the first match of json object | |
const jsonRegex = /{.*}/s; | |
const dataTagMatch = response.choices[0].message.content.match(dataTagRegex); | |
const jsonMatch = response.choices[0].message.content.match(jsonRegex); | |
const finalData = dataTagMatch ? dataTagMatch[1] : jsonMatch[0]; | |
return JSON.parse(finalData); | |
} | |
// Function to generate HTML from product info | |
function generateHTML(productInfo) { | |
return ` | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Product Details</title> | |
</head> | |
<body> | |
<h1>${productInfo.title}</h1> | |
<p><strong>Price:</strong> ${productInfo.price}</p> | |
<p><strong>Description:</strong> ${productInfo.description}</p> | |
<img src="./screenshots/screenshot.png" style="width: 100%; height: auto;" alt="Product Image"> | |
</body> | |
</html> | |
`; | |
} | |
// Function to launch the browser and display HTML | |
async function launchBrowserWithHtml(htmlContent) { | |
const browser = await puppeteer.launch({ | |
headless: false, | |
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-cache'] | |
}); | |
const page = await browser.newPage(); | |
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'); | |
// Write the HTML content to a temporary file | |
const tempFilePath = path.join(__dirname, 'product_page.html'); | |
fs.writeFileSync(tempFilePath, htmlContent); | |
// Open the HTML page | |
await page.goto(`file://${tempFilePath}`); | |
// Use setTimeout to wait for 1 minute (60000 milliseconds) | |
await new Promise(resolve => setTimeout(resolve, 60000)); | |
// Close the browser | |
await browser.close(); | |
// Delete the temporary file | |
fs.unlinkSync(tempFilePath); | |
} | |
// Main function to extract product info, generate HTML, and launch browser | |
async function processImage(url, outputFolder, outputFileName) { | |
// Capture the screenshot | |
await captureScreenshot(url, outputFolder, outputFileName); | |
// Convert the screenshot to base64 | |
const imagePath = path.join(outputFolder, outputFileName); | |
const imageBase64 = fs.readFileSync(imagePath, { encoding: 'base64' }); | |
// Extract product info from the image | |
const productInfo = await extractProductInfo(imageBase64); | |
// Generate the HTML content based on the extracted info | |
const htmlContent = generateHTML(productInfo); | |
// Launch the browser to display the generated HTML | |
await launchBrowserWithHtml(htmlContent); | |
} | |
// Example usage | |
const url = 'https://www.amazon.com/Dessert-Teaspoon-Cooking-Kitchen-Accessories/dp/B0DGY511JD/ref=sr_1_2'; | |
const outputFolder = './screenshots'; // Folder where the screenshot will be saved | |
const outputFileName = 'screenshot.png'; // Name of the output screenshot | |
// Create the folder if it doesn't exist | |
if (!fs.existsSync(outputFolder)) { | |
fs.mkdirSync(outputFolder); | |
} | |
// Process the image | |
processImage(url, outputFolder, outputFileName).catch(console.error); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment