File size: 3,330 Bytes
99b81db 820622d c9d5bf0 820622d 99b81db c9d5bf0 99b81db 820622d 99b81db 820622d c9d5bf0 99b81db 820622d 99b81db 820622d c9d5bf0 820622d c9d5bf0 820622d c9d5bf0 99b81db 820622d 99b81db 820622d c9d5bf0 820622d c9d5bf0 820622d c9d5bf0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
from fastapi import FastAPI, HTTPException, Query
from pydantic import BaseModel
from playwright.async_api import async_playwright
import asyncio
import base64
import time
from typing import Optional, List
import uvicorn
import logging
app = FastAPI()
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("analyzer")
class AnalysisResult(BaseModel):
url: str
load_time: float
title: Optional[str]
meta_description: Optional[str]
og_image: Optional[str]
seo_flags: List[str]
accessibility_flags: List[str]
screenshot_base64: str
status_code: Optional[int] = None
@app.get("/analyze", response_model=AnalysisResult)
async def analyze_website(url: str):
try:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context()
page = await context.new_page()
# Start timing
start_time = time.time()
response = await page.goto(url, timeout=60000, wait_until='domcontentloaded')
await page.wait_for_load_state("networkidle")
load_time = round(time.time() - start_time, 2)
# Screenshot
screenshot = await page.screenshot(full_page=True)
screenshot_base64 = base64.b64encode(screenshot).decode("utf-8")
# Title and meta info
title = await page.title()
meta_description = await page.eval_on_selector("meta[name='description']", "el => el.content") if await page.query_selector("meta[name='description']") else None
og_image = await page.eval_on_selector("meta[property='og:image']", "el => el.content") if await page.query_selector("meta[property='og:image']") else None
# SEO flags
seo_flags = []
if not title:
seo_flags.append("Missing <title>")
if not meta_description:
seo_flags.append("Missing meta description")
if not await page.query_selector("h1"):
seo_flags.append("Missing <h1> tag")
if not og_image:
seo_flags.append("Missing Open Graph image")
# Accessibility flags
accessibility_flags = []
images = await page.query_selector_all("img")
for img in images:
has_alt = await img.get_attribute("alt")
if not has_alt:
accessibility_flags.append("Image without alt attribute")
break
status_code = response.status if response else None
await browser.close()
return AnalysisResult(
url=url,
load_time=load_time,
title=title,
meta_description=meta_description,
og_image=og_image,
seo_flags=seo_flags,
accessibility_flags=accessibility_flags,
screenshot_base64=screenshot_base64,
status_code=status_code
)
except Exception as e:
logger.error(f"Analysis failed for {url}: {str(e)}")
raise HTTPException(status_code=500, detail=f"Error analyzing {url}: {str(e)}")
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|