AI
Builder Hub
build-ai2026-03-1315 min

AI SEO Analyzer: Xây Dựng Công Cụ Phân Tích SEO Tự Động Với AI Và Python

Tool SEO thương mại tốn $100+/tháng. Tutorial này hướng dẫn bạn xây một công cụ AI SEO analyzer đơn giản bằng Python + OpenAI — chạy free, customize theo nhu cầu thực tế.

AI SEO Analyzer: Xây Dựng Công Cụ Phân Tích SEO Tự Động Với AI Và Python

Các tool SEO như Ahrefs hay SEMrush tốt, nhưng đắt và không flexible. Bài này hướng dẫn bạn xây một AI SEO analyzer của riêng mình — nhập URL vào, tool tự crawl và đưa ra recommendations actionable.


📌 TL;DR: Kết Quả Cuối Bài

  • Input: URL của trang cần analyze
  • Output: Báo cáo SEO với: title tag issues, meta description, heading structure, content quality, internal links, tốc độ tải
  • Tech stack: Python 3.11 + OpenAI GPT-4o + BeautifulSoup + requests
  • Thời gian build: ~1 giờ

Kiến Trúc Tool

User input (URL)
       ↓
Requests: Fetch HTML
       ↓
BeautifulSoup: Extract elements
  - title, meta description
  - H1-H6 headings
  - body text (cleaned)
  - internal/external links
  - image alt texts
       ↓
OpenAI GPT-4o: Analyze + Recommendations
       ↓
Report output (console hoặc HTML)

Setup

# Tạo virtual environment
python -m venv seo-analyzer
source seo-analyzer/bin/activate  # macOS/Linux
# seo-analyzer\Scripts\activate  # Windows

# Cài dependencies
pip install requests beautifulsoup4 openai python-dotenv

Tạo file .env:

OPENAI_API_KEY=sk-proj-your-key-here

Code: SEO Data Extractor

# seo_extractor.py
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse
import json

def extract_seo_data(url: str) -> dict:
    """Crawl URL và extract các SEO elements chính."""
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (SEO Analyzer Bot)'
    }
    
    try:
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
    except Exception as e:
        return {"error": str(e)}
    
    soup = BeautifulSoup(response.text, 'html.parser')
    base_url = f"{urlparse(url).scheme}://{urlparse(url).netloc}"
    
    # Title
    title_tag = soup.find('title')
    title = title_tag.get_text(strip=True) if title_tag else None
    
    # Meta description
    meta_desc = soup.find('meta', attrs={'name': 'description'})
    description = meta_desc.get('content', '').strip() if meta_desc else None
    
    # Headings
    headings = {}
    for level in ['h1', 'h2', 'h3', 'h4']:
        tags = soup.find_all(level)
        headings[level] = [tag.get_text(strip=True) for tag in tags]
    
    # Body text (cleaned)
    body = soup.find('body')
    if body:
        for tag in body(['script', 'style', 'nav', 'footer']):
            tag.decompose()
        body_text = ' '.join(body.get_text(separator=' ').split())[:3000]
    else:
        body_text = ''
    
    # Links
    links = soup.find_all('a', href=True)
    internal_links = []
    external_links = []
    for link in links:
        href = link.get('href', '')
        full_url = urljoin(url, href)
        if urlparse(full_url).netloc == urlparse(url).netloc:
            internal_links.append({'text': link.get_text(strip=True), 'url': full_url})
        elif href.startswith('http'):
            external_links.append({'text': link.get_text(strip=True), 'url': full_url})
    
    # Images no alt
    images = soup.find_all('img')
    images_without_alt = [img.get('src', '') for img in images if not img.get('alt')]
    
    # Word count
    word_count = len(body_text.split())
    
    return {
        'url': url,
        'title': title,
        'title_length': len(title) if title else 0,
        'description': description,
        'description_length': len(description) if description else 0,
        'headings': headings,
        'body_text_preview': body_text[:1500],
        'word_count': word_count,
        'internal_links_count': len(internal_links),
        'external_links_count': len(external_links),
        'images_without_alt': len(images_without_alt),
        'status_code': response.status_code,
        'load_time_ms': int(response.elapsed.total_seconds() * 1000)
    }

Code: AI Analyzer

# ai_analyzer.py
from openai import OpenAI
from dotenv import load_dotenv
import json

load_dotenv()
client = OpenAI()

def analyze_with_ai(seo_data: dict) -> str:
    """Gửi SEO data vào GPT-4o để phân tích và nhận recommendations."""
    
    data_str = json.dumps(seo_data, ensure_ascii=False, indent=2)
    
    prompt = f"""Bạn là một SEO expert chuyên phân tích kỹ thuật. Hãy phân tích dữ liệu SEO sau và đưa ra báo cáo có cấu trúc.

DỮ LIỆU SEO:
{data_str}

BÁO CÁO CẦN CÓ:

## 🎯 Tổng Quan (Score: X/100)

## ✅ Điểm Mạnh
(liệt kê những gì đang tốt)

## ❌ Vấn Đề Cần Sửa (theo mức độ ưu tiên)

### 🔴 Ưu tiên cao (cần sửa ngay):
- [vấn đề] → [cách sửa cụ thể]

### 🟡 Ưu tiên trung bình:
- [vấn đề] → [cách sửa cụ thể]

### 🟢 Cải thiện tiếp:
- [gợi ý nâng cao]

## 📝 Tiêu Đề Đề Xuất
(nếu title hiện tại chưa tối ưu, đề xuất 3 phiên bản)

## 📋 Meta Description Đề Xuất
(nếu chưa có hoặc kém, đề xuất 2 phiên bản)

Chú ý: Mỗi recommendation phải ACTIONABLE — chỉ rõ cần làm gì, không chỉ nêu vấn đề."""
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.3
    )
    
    return response.choices[0].message.content

Code: Main Runner

# main.py
from seo_extractor import extract_seo_data
from ai_analyzer import analyze_with_ai
import sys

def run_seo_analysis(url: str):
    print(f"\n🔍 Đang crawl: {url}")
    print("⏳ Extracting SEO data...")
    
    seo_data = extract_seo_data(url)
    
    if 'error' in seo_data:
        print(f"❌ Lỗi: {seo_data['error']}")
        return
    
    print(f"✅ Crawl xong. Load time: {seo_data['load_time_ms']}ms")
    print(f"📊 Word count: {seo_data['word_count']} words")
    print("\n🤖 Đang phân tích với AI...")
    
    report = analyze_with_ai(seo_data)
    
    print("\n" + "="*60)
    print("📋 BÁO CÁO SEO")
    print("="*60)
    print(report)
    print("="*60)
    
    # Lưu report
    with open('seo_report.md', 'w', encoding='utf-8') as f:
        f.write(f"# SEO Report: {url}\n\n")
        f.write(report)
    print("\n✅ Đã lưu vào seo_report.md")

if __name__ == "__main__":
    url = sys.argv[1] if len(sys.argv) > 1 else input("Nhập URL cần analyze: ")
    run_seo_analysis(url)

Chạy Tool

python main.py https://aibuilderhub.dev/vi/use-ai/chatgpt-beginners

Sample output:

🔍 Đang crawl: https://aibuilderhub.dev/...
✅ Crawl xong. Load time: 342ms
📊 Word count: 1247 words

🤖 Đang phân tích với AI...

## 🎯 Tổng Quan (Score: 72/100)

## ✅ Điểm Mạnh
- Title tag tồn tại và có độ dài hợp lý (58 ký tự)
- H1 duy nhất, rõ ràng
- Nội dung có chiều sâu (>1000 từ)
...

Mở Rộng Tool

Thêm XML sitemap crawler: Tự động analyze toàn bộ website

Export HTML report: Template đẹp thay vì console output

Batch mode: Analyze nhiều URL cùng lúc

Competitor comparison: So sánh SEO giữa URL của bạn vs competitor


Đọc thêm: