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)