Spaces:
Running
Running
| import subprocess | |
| # الأمر لتحميل مكتبة معينة باستخدام pip | |
| command = "pip install whois urllib.parse" | |
| # تنفيذ الأمر في التيرمينال | |
| subprocess.run(command, shell=True) | |
| from flask import Flask, request, jsonify | |
| import whois | |
| import requests | |
| from urllib.parse import urlparse | |
| app = Flask(__name__) | |
| # Store the HTML content in a variable | |
| HTML_CONTENT = '''<!DOCTYPE html> | |
| <html dir="rtl" lang="ar"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>سبيدي | فاحص المواقع السريع</title> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Cairo:wght@400;600;700&display=swap'); | |
| :root { | |
| --speedy-primary: #8B4513; | |
| --speedy-dark: #5C2C0B; | |
| --speedy-light: #F5E6DB; | |
| --speedy-accent: #D2691E; | |
| --speedy-bg: #FDF9F6; | |
| --speedy-text: #3E2723; | |
| --speedy-border: #DEB887; | |
| --speedy-gradient: linear-gradient(135deg, #8B4513 0%, #5C2C0B 100%); | |
| --speedy-shadow: 0 4px 6px rgba(139, 69, 19, 0.2); | |
| } | |
| body { | |
| font-family: 'Cairo', sans-serif; | |
| margin: 0; | |
| padding: 20px; | |
| background: var(--speedy-bg); | |
| color: var(--speedy-text); | |
| line-height: 1.6; | |
| } | |
| .container { | |
| max-width: 900px; | |
| margin: 20px auto; | |
| background: white; | |
| padding: 30px; | |
| border-radius: 20px; | |
| box-shadow: var(--speedy-shadow); | |
| border: 1px solid var(--speedy-border); | |
| } | |
| .brand { | |
| text-align: center; | |
| margin-bottom: 10px; | |
| } | |
| .logo { | |
| font-size: 3em; | |
| font-weight: 700; | |
| color: var(--speedy-primary); | |
| text-shadow: 2px 2px 4px rgba(139, 69, 19, 0.2); | |
| margin: 0; | |
| } | |
| .tagline { | |
| color: var(--speedy-accent); | |
| font-size: 1.2em; | |
| margin-top: 5px; | |
| } | |
| h1 { | |
| text-align: center; | |
| color: var(--speedy-dark); | |
| font-size: 2em; | |
| margin: 20px 0; | |
| font-weight: 700; | |
| } | |
| .input-group { | |
| display: flex; | |
| gap: 15px; | |
| margin: 30px auto; | |
| max-width: 700px; | |
| padding: 20px; | |
| background: var(--speedy-light); | |
| border-radius: 16px; | |
| box-shadow: inset 0 2px 4px rgba(92, 44, 11, 0.1); | |
| } | |
| input { | |
| flex: 1; | |
| padding: 15px 20px; | |
| border: 2px solid var(--speedy-border); | |
| border-radius: 12px; | |
| font-size: 16px; | |
| transition: all 0.3s ease; | |
| font-family: 'Cairo', sans-serif; | |
| background: white; | |
| color: var(--speedy-text); | |
| } | |
| input:focus { | |
| outline: none; | |
| border-color: var(--speedy-primary); | |
| box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.2); | |
| } | |
| input::placeholder { | |
| color: var(--speedy-border); | |
| } | |
| button { | |
| padding: 15px 30px; | |
| background: var(--speedy-gradient); | |
| color: white; | |
| border: none; | |
| border-radius: 12px; | |
| cursor: pointer; | |
| font-size: 16px; | |
| font-weight: 600; | |
| transition: all 0.3s ease; | |
| font-family: 'Cairo', sans-serif; | |
| } | |
| button:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 12px rgba(92, 44, 11, 0.3); | |
| } | |
| button:active { | |
| transform: translateY(0); | |
| background: var(--speedy-dark); | |
| } | |
| button:disabled { | |
| background: var(--speedy-border); | |
| transform: none; | |
| box-shadow: none; | |
| } | |
| .loading { | |
| text-align: center; | |
| display: none; | |
| margin: 20px 0; | |
| color: var(--speedy-primary); | |
| font-weight: 600; | |
| } | |
| .loading::after { | |
| content: '🚀'; | |
| display: inline-block; | |
| margin-right: 10px; | |
| animation: rocket 1s infinite; | |
| } | |
| @keyframes rocket { | |
| 0% { transform: translateY(0) rotate(45deg); } | |
| 50% { transform: translateY(-10px) rotate(45deg); } | |
| 100% { transform: translateY(0) rotate(45deg); } | |
| } | |
| .results { | |
| margin-top: 30px; | |
| display: none; | |
| animation: fadeIn 0.5s ease; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(20px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .results-section { | |
| background: white; | |
| border-radius: 16px; | |
| padding: 25px; | |
| margin-bottom: 20px; | |
| border: 1px solid var(--speedy-border); | |
| transition: all 0.3s ease; | |
| } | |
| .results-section:hover { | |
| transform: translateY(-3px); | |
| box-shadow: var(--speedy-shadow); | |
| border-color: var(--speedy-primary); | |
| } | |
| .results h2 { | |
| color: var(--speedy-dark); | |
| border-bottom: 2px solid var(--speedy-primary); | |
| padding-bottom: 10px; | |
| margin-bottom: 20px; | |
| } | |
| .info-item { | |
| display: flex; | |
| justify-content: space-between; | |
| padding: 12px; | |
| border-bottom: 1px solid var(--speedy-light); | |
| transition: background-color 0.2s ease; | |
| } | |
| .info-item:hover { | |
| background-color: var(--speedy-bg); | |
| border-radius: 8px; | |
| } | |
| .info-item:last-child { | |
| border-bottom: none; | |
| } | |
| .info-label { | |
| font-weight: 600; | |
| color: var(--speedy-text); | |
| } | |
| .info-value { | |
| color: var(--speedy-primary); | |
| } | |
| .error { | |
| color: #D35400; | |
| background: rgba(211, 84, 0, 0.1); | |
| padding: 15px; | |
| border-radius: 12px; | |
| text-align: center; | |
| margin: 20px 0; | |
| display: none; | |
| border: 1px solid rgba(211, 84, 0, 0.3); | |
| } | |
| @media (max-width: 768px) { | |
| .input-group { | |
| flex-direction: column; | |
| } | |
| button { | |
| width: 100%; | |
| } | |
| .container { | |
| padding: 20px; | |
| } | |
| .logo { | |
| font-size: 2.5em; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="brand"> | |
| <h1 class="logo">سبيدي</h1> | |
| <div class="tagline">فاحص المواقع السريع والذكي</div> | |
| </div> | |
| <div class="input-group"> | |
| <input type="url" id="urlInput" placeholder="https://example.com" dir="ltr"> | |
| <button onclick="checkUrl()">فحص سريع</button> | |
| </div> | |
| <div class="loading" id="loading"> | |
| جاري التحليل السريع للموقع... | |
| </div> | |
| <div class="error" id="error"></div> | |
| <div class="results" id="results"> | |
| <div class="results-section"> | |
| <h2>معلومات الموقع</h2> | |
| <div id="info"></div> | |
| </div> | |
| <div class="results-section"> | |
| <h2>نصائح تحسين الموقع</h2> | |
| <div id="tips"></div> | |
| </div> | |
| <div class="results-section"> | |
| <h2>تحليل الزيارات</h2> | |
| <div id="traffic"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| async function checkUrl() { | |
| const urlInput = document.getElementById('urlInput'); | |
| const loading = document.getElementById('loading'); | |
| const results = document.getElementById('results'); | |
| const error = document.getElementById('error'); | |
| const button = document.querySelector('button'); | |
| if (!urlInput.value) { | |
| error.textContent = 'الرجاء إدخال رابط صالح للفحص'; | |
| error.style.display = 'block'; | |
| return; | |
| } | |
| error.style.display = 'none'; | |
| results.style.display = 'none'; | |
| loading.style.display = 'block'; | |
| button.disabled = true; | |
| try { | |
| const response = await fetch('/check-url', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ url: urlInput.value }) | |
| }); | |
| const data = await response.json(); | |
| if (data.error) { | |
| error.textContent = data.error; | |
| error.style.display = 'block'; | |
| } else { | |
| document.getElementById('info').innerHTML = formatInfo(data.info); | |
| document.getElementById('tips').innerHTML = formatList(data.tips); | |
| document.getElementById('traffic').innerHTML = formatList(data.traffic_estimate); | |
| results.style.display = 'block'; | |
| } | |
| } catch (err) { | |
| error.textContent = 'عذراً، حدث خطأ أثناء الاتصال بالخادم'; | |
| error.style.display = 'block'; | |
| } finally { | |
| loading.style.display = 'none'; | |
| button.disabled = false; | |
| } | |
| } | |
| function formatInfo(info) { | |
| return Object.entries(info) | |
| .map(([key, value]) => ` | |
| <div class="info-item"> | |
| <span class="info-label">${key}</span> | |
| <span class="info-value">${value}</span> | |
| </div> | |
| `).join(''); | |
| } | |
| function formatList(items) { | |
| return items | |
| .map(item => `<div class="info-item">${item}</div>`) | |
| .join(''); | |
| } | |
| </script> | |
| </body> | |
| </html>''' | |
| def get_url_info(url): | |
| try: | |
| response = requests.get(url, timeout=10) | |
| response.raise_for_status() | |
| domain = urlparse(url).netloc | |
| domain_info = whois.whois(domain) | |
| registrar = domain_info.get('registrar', 'غير متوفر') | |
| creation_date = domain_info.get('creation_date', 'غير متوفر') | |
| expiration_date = domain_info.get('expiration_date', 'غير متوفر') | |
| info = { | |
| 'رابط': url, | |
| 'بروتوكول': urlparse(url).scheme, | |
| 'النطاق': domain, | |
| 'رمز الحالة': response.status_code, | |
| 'حجم المحتوى (بايت)': len(response.content), | |
| 'نوع المحتوى': response.headers.get('Content-Type', 'غير متوفر'), | |
| 'تاريخ الاستجابة': response.headers.get('Date', 'غير متوفر'), | |
| 'مسجل النطاق': registrar, | |
| 'تاريخ تسجيل النطاق': str(creation_date), | |
| 'تاريخ انتهاء النطاق': str(expiration_date) | |
| } | |
| return info | |
| except requests.RequestException as e: | |
| return {'error': f'خطأ في الوصول إلى الرابط {url}: {e}'} | |
| except Exception as e: | |
| return {'error': f'حدث خطأ أثناء جمع المعلومات: {e}'} | |
| def provide_website_tips(status_code): | |
| tips = [] | |
| if status_code == 200: | |
| tips.append("- الموقع يعمل بشكل جيد. تأكد من تحسين سرعة التحميل وتجربة المستخدم.") | |
| elif status_code == 404: | |
| tips.append("- الصفحة غير موجودة. تأكد من تحديث الروابط أو إنشاء صفحة 404 مخصصة.") | |
| elif status_code >= 500: | |
| tips.append("- خطأ في الخادم. تحقق من تكوين الخادم وتأكد من عدم وجود مشاكل في البرمجة.") | |
| else: | |
| tips.append(f"- حالة غير متوقعة: {status_code}. تحقق من إعدادات الخادم وتحسين جودة الموقع.") | |
| return tips | |
| def estimate_traffic(url): | |
| traffic_estimate = [] | |
| if 'example.com' in url: | |
| traffic_estimate.append("- الموقع يستخدم مثالاً، لذا تقدير الزيارات غير ممكن.") | |
| else: | |
| if 'edu' in urlparse(url).netloc: | |
| traffic_estimate.append("- المواقع التعليمية غالباً ما يكون لديها حركة مرور معتدلة إلى مرتفعة.") | |
| else: | |
| traffic_estimate.append("- تقدير عدد الزيارات غير متاح بدون أدوات تحليل متقدمة.") | |
| return traffic_estimate | |
| def index(): | |
| return HTML_CONTENT | |
| def check_url(): | |
| data = request.json | |
| url = data.get('url', '') | |
| if not url: | |
| return jsonify({'error': 'مطلوب إدخال الرابط'}), 400 | |
| info |