""" Meta Description Generator AI-powered meta description generation for SEO """ import os import re from typing import Dict, List def generate_meta_description(page: Dict, api_keys: Dict = None) -> str: """ Generate SEO-optimized meta description for a page Uses AI if available, falls back to smart extraction """ title = page.get('title', '') text = page.get('text', '') headings = page.get('headings', []) url = page.get('url', '') # Try AI generation first ai_description = _generate_with_ai(title, text, headings, api_keys) if ai_description: return ai_description # Fallback to smart extraction return _generate_smart_description(title, text, headings) def _generate_with_ai(title: str, text: str, headings: List, api_keys: Dict = None) -> str: """Generate meta description using AI (Groq or OpenAI)""" try: # Try Groq first (faster and free) groq_key = (api_keys or {}).get('groq') or os.getenv('GROQ_API_KEY') if groq_key: return _generate_with_groq(title, text, headings, groq_key) # Fallback to OpenAI openai_key = (api_keys or {}).get('openai') or os.getenv('OPENAI_API_KEY') if openai_key: return _generate_with_openai(title, text, headings, openai_key) return None except Exception as e: print(f"AI meta generation failed: {e}") return None def _generate_with_groq(title: str, text: str, headings: List, api_key: str) -> str: """Generate using Groq API""" try: import requests # Extract key points from text text_sample = text[:1000] if text else '' headings_text = ' '.join([h.get('text', '') if isinstance(h, dict) else str(h) for h in headings[:5]]) prompt = f"""اكتب وصف meta description مثالي لصفحة ويب بالمواصفات التالية: - العنوان: {title} - المحتوى: {text_sample} - العناوين: {headings_text} المتطلبات: - الطول: 150-160 حرف بالضبط - يجب أن يكون جذاب ومقنع - يحتوي على كلمات مفتاحية - يشجع على النقر - بدون علامات تنصيص اكتب الوصف فقط بدون أي نص إضافي:""" response = requests.post( 'https://api.groq.com/openai/v1/chat/completions', headers={ 'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json' }, json={ 'model': 'llama-3.3-70b-versatile', 'messages': [{'role': 'user', 'content': prompt}], 'temperature': 0.7, 'max_tokens': 100 }, timeout=15 ) if response.status_code == 200: data = response.json() description = data['choices'][0]['message']['content'].strip() # Clean up description = description.replace('"', '').replace("'", '').strip() # Ensure proper length if len(description) > 160: description = description[:157] + '...' return description return None except Exception as e: print(f"Groq meta generation error: {e}") return None def _generate_with_openai(title: str, text: str, headings: List, api_key: str) -> str: """Generate using OpenAI API""" try: import requests text_sample = text[:1000] if text else '' headings_text = ' '.join([h.get('text', '') if isinstance(h, dict) else str(h) for h in headings[:5]]) prompt = f"""Write a perfect meta description for a webpage with these details: - Title: {title} - Content: {text_sample} - Headings: {headings_text} Requirements: - Exactly 150-160 characters - Compelling and click-worthy - Contains keywords - No quotation marks Write only the description:""" response = requests.post( 'https://api.openai.com/v1/chat/completions', headers={ 'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json' }, json={ 'model': 'gpt-3.5-turbo', 'messages': [{'role': 'user', 'content': prompt}], 'temperature': 0.7, 'max_tokens': 100 }, timeout=15 ) if response.status_code == 200: data = response.json() description = data['choices'][0]['message']['content'].strip() description = description.replace('"', '').replace("'", '').strip() if len(description) > 160: description = description[:157] + '...' return description return None except Exception as e: print(f"OpenAI meta generation error: {e}") return None def _generate_smart_description(title: str, text: str, headings: List) -> str: """Generate meta description using smart extraction (no AI)""" # Clean text text = re.sub(r'\s+', ' ', text).strip() # Try to find first meaningful paragraph sentences = re.split(r'[.!?]+', text) description = '' for sentence in sentences: sentence = sentence.strip() if len(sentence) > 50 and len(sentence) < 200: description = sentence break # If no good sentence, use title + first heading if not description and headings: first_heading = headings[0] heading_text = first_heading.get('text', '') if isinstance(first_heading, dict) else str(first_heading) description = f"{title} - {heading_text}" # If still nothing, use title + generic text if not description: description = f"{title} - اكتشف خدماتنا ومنتجاتنا المتميزة" # Ensure proper length if len(description) > 160: description = description[:157] + '...' elif len(description) < 120: description += ' - تواصل معنا الآن للمزيد من المعلومات' return description def generate_meta_descriptions_for_audit(audit: Dict, api_keys: Dict = None) -> List[Dict]: """Generate meta descriptions for all pages in audit""" pages = audit.get('pages', []) results = [] for page in pages: url = page.get('url', '') title = page.get('title', '') # Check if page already has meta description html = page.get('html', '') existing_meta = re.search(r' 160: issues.append('طويل جداً (أكثر من 160 حرف)') if not any(keyword in existing_description.lower() for keyword in title.lower().split()[:3]): issues.append('لا يحتوي على كلمات مفتاحية من العنوان') results.append({ 'url': url, 'title': title, 'has_meta': has_meta, 'existing': existing_description, 'suggested': new_description, 'issues': issues, 'status': 'جيد ✓' if has_meta and not issues else 'يحتاج تحسين ⚠️' if has_meta else 'مفقود ❌' }) return results def get_meta_description_recommendations(audit: Dict) -> Dict: """Get summary and recommendations for meta descriptions""" pages = audit.get('pages', []) total_pages = len(pages) pages_with_meta = 0 pages_with_good_meta = 0 pages_missing_meta = 0 for page in pages: html = page.get('html', '') meta_match = re.search(r' 0 else 0 recommendations = [] if pages_missing_meta > 0: recommendations.append(f'أضف meta description لـ {pages_missing_meta} صفحة') if pages_with_meta - pages_with_good_meta > 0: recommendations.append(f'حسّن meta description لـ {pages_with_meta - pages_with_good_meta} صفحة') return { 'score': score, 'total_pages': total_pages, 'pages_with_meta': pages_with_meta, 'pages_with_good_meta': pages_with_good_meta, 'pages_missing_meta': pages_missing_meta, 'status': 'ممتاز ✅' if score >= 90 else 'جيد ✓' if score >= 70 else 'يحتاج تحسين ⚠️', 'recommendations': recommendations }