import gradio as gr import logging import os from datetime import datetime from typing import Dict, List, Optional, Tuple from enhanced_legal_scraper import EnhancedLegalScraper, LegalDocument # Create log directory log_dir = '/app/logs' os.makedirs(log_dir, exist_ok=True) # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler(os.path.join(log_dir, 'legal_scraper.log')), logging.StreamHandler() ] ) logger = logging.getLogger(__name__) class LegalScraperInterface: def __init__(self): self.scraper = EnhancedLegalScraper(delay=2.0) self.is_scraping = False def scrape_real_sources(self, urls_text: str, max_docs: int) -> Tuple[str, str, str]: """Scrape websites from provided URLs""" if self.is_scraping: return "❌ اسکراپینگ در حال انجام است", "", "" try: self.is_scraping = True urls = [url.strip() for url in urls_text.split('\n') if url.strip()] if not urls: # Use default sources if no URLs provided urls = [ "https://rc.majlis.ir", "https://dolat.ir", "https://iribnews.ir" ] documents = self.scraper.scrape_real_sources(urls, max_docs) status = f"✅ اسکراپینگ کامل شد - {len(documents)} سند جمعآوری شد" # Create summary summary_lines = [ f"📊 **خلاصه نتایج:**", f"- تعداد کل اسناد: {len(documents)}", f"- منابع پردازش شده: {len(urls)}", f"- زمان اسکراپینگ: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", "", "📋 **جزئیات:**" ] for i, url in enumerate(urls): docs_from_url = [doc for doc in documents if url in doc.source_url] summary_lines.append(f"- {url}: {len(docs_from_url)} سند") summary = "\n".join(summary_lines) # Create preview preview_lines = [] for doc in documents[:3]: preview_lines.extend([ f"**{doc.title}**", f"نوع: {doc.document_type}", f"منبع: {doc.source_url}", f"امتیاز اهمیت: {doc.importance_score:.2f}", f"خلاصه: {doc.summary[:100]}..." if doc.summary else "بدون خلاصه", "---" ]) preview = "\n".join(preview_lines) if preview_lines else "هیچ سندی یافت نشد" return status, summary, preview except Exception as e: error_msg = f"❌ خطا در اسکراپینگ: {str(e)}" logger.error(error_msg) return error_msg, "", "" finally: self.is_scraping = False def get_database_stats(self) -> Tuple[str, str]: """Get database statistics and visualizations""" try: stats = self.scraper.get_enhanced_statistics() stats_lines = [ "📊 **آمار پایگاه داده:**", f"- کل اسناد: {stats.get('total_documents', 0)}", "", "📈 **بر اساس نوع:**" ] type_names = { 'law': 'قوانین', 'news': 'اخبار', 'ruling': 'آرا', 'regulation': 'آییننامه', 'general': 'عمومی' } for doc_type, count in stats.get('by_type', {}).items(): stats_lines.append(f"- {type_names.get(doc_type, doc_type)}: {count}") stats_text = "\n".join(stats_lines) # Create visualization viz_html = self._create_stats_visualization(stats) return stats_text, viz_html except Exception as e: error_msg = f"خطا در دریافت آمار: {str(e)}" logger.error(error_msg) return error_msg, "" def _create_stats_visualization(self, stats: Dict) -> str: """Create visualization for statistics""" try: import plotly.express as px import pandas as pd by_type = stats.get('by_type', {}) if by_type and stats.get('total_documents', 0) > 0: type_names = { 'law': 'قوانین', 'news': 'اخبار', 'ruling': 'آرا', 'regulation': 'آییننامه', 'general': 'عمومی' } labels = [type_names.get(k, k) for k in by_type.keys()] values = list(by_type.values()) fig = px.pie( values=values, names=labels, title="توزیع اسناد بر اساس نوع" ) fig.update_traces(textposition='inside', textinfo='percent+label') return fig.to_html() else: return "
دادهای برای نمایش یافت نشد
" except Exception as e: return f"خطا در ایجاد نمودار: {str(e)}
" def search_documents(self, query: str) -> str: """Search in collected documents""" if not query.strip(): return "لطفاً کلیدواژهای برای جستجو وارد کنید" try: results = self.scraper.search_with_similarity(query, limit=10) if not results: return f"هیچ سندی با کلیدواژه '{query}' یافت نشد" result_lines = [f"🔍 **نتایج جستجو برای '{query}':** ({len(results)} مورد یافت شد)\n"] for i, result in enumerate(results, 1): result_lines.extend([ f"**{i}. {result['title']}**", f" نوع: {result['document_type']}", f" امتیاز شباهت: {result.get('similarity_score', 0):.3f}", f" منبع: {result['source_url']}", f" خلاصه: {result.get('summary', 'ندارد')[:100]}...", "---" ]) return "\n".join(result_lines) except Exception as e: error_msg = f"خطا در جستجو: {str(e)}" logger.error(error_msg) return error_msg def export_data(self) -> Tuple[str, str]: """Export collected data""" try: filename = f"/app/data/legal_documents_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv" success = self.scraper.export_to_csv(filename) if success: return f"✅ فایل با موفقیت تولید شد: {filename}", filename else: return "❌ خطا در تولید فایل", "" except Exception as e: error_msg = f"❌ خطا در export: {str(e)}" logger.error(error_msg) return error_msg, "" def create_interface(): interface = LegalScraperInterface() css = """ .gradio-container { max-width: 1200px !important; margin: auto; font-family: 'Tahoma', sans-serif; } .header { background: linear-gradient(135deg, #2c3e50, #3498db); color: white; padding: 20px; border-radius: 10px; text-align: center; margin-bottom: 20px; } """ with gr.Blocks(css=css, title="اسکراپر اسناد حقوقی", theme=gr.themes.Soft()) as app: gr.HTML("""سیستم هوشمند جمعآوری و تحلیل اسناد حقوقی