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 |