Spaces:
Sleeping
Sleeping
| import { chromium } from "playwright"; | |
| import fs from "fs"; | |
| export async function crawlBrowser(url:string){ | |
| console.log("AI Browser crawling:",url); | |
| const browserPath = | |
| "/root/.cache/puppeteer/chrome/linux_arm-148.0.7778.97/chrome-linux64/chrome"; | |
| const browser = | |
| await chromium.launch({ | |
| executablePath: browserPath, | |
| headless:true, | |
| args:[ | |
| "--no-sandbox", | |
| "--disable-setuid-sandbox", | |
| "--disable-dev-shm-usage" | |
| ] | |
| }); | |
| const page = await browser.newPage({ | |
| viewport:{ | |
| width:1440, | |
| height:900 | |
| } | |
| }); | |
| await page.goto(url,{ | |
| waitUntil:"commit", | |
| timeout:60000 | |
| }); | |
| const data = await page.evaluate(()=>{ | |
| const pick=(arr:string[]) => | |
| Array.from(new Set(arr.filter(Boolean))); | |
| const elements = | |
| Array.from(document.querySelectorAll("*")); | |
| const styles = | |
| elements.map(e=>getComputedStyle(e)); | |
| return { | |
| title: | |
| document.title, | |
| description: | |
| document.querySelector( | |
| 'meta[name="description"]' | |
| )?.getAttribute("content") || "", | |
| viewport: | |
| document.querySelector( | |
| 'meta[name="viewport"]' | |
| )?.getAttribute("content") || "", | |
| favicon: | |
| (document.querySelector( | |
| 'link[rel="icon"]' | |
| ) as HTMLLinkElement)?.href || "", | |
| headings: | |
| Array.from( | |
| document.querySelectorAll("h1,h2,h3,h4") | |
| ) | |
| .map(x=>x.textContent?.trim()) | |
| .filter(Boolean), | |
| images: | |
| Array.from( | |
| document.images | |
| ) | |
| .map(x=>({ | |
| src:x.src, | |
| alt:x.alt, | |
| width:x.width, | |
| height:x.height | |
| })), | |
| links: | |
| Array.from( | |
| document.querySelectorAll("a") | |
| ) | |
| .map(x=>(x as HTMLAnchorElement).href) | |
| .filter(Boolean), | |
| buttons: | |
| Array.from( | |
| document.querySelectorAll( | |
| "button,a" | |
| ) | |
| ) | |
| .map(x=>x.textContent?.trim()) | |
| .filter(Boolean), | |
| css: | |
| Array.from( | |
| document.styleSheets | |
| ) | |
| .map((x:any)=>x.href) | |
| .filter(Boolean), | |
| design:{ | |
| colors: | |
| pick( | |
| styles.map( | |
| s=>s.color | |
| ) | |
| .concat( | |
| styles.map( | |
| s=>s.backgroundColor | |
| ) | |
| ) | |
| ), | |
| fonts: | |
| pick( | |
| styles.map( | |
| s=>s.fontFamily | |
| ) | |
| ), | |
| fontSizes: | |
| pick( | |
| styles.map( | |
| s=>s.fontSize | |
| ) | |
| ), | |
| spacing: | |
| pick( | |
| styles.map( | |
| s=>`${s.margin}|${s.padding}` | |
| ) | |
| ), | |
| borderRadius: | |
| pick( | |
| styles.map( | |
| s=>s.borderRadius | |
| ) | |
| ), | |
| animations: | |
| pick( | |
| styles.map( | |
| s=>s.animation | |
| ) | |
| ), | |
| gradients: | |
| pick( | |
| styles.map( | |
| s=>s.backgroundImage | |
| ) | |
| .filter(x=>x.includes("gradient")) | |
| ) | |
| }, | |
| text: | |
| document.body.innerText | |
| .replace(/\s+/g," ") | |
| .slice(0,5000) | |
| }; | |
| }); | |
| const screenshot = | |
| `/tmp/crawl-${Date.now()}.png`; | |
| await page.screenshot({ | |
| path:screenshot, | |
| fullPage:true | |
| }); | |
| await browser.close(); | |
| return { | |
| url, | |
| screenshot, | |
| ...data | |
| }; | |
| } | |