Spaces:
Paused
Paused
| const express = require('express'); | |
| const puppeteer = require('puppeteer-extra'); | |
| const StealthPlugin = require('puppeteer-extra-plugin-stealth'); | |
| puppeteer.use(StealthPlugin()); | |
| const app = express(); | |
| const PORT = 7860; | |
| // Reusable launch options | |
| const launchOptions = { | |
| headless: 'new', | |
| args: [ | |
| '--no-sandbox', | |
| '--disable-setuid-sandbox', | |
| '--disable-blink-features=AutomationControlled', | |
| ], | |
| }; | |
| const userAgent = | |
| 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'; | |
| /** | |
| * GET /get-image?url= | |
| * Scrapes the main pin image (736x if available) | |
| */ | |
| app.get('/get-image', async (req, res) => { | |
| const pinUrl = req.query.url; | |
| if (!pinUrl) return res.status(400).json({ error: 'Missing ?url=' }); | |
| let browser; | |
| try { | |
| browser = await puppeteer.launch(launchOptions); | |
| const page = await browser.newPage(); | |
| await page.setUserAgent(userAgent); | |
| await page.setViewport({ width: 1280, height: 800 }); | |
| await page.goto(pinUrl, { waitUntil: 'networkidle2' }); | |
| await page.evaluate(() => window.scrollBy(0, 200)); // lazy loading | |
| const imageUrl = await page.evaluate(() => { | |
| const images = Array.from(document.querySelectorAll('img')); | |
| const target = images.find(img => | |
| img.src.includes('pinimg.com/736x') | |
| ); | |
| return target ? target.src : null; | |
| }); | |
| if (!imageUrl) throw new Error('Main image not found'); | |
| res.json({ imageUrl }); | |
| } catch (err) { | |
| console.error('Error:', err.message); | |
| res.status(500).json({ error: err.message }); | |
| } finally { | |
| if (browser) await browser.close(); | |
| } | |
| }); | |
| /** | |
| * GET /search-images?q=sanji | |
| * Scrapes first 5 Pinterest search result images (736x best quality) | |
| */ | |
| app.get('/search-images', async (req, res) => { | |
| const query = req.query.q; | |
| if (!query) return res.status(400).json({ error: 'Missing ?q=' }); | |
| const searchUrl = `https://www.pinterest.com/search/pins/?q=${encodeURIComponent(query)}`; | |
| let browser; | |
| try { | |
| browser = await puppeteer.launch(launchOptions); | |
| const page = await browser.newPage(); | |
| await page.setUserAgent(userAgent); | |
| await page.setViewport({ width: 1280, height: 1000 }); | |
| await page.goto(searchUrl, { waitUntil: 'networkidle2' }); | |
| // Scroll to force lazy-loading | |
| await page.evaluate(() => window.scrollBy(0, 3000)); | |
| // Use native delay | |
| await new Promise(resolve => setTimeout(resolve, 2000)); | |
| const imageUrls = await page.evaluate(() => { | |
| const images = Array.from(document.querySelectorAll('img')); | |
| const urls = []; | |
| for (let img of images) { | |
| if (img.srcset) { | |
| const match = img.srcset.match(/https:\/\/i\.pinimg\.com\/736x\/[^ ]+/); | |
| if (match && !urls.includes(match[0])) { | |
| urls.push(match[0]); | |
| } | |
| } | |
| if (urls.length >= 5) break; | |
| } | |
| return urls; | |
| }); | |
| if (imageUrls.length === 0) throw new Error('No high-quality images found'); | |
| res.json({ images: imageUrls }); | |
| } catch (err) { | |
| console.error('Search Error:', err.message); | |
| res.status(500).json({ error: err.message }); | |
| } finally { | |
| if (browser) await browser.close(); | |
| } | |
| }); | |
| app.listen(PORT, () => { | |
| console.log(`Server running at http://localhost:${PORT}`); | |
| }); |