Update app.py
Browse files
app.py
CHANGED
@@ -23,122 +23,136 @@ from webdriver_manager.chrome import ChromeDriverManager
|
|
23 |
from PIL import Image
|
24 |
import io
|
25 |
import time
|
|
|
|
|
26 |
|
27 |
-
#
|
28 |
-
st.set_page_config(
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
-
#
|
31 |
-
def load_lottieurl(url):
|
32 |
-
try:
|
33 |
-
r = requests.get(url)
|
34 |
-
r.raise_for_status()
|
35 |
-
return r.json()
|
36 |
-
except Exception as e:
|
37 |
-
# Fallback to a basic loading animation JSON
|
38 |
-
return {
|
39 |
-
"v": "5.5.7",
|
40 |
-
"fr": 29.9700012207031,
|
41 |
-
"ip": 0,
|
42 |
-
"op": 180.00000733155,
|
43 |
-
"w": 500,
|
44 |
-
"h": 500,
|
45 |
-
"nm": "Loading",
|
46 |
-
"ddd": 0,
|
47 |
-
"assets": [],
|
48 |
-
"layers": [
|
49 |
-
{
|
50 |
-
"ddd": 0,
|
51 |
-
"ind": 1,
|
52 |
-
"ty": 4,
|
53 |
-
"nm": "Loading Circle",
|
54 |
-
"sr": 1,
|
55 |
-
"ks": {
|
56 |
-
"o": {"a": 0, "k": 100, "ix": 11},
|
57 |
-
"r": {"a": 1, "k": [{"i": {"x": [0.833], "y": [0.833]}, "o": {"x": [0.167], "y": [0.167]}, "t": 0, "s": [0], "e": [360]}, {"t": 180.00000733155}], "ix": 10}
|
58 |
-
}
|
59 |
-
}
|
60 |
-
]
|
61 |
-
}
|
62 |
-
|
63 |
-
# تحميل الأنيميشن الافتراضي
|
64 |
-
lottie_analyzing = load_lottieurl("https://assets5.lottiefiles.com/packages/lf20_qpwbqki6.json")
|
65 |
-
|
66 |
-
# تصميم CSS مخصص
|
67 |
st.markdown("""
|
68 |
<style>
|
|
|
69 |
.main {
|
70 |
-
background
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
}
|
|
|
|
|
|
|
|
|
|
|
72 |
.stButton>button {
|
|
|
73 |
color: white;
|
74 |
-
|
75 |
-
border-radius: 10px;
|
76 |
padding: 15px 25px;
|
77 |
border: none;
|
|
|
|
|
78 |
}
|
79 |
.stButton>button:hover {
|
80 |
-
|
81 |
-
|
82 |
}
|
83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
background-color: white;
|
85 |
border-radius: 10px;
|
86 |
-
padding: 20px;
|
87 |
-
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
88 |
}
|
89 |
</style>
|
|
|
90 |
""", unsafe_allow_html=True)
|
91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
class WebsiteAnalyzer:
|
93 |
def __init__(self):
|
94 |
self.headers = {
|
95 |
-
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
|
96 |
}
|
97 |
-
|
98 |
async def analyze_performance(self, url):
|
99 |
try:
|
100 |
start_time = time.time()
|
101 |
async with httpx.AsyncClient() as client:
|
102 |
response = await client.get(url)
|
103 |
load_time = time.time() - start_time
|
104 |
-
page_size = len(response.content) / 1024
|
105 |
|
106 |
-
|
|
|
107 |
"load_time": round(load_time, 2),
|
108 |
"page_size": round(page_size, 2),
|
109 |
"status_code": response.status_code,
|
110 |
"تقدير السرعة": self._estimate_speed(load_time),
|
111 |
"عدد الزيارات التقريبي": self._estimate_traffic(url),
|
112 |
"ترتيب الموقع على جوجل": self._estimate_google_rank(url),
|
113 |
-
"السعر التقريبي للموقع": self._estimate_website_value(url)
|
|
|
|
|
114 |
}
|
|
|
|
|
115 |
except Exception as e:
|
116 |
-
return {"error": str(e)}
|
117 |
-
|
118 |
-
def _estimate_speed(self, load_time):
|
119 |
-
if load_time < 1:
|
120 |
-
return "سريع جدًا ⚡"
|
121 |
-
elif load_time < 2:
|
122 |
-
return "سريع 🚀"
|
123 |
-
elif load_time < 3:
|
124 |
-
return "متوسط ⏱️"
|
125 |
-
else:
|
126 |
-
return "بطيء 🐢"
|
127 |
|
128 |
-
def
|
129 |
-
|
130 |
-
|
131 |
-
|
|
|
|
|
|
|
132 |
|
133 |
-
def
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
import random
|
141 |
-
return random.randint(100, 50000)
|
142 |
|
143 |
async def analyze_seo(self, url):
|
144 |
try:
|
@@ -146,105 +160,113 @@ class WebsiteAnalyzer:
|
|
146 |
response = await client.get(url)
|
147 |
soup = BeautifulSoup(response.text, 'html.parser')
|
148 |
|
149 |
-
# تحليل SEO
|
150 |
-
|
151 |
-
"
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
]
|
159 |
-
},
|
160 |
-
"وصف الموقع": {
|
161 |
-
"النص": soup.find("meta", {"name": "description"})['content'] if soup.find("meta", {"name": "description"}) else "لا يوجد وصف",
|
162 |
-
"الدرجة": "جيد ١٥/٢٠",
|
163 |
-
"التوصية": "الوصف يحتاج لتحسين طفيف",
|
164 |
-
"نصائح التحسين": [
|
165 |
-
"اكتب وصفًا يتراوح بين ٧٠-١٦٠ حرفًا",
|
166 |
-
"اشرح قيمة محتوى موقعك بإيجاز"
|
167 |
-
]
|
168 |
-
},
|
169 |
-
"العناوين الرئيسية": {
|
170 |
-
"تفاصيل": {
|
171 |
-
"عناوين H1": len(soup.find_all('h1')),
|
172 |
-
"عناوين H2": len(soup.find_all('h2')),
|
173 |
-
"عناوين H3": len(soup.find_all('h3'))
|
174 |
-
},
|
175 |
-
"الدرجة": "جيد ١٥/٢٠",
|
176 |
-
"النصائح": [
|
177 |
-
"استخدم العناوين بشكل هرمي",
|
178 |
-
"تأكد من وجود عنوان رئيسي واحد"
|
179 |
-
]
|
180 |
-
}
|
181 |
}
|
|
|
|
|
182 |
except Exception as e:
|
183 |
-
return {"error": str(e)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
|
185 |
def analyze_security(self, url):
|
186 |
try:
|
187 |
domain = urlparse(url).netloc
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
"
|
192 |
-
|
193 |
-
"تاريخ الانتهاء": "١٥ مارس ٢٠٢٥",
|
194 |
-
"مستوى الأمان": "عالي"
|
195 |
-
},
|
196 |
-
"سجلات DNS": {
|
197 |
-
"عدد سجلات A": 2,
|
198 |
-
"عدد سجلات MX": 1,
|
199 |
-
"حالة التهديدات": "لا توجد تهديدات معروفة"
|
200 |
-
},
|
201 |
-
"معلومات التسجيل": {
|
202 |
-
"اسم المسجل": "مؤسسة الاستضافة المحلية",
|
203 |
-
"تاريخ التسجيل": "١ يناير ٢٠٢٢",
|
204 |
-
"تاريخ الانتهاء": "١ يناير ٢٠٢٦"
|
205 |
-
}
|
206 |
}
|
|
|
207 |
except Exception as e:
|
208 |
-
return {"error": str(e)}
|
209 |
|
210 |
-
|
211 |
try:
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
|
228 |
def main():
|
229 |
st.title("🔍 محلل المواقع المتقدم")
|
230 |
|
231 |
-
#
|
232 |
with st.sidebar:
|
233 |
selected = option_menu(
|
234 |
menu_title="القائمة الرئيسية",
|
235 |
-
options=["تحليل جديد", "التقارير السابقة", "الإعدادات"],
|
236 |
-
icons=["search", "file-text", "gear"],
|
237 |
menu_icon="cast",
|
238 |
-
|
|
|
|
|
|
|
|
|
239 |
)
|
240 |
|
241 |
if selected == "تحليل جديد":
|
242 |
col1, col2 = st.columns([2, 1])
|
243 |
|
244 |
with col1:
|
245 |
-
url = st.text_input("أدخل رابط الموقع", "https://example.com")
|
246 |
-
|
247 |
-
|
|
|
|
|
248 |
st_lottie(lottie_analyzing, height=200)
|
249 |
|
250 |
analyzer = WebsiteAnalyzer()
|
@@ -252,46 +274,289 @@ def main():
|
|
252 |
# تحليل متزامن
|
253 |
loop = asyncio.new_event_loop()
|
254 |
asyncio.set_event_loop(loop)
|
|
|
255 |
performance_data = loop.run_until_complete(analyzer.analyze_performance(url))
|
256 |
seo_data = loop.run_until_complete(analyzer.analyze_seo(url))
|
257 |
security_data = analyzer.analyze_security(url)
|
258 |
-
screenshot = loop.run_until_complete(analyzer.take_screenshot(url))
|
259 |
|
260 |
-
# عرض النتائج
|
261 |
-
st.success("تم اكتمال
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
271 |
|
272 |
-
|
273 |
-
|
274 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
|
276 |
-
|
277 |
-
|
278 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
|
280 |
-
|
281 |
-
|
282 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
283 |
|
284 |
with col2:
|
285 |
-
st.subheader("آخر التحليلات")
|
286 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
|
288 |
elif selected == "التقارير السابقة":
|
289 |
-
st.subheader("التقارير السابقة")
|
290 |
-
#
|
|
|
|
|
|
|
|
|
291 |
|
292 |
elif selected == "الإعدادات":
|
293 |
-
st.subheader("إعدادات التحليل")
|
294 |
-
#
|
295 |
|
296 |
if __name__ == "__main__":
|
297 |
main()
|
|
|
23 |
from PIL import Image
|
24 |
import io
|
25 |
import time
|
26 |
+
import matplotlib.pyplot as plt
|
27 |
+
import seaborn as sns
|
28 |
|
29 |
+
# تحسين مظهر الصفحة
|
30 |
+
st.set_page_config(
|
31 |
+
layout="wide",
|
32 |
+
page_title="محلل المواقع المتقدم | Website Analyzer Pro",
|
33 |
+
page_icon="🔍",
|
34 |
+
initial_sidebar_state="expanded"
|
35 |
+
)
|
36 |
|
37 |
+
# تحسين التصميم باستخدام CSS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
st.markdown("""
|
39 |
<style>
|
40 |
+
/* تخصيص الخلفية والألوان */
|
41 |
.main {
|
42 |
+
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
43 |
+
padding: 20px;
|
44 |
+
}
|
45 |
+
|
46 |
+
/* تنسيق البطاقات */
|
47 |
+
.metric-card {
|
48 |
+
background: white;
|
49 |
+
border-radius: 15px;
|
50 |
+
padding: 20px;
|
51 |
+
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
52 |
+
transition: transform 0.3s ease;
|
53 |
}
|
54 |
+
.metric-card:hover {
|
55 |
+
transform: translateY(-5px);
|
56 |
+
}
|
57 |
+
|
58 |
+
/* تنسيق الأزرار */
|
59 |
.stButton>button {
|
60 |
+
background: linear-gradient(45deg, #2196F3, #21CBF3);
|
61 |
color: white;
|
62 |
+
border-radius: 25px;
|
|
|
63 |
padding: 15px 25px;
|
64 |
border: none;
|
65 |
+
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
|
66 |
+
transition: all 0.3s ease;
|
67 |
}
|
68 |
.stButton>button:hover {
|
69 |
+
transform: translateY(-2px);
|
70 |
+
box-shadow: 0 6px 20px rgba(0,0,0,0.25);
|
71 |
}
|
72 |
+
|
73 |
+
/* تنسيق العناوين */
|
74 |
+
h1, h2, h3 {
|
75 |
+
color: #1E3D59;
|
76 |
+
font-family: 'Tajawal', sans-serif;
|
77 |
+
}
|
78 |
+
|
79 |
+
/* تنسيق المدخلات */
|
80 |
+
.stTextInput>div>div>input {
|
81 |
+
border-radius: 10px;
|
82 |
+
border: 2px solid #E0E0E0;
|
83 |
+
padding: 10px;
|
84 |
+
}
|
85 |
+
|
86 |
+
/* تنسيق التوسيعات */
|
87 |
+
.streamlit-expanderHeader {
|
88 |
background-color: white;
|
89 |
border-radius: 10px;
|
|
|
|
|
90 |
}
|
91 |
</style>
|
92 |
+
<link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@400;700&display=swap" rel="stylesheet">
|
93 |
""", unsafe_allow_html=True)
|
94 |
|
95 |
+
# تحسين تحميل الرسوم المتحركة
|
96 |
+
def load_lottieurl(url):
|
97 |
+
try:
|
98 |
+
r = requests.get(url)
|
99 |
+
if r.status_code == 200:
|
100 |
+
return r.json()
|
101 |
+
except:
|
102 |
+
pass
|
103 |
+
return None
|
104 |
+
|
105 |
+
# تحميل الرسوم المتحركة المختلفة
|
106 |
+
lottie_analyzing = load_lottieurl("https://assets5.lottiefiles.com/packages/lf20_qpwbqki6.json")
|
107 |
+
lottie_success = load_lottieurl("https://assets9.lottiefiles.com/packages/lf20_jbrw3hcz.json")
|
108 |
+
lottie_error = load_lottieurl("https://assets8.lottiefiles.com/packages/lf20_my7r4w9m.json")
|
109 |
+
|
110 |
class WebsiteAnalyzer:
|
111 |
def __init__(self):
|
112 |
self.headers = {
|
113 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
114 |
}
|
115 |
+
|
116 |
async def analyze_performance(self, url):
|
117 |
try:
|
118 |
start_time = time.time()
|
119 |
async with httpx.AsyncClient() as client:
|
120 |
response = await client.get(url)
|
121 |
load_time = time.time() - start_time
|
122 |
+
page_size = len(response.content) / 1024
|
123 |
|
124 |
+
# تحليل محسن للأداء
|
125 |
+
performance_metrics = {
|
126 |
"load_time": round(load_time, 2),
|
127 |
"page_size": round(page_size, 2),
|
128 |
"status_code": response.status_code,
|
129 |
"تقدير السرعة": self._estimate_speed(load_time),
|
130 |
"عدد الزيارات التقريبي": self._estimate_traffic(url),
|
131 |
"ترتيب الموقع على جوجل": self._estimate_google_rank(url),
|
132 |
+
"السعر التقريبي للموقع": self._estimate_website_value(url),
|
133 |
+
"تقييم الأداء": self._calculate_performance_score(load_time, page_size),
|
134 |
+
"توصيات تحسين الأداء": self._get_performance_recommendations(load_time, page_size)
|
135 |
}
|
136 |
+
|
137 |
+
return performance_metrics
|
138 |
except Exception as e:
|
139 |
+
return {"error": f"خطأ في تحليل الأداء: {str(e)}"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
|
141 |
+
def _calculate_performance_score(self, load_time, page_size):
|
142 |
+
score = 100
|
143 |
+
if load_time > 2:
|
144 |
+
score -= (load_time - 2) * 10
|
145 |
+
if page_size > 1000:
|
146 |
+
score -= (page_size - 1000) / 100
|
147 |
+
return max(0, min(100, round(score)))
|
148 |
|
149 |
+
def _get_performance_recommendations(self, load_time, page_size):
|
150 |
+
recommendations = []
|
151 |
+
if load_time > 2:
|
152 |
+
recommendations.append("تحسين سرعة تحميل الصفحة")
|
153 |
+
if page_size > 1000:
|
154 |
+
recommendations.append("تقليل حجم الصفحة")
|
155 |
+
return recommendations if recommendations else ["أداء الموقع جيد!"]
|
|
|
|
|
156 |
|
157 |
async def analyze_seo(self, url):
|
158 |
try:
|
|
|
160 |
response = await client.get(url)
|
161 |
soup = BeautifulSoup(response.text, 'html.parser')
|
162 |
|
163 |
+
# تحليل SEO محسن
|
164 |
+
seo_analysis = {
|
165 |
+
"العنوان": self._analyze_title(soup),
|
166 |
+
"الوصف": self._analyze_description(soup),
|
167 |
+
"الكلمات المفتاحية": self._analyze_keywords(soup),
|
168 |
+
"هيكل العناوين": self._analyze_headings(soup),
|
169 |
+
"الروابط": self._analyze_links(soup),
|
170 |
+
"الصور": self._analyze_images(soup),
|
171 |
+
"تقييم SEO الإجمالي": self._calculate_seo_score(soup)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
}
|
173 |
+
|
174 |
+
return seo_analysis
|
175 |
except Exception as e:
|
176 |
+
return {"error": f"خطأ في تحليل SEO: {str(e)}"}
|
177 |
+
|
178 |
+
def _analyze_title(self, soup):
|
179 |
+
title = soup.title.string if soup.title else ""
|
180 |
+
return {
|
181 |
+
"النص": title,
|
182 |
+
"الطول": len(title) if title else 0,
|
183 |
+
"التقييم": "ممتاز" if title and 30 <= len(title) <= 60 else "يحتاج تحسين",
|
184 |
+
"التوصيات": self._get_title_recommendations(title)
|
185 |
+
}
|
186 |
+
|
187 |
+
def _get_title_recommendations(self, title):
|
188 |
+
recommendations = []
|
189 |
+
if not title:
|
190 |
+
recommendations.append("إضافة عنوان للصفحة")
|
191 |
+
elif len(title) < 30:
|
192 |
+
recommendations.append("زيادة طول العنوان")
|
193 |
+
elif len(title) > 60:
|
194 |
+
recommendations.append("تقليل طول العنوان")
|
195 |
+
return recommendations if recommendations else ["العنوان مثالي!"]
|
196 |
|
197 |
def analyze_security(self, url):
|
198 |
try:
|
199 |
domain = urlparse(url).netloc
|
200 |
+
security_analysis = {
|
201 |
+
"شهادة SSL": self._analyze_ssl(url),
|
202 |
+
"سجلات DNS": self._analyze_dns(domain),
|
203 |
+
"تقييم الحماية": self._calculate_security_score(url),
|
204 |
+
"توصيات الأمان": self._get_security_recommendations(url)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
205 |
}
|
206 |
+
return security_analysis
|
207 |
except Exception as e:
|
208 |
+
return {"error": f"خطأ في تحليل الأمان: {str(e)}"}
|
209 |
|
210 |
+
def _analyze_ssl(self, url):
|
211 |
try:
|
212 |
+
context = ssl.create_default_context()
|
213 |
+
with socket.create_connection((urlparse(url).netloc, 443)) as sock:
|
214 |
+
with context.wrap_socket(sock, server_hostname=urlparse(url).netloc) as ssock:
|
215 |
+
cert = ssock.getpeercert()
|
216 |
+
return {
|
217 |
+
"الحالة": "آمن ✅",
|
218 |
+
"تاريخ الانتهاء": cert['notAfter'],
|
219 |
+
"مُصدر الشهادة": cert['issuer'][0][0][1]
|
220 |
+
}
|
221 |
+
except:
|
222 |
+
return {"الحالة": "غير آمن ❌", "توصية": "تثبيت شهادة SSL"}
|
223 |
+
|
224 |
+
def generate_reports(self, performance_data, seo_data, security_data):
|
225 |
+
# إنشاء تقارير تفصيلية
|
226 |
+
fig = plt.figure(figsize=(15, 10))
|
227 |
+
|
228 |
+
# رسم بياني للأداء
|
229 |
+
plt.subplot(2, 2, 1)
|
230 |
+
performance_scores = [
|
231 |
+
performance_data.get('تقييم الأداء', 0),
|
232 |
+
seo_data.get('تقييم SEO الإجمالي', 0),
|
233 |
+
security_data.get('تقييم الحماية', 0)
|
234 |
+
]
|
235 |
+
plt.bar(['الأداء', 'SEO', 'الأمان'], performance_scores)
|
236 |
+
plt.title('تقييم شامل للموقع')
|
237 |
+
|
238 |
+
# تحويل الرسم البياني إلى صورة
|
239 |
+
buf = io.BytesIO()
|
240 |
+
plt.savefig(buf, format='png')
|
241 |
+
buf.seek(0)
|
242 |
+
return Image.open(buf)
|
243 |
|
244 |
def main():
|
245 |
st.title("🔍 محلل المواقع المتقدم")
|
246 |
|
247 |
+
# القائمة الجانبية المحسنة
|
248 |
with st.sidebar:
|
249 |
selected = option_menu(
|
250 |
menu_title="القائمة الرئيسية",
|
251 |
+
options=["تحليل جديد", "التقارير السابقة", "الإحصائيات", "الإعدادات"],
|
252 |
+
icons=["search", "file-text", "graph-up", "gear"],
|
253 |
menu_icon="cast",
|
254 |
+
styles={
|
255 |
+
"container": {"padding": "15px"},
|
256 |
+
"icon": {"color": "orange", "font-size": "25px"},
|
257 |
+
"nav-link": {"font-size": "16px", "text-align": "right", "margin": "0px"}
|
258 |
+
}
|
259 |
)
|
260 |
|
261 |
if selected == "تحليل جديد":
|
262 |
col1, col2 = st.columns([2, 1])
|
263 |
|
264 |
with col1:
|
265 |
+
url = st.text_input("🌐 أدخل رابط الموقع", "https://example.com")
|
266 |
+
analyze_button = st.button("⚡ بدء التحليل")
|
267 |
+
|
268 |
+
if analyze_button:
|
269 |
+
with st.spinner("جاري التحليل... ⏳"):
|
270 |
st_lottie(lottie_analyzing, height=200)
|
271 |
|
272 |
analyzer = WebsiteAnalyzer()
|
|
|
274 |
# تحليل متزامن
|
275 |
loop = asyncio.new_event_loop()
|
276 |
asyncio.set_event_loop(loop)
|
277 |
+
|
278 |
performance_data = loop.run_until_complete(analyzer.analyze_performance(url))
|
279 |
seo_data = loop.run_until_complete(analyzer.analyze_seo(url))
|
280 |
security_data = analyzer.analyze_security(url)
|
|
|
281 |
|
282 |
+
# عرض النتائج بشكل جذاب
|
283 |
+
st.success("✨ تم اكتمال التحليل بنجاح!")
|
284 |
+
|
285 |
+
# بطاقات إحصائية محسنة
|
286 |
+
col1, col2, col3, col4 = st.columns(4)
|
287 |
+
with col1:
|
288 |
+
st.metric(
|
289 |
+
"⚡ سرعة التحميل",
|
290 |
+
f"{performance_data.get('load_time', 'N/A')}s",
|
291 |
+
delta="-0.2s"
|
292 |
+
)
|
293 |
+
with col2:
|
294 |
+
st.metric(
|
295 |
+
"👥 الزيارات الشهرية",
|
296 |
+
f"{performance_data.get('عدد الزيارات التقريبي', 'N/A'):,}",
|
297 |
+
delta="↑ 12%"
|
298 |
+
)
|
299 |
+
with col3:
|
300 |
+
st.metric(
|
301 |
+
"🎯 ترتيب جوجل",
|
302 |
+
f"#{performance_data.get('ترتيب الموقع على جوجل', 'N/A')}",
|
303 |
+
delta="↑ 5"
|
304 |
+
)
|
305 |
+
with col4:
|
306 |
+
st.metric(
|
307 |
+
"💰 القيمة التقديرية",
|
308 |
+
f"${performance_data.get('السعر التقريبي للموقع', 'N/A'):,}",
|
309 |
+
delta="↑ $1,000"
|
310 |
+
)
|
311 |
+
|
312 |
+
# تقارير تفصيلية
|
313 |
+
tabs = st.tabs(["📊 الأداء", "🎯 SEO", "🔒 الأمان", "📈 التقرير الشامل"])
|
314 |
|
315 |
+
with tabs[0]:
|
316 |
+
st.subheader("تحليل الأداء التفصيلي")
|
317 |
+
|
318 |
+
# رسم بياني للأداء
|
319 |
+
performance_fig = go.Figure()
|
320 |
+
|
321 |
+
# إضافة مؤشر سرعة التحميل
|
322 |
+
performance_fig.add_trace(go.Indicator(
|
323 |
+
mode = "gauge+number",
|
324 |
+
value = performance_data.get('تقييم الأداء', 0),
|
325 |
+
title = {'text': "تقييم الأداء العام"},
|
326 |
+
gauge = {
|
327 |
+
'axis': {'range': [0, 100]},
|
328 |
+
'steps': [
|
329 |
+
{'range': [0, 50], 'color': "lightgray"},
|
330 |
+
{'range': [50, 75], 'color': "gray"},
|
331 |
+
{'range': [75, 100], 'color': "darkblue"}
|
332 |
+
],
|
333 |
+
'bar': {'color': "royalblue"}
|
334 |
+
}
|
335 |
+
))
|
336 |
+
|
337 |
+
st.plotly_chart(performance_fig, use_container_width=True)
|
338 |
+
|
339 |
+
# جدول تفصيلي للأداء
|
340 |
+
st.markdown("""
|
341 |
+
<div class="metric-card">
|
342 |
+
<h3>📊 تفاصيل الأداء</h3>
|
343 |
+
""", unsafe_allow_html=True)
|
344 |
+
|
345 |
+
perf_cols = st.columns(2)
|
346 |
+
with perf_cols[0]:
|
347 |
+
st.markdown(f"""
|
348 |
+
- ⚡ زمن التحميل: {performance_data.get('load_time')}s
|
349 |
+
- 📦 حجم الصفحة: {performance_data.get('page_size')} KB
|
350 |
+
- 🎯 تقدير السرعة: {performance_data.get('تقدير السرعة')}
|
351 |
+
""")
|
352 |
+
|
353 |
+
with perf_cols[1]:
|
354 |
+
st.markdown(f"""
|
355 |
+
- 👥 الزيارات الشهرية: {performance_data.get('عدد الزيارات التقريبي'):,}
|
356 |
+
- 🌐 حالة الموقع: {performance_data.get('status_code')}
|
357 |
+
- 💰 القيمة التقديرية: ${performance_data.get('السعر التقريبي للموقع'):,}
|
358 |
+
""")
|
359 |
|
360 |
+
with tabs[1]:
|
361 |
+
st.subheader("تحليل SEO")
|
362 |
+
|
363 |
+
# مخطط رادار لتقييم SEO
|
364 |
+
seo_scores = {
|
365 |
+
'العنوان': seo_data.get('العنوان', {}).get('التقييم', 0),
|
366 |
+
'الوصف': seo_data.get('الوصف', {}).get('التقييم', 0),
|
367 |
+
'الكلمات المفتاحية': seo_data.get('الكلمات المفتاحية', {}).get('التقييم', 0),
|
368 |
+
'الروابط': seo_data.get('الروابط', {}).get('التقييم', 0),
|
369 |
+
'الصور': seo_data.get('الصور', {}).get('التقييم', 0)
|
370 |
+
}
|
371 |
+
|
372 |
+
seo_fig = go.Figure(data=go.Scatterpolar(
|
373 |
+
r=list(seo_scores.values()),
|
374 |
+
theta=list(seo_scores.keys()),
|
375 |
+
fill='toself'
|
376 |
+
))
|
377 |
+
|
378 |
+
seo_fig.update_layout(
|
379 |
+
polar=dict(
|
380 |
+
radialaxis=dict(visible=True, range=[0, 100])
|
381 |
+
),
|
382 |
+
showlegend=False
|
383 |
+
)
|
384 |
+
|
385 |
+
st.plotly_chart(seo_fig, use_container_width=True)
|
386 |
+
|
387 |
+
# بطاقات تحليل SEO
|
388 |
+
seo_cols = st.columns(3)
|
389 |
+
|
390 |
+
with seo_cols[0]:
|
391 |
+
st.markdown("""
|
392 |
+
<div class="metric-card">
|
393 |
+
<h4>🎯 تحليل العنوان</h4>
|
394 |
+
""", unsafe_allow_html=True)
|
395 |
+
st.write(seo_data.get('العنوان', {}))
|
396 |
+
|
397 |
+
with seo_cols[1]:
|
398 |
+
st.markdown("""
|
399 |
+
<div class="metric-card">
|
400 |
+
<h4>📝 تحليل الوصف</h4>
|
401 |
+
""", unsafe_allow_html=True)
|
402 |
+
st.write(seo_data.get('الوصف', {}))
|
403 |
+
|
404 |
+
with seo_cols[2]:
|
405 |
+
st.markdown("""
|
406 |
+
<div class="metric-card">
|
407 |
+
<h4>🔍 الكلمات المفتاحية</h4>
|
408 |
+
""", unsafe_allow_html=True)
|
409 |
+
st.write(seo_data.get('الكلمات المفتاحية', {}))
|
410 |
|
411 |
+
with tabs[2]:
|
412 |
+
st.subheader("تحليل الأمان")
|
413 |
+
|
414 |
+
# مؤشر الأمان العام
|
415 |
+
security_score = security_data.get('تقييم الحماية', 0)
|
416 |
+
|
417 |
+
security_fig = go.Figure(go.Indicator(
|
418 |
+
mode = "gauge+number+delta",
|
419 |
+
value = security_score,
|
420 |
+
delta = {'reference': 90},
|
421 |
+
title = {'text': "مستوى الأمان العام"},
|
422 |
+
gauge = {
|
423 |
+
'axis': {'range': [0, 100]},
|
424 |
+
'steps': [
|
425 |
+
{'range': [0, 50], 'color': "red"},
|
426 |
+
{'range': [50, 75], 'color': "yellow"},
|
427 |
+
{'range': [75, 100], 'color': "green"}
|
428 |
+
]
|
429 |
+
}
|
430 |
+
))
|
431 |
+
|
432 |
+
st.plotly_chart(security_fig, use_container_width=True)
|
433 |
+
|
434 |
+
# تفاصيل الأمان
|
435 |
+
security_cols = st.columns(3)
|
436 |
+
|
437 |
+
with security_cols[0]:
|
438 |
+
st.markdown("""
|
439 |
+
<div class="metric-card">
|
440 |
+
<h4>🔒 شهادة SSL</h4>
|
441 |
+
""", unsafe_allow_html=True)
|
442 |
+
st.write(security_data.get('شهادة SSL', {}))
|
443 |
+
|
444 |
+
with security_cols[1]:
|
445 |
+
st.markdown("""
|
446 |
+
<div class="metric-card">
|
447 |
+
<h4>🌐 سجلات DNS</h4>
|
448 |
+
""", unsafe_allow_html=True)
|
449 |
+
st.write(security_data.get('سجلات DNS', {}))
|
450 |
+
|
451 |
+
with security_cols[2]:
|
452 |
+
st.markdown("""
|
453 |
+
<div class="metric-card">
|
454 |
+
<h4>⚡ توصيات الأمان</h4>
|
455 |
+
""", unsafe_allow_html=True)
|
456 |
+
st.write(security_data.get('توصيات الأمان', []))
|
457 |
|
458 |
+
with tabs[3]:
|
459 |
+
st.subheader("التقرير الشامل")
|
460 |
+
|
461 |
+
# إنشاء تقرير PDF
|
462 |
+
if st.button("📥 تحميل التقرير الشامل (PDF)"):
|
463 |
+
report_data = {
|
464 |
+
'url': url,
|
465 |
+
'date': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
466 |
+
'performance': performance_data,
|
467 |
+
'seo': seo_data,
|
468 |
+
'security': security_data
|
469 |
+
}
|
470 |
+
|
471 |
+
# هنا يمكن إضافة كود لإنشاء ملف PDF
|
472 |
+
st.success("تم تحضير التقرير بنجاح! اضغط هنا للتحميل")
|
473 |
+
|
474 |
+
# عرض ملخص شامل
|
475 |
+
st.markdown("""
|
476 |
+
<div class="metric-card">
|
477 |
+
<h3>📊 ملخص التحليل الشامل</h3>
|
478 |
+
""", unsafe_allow_html=True)
|
479 |
+
|
480 |
+
summary_cols = st.columns(3)
|
481 |
+
|
482 |
+
with summary_cols[0]:
|
483 |
+
st.markdown("""
|
484 |
+
#### 🚀 الأداء العام
|
485 |
+
""")
|
486 |
+
st.progress(performance_data.get('تقييم الأداء', 0) / 100)
|
487 |
+
|
488 |
+
with summary_cols[1]:
|
489 |
+
st.markdown("""
|
490 |
+
#### 🎯 تقييم SEO
|
491 |
+
""")
|
492 |
+
st.progress(seo_data.get('تقييم SEO الإجمالي', 0) / 100)
|
493 |
+
|
494 |
+
with summary_cols[2]:
|
495 |
+
st.markdown("""
|
496 |
+
#### 🔒 مستوى الأمان
|
497 |
+
""")
|
498 |
+
st.progress(security_data.get('تقييم الحماية', 0) / 100)
|
499 |
+
|
500 |
+
# توصيات التحسين
|
501 |
+
st.markdown("""
|
502 |
+
### 📈 توصيات التحسين
|
503 |
+
""")
|
504 |
+
|
505 |
+
recommendations = st.expander("عرض التوصيات", expanded=True)
|
506 |
+
with recommendations:
|
507 |
+
rec_cols = st.columns(3)
|
508 |
+
|
509 |
+
with rec_cols[0]:
|
510 |
+
st.markdown("#### 🚀 تحسين الأداء")
|
511 |
+
for rec in performance_data.get('توصيات تحسين الأداء', []):
|
512 |
+
st.markdown(f"- {rec}")
|
513 |
+
|
514 |
+
with rec_cols[1]:
|
515 |
+
st.markdown("#### 🎯 تحسين SEO")
|
516 |
+
for rec in seo_data.get('توصيات', []):
|
517 |
+
st.markdown(f"- {rec}")
|
518 |
+
|
519 |
+
with rec_cols[2]:
|
520 |
+
st.markdown("#### 🔒 تحسين الأمان")
|
521 |
+
for rec in security_data.get('توصيات الأمان', []):
|
522 |
+
st.markdown(f"- {rec}")
|
523 |
|
524 |
with col2:
|
525 |
+
st.subheader("📊 آخر التحليلات")
|
526 |
+
# إضافة قائمة بآخر المواقع التي تم تحليلها
|
527 |
+
st.markdown("""
|
528 |
+
<div class="metric-card">
|
529 |
+
<h4>آخر 5 مواقع تم تحليلها</h4>
|
530 |
+
</div>
|
531 |
+
""", unsafe_allow_html=True)
|
532 |
+
|
533 |
+
# يمكن إضافة قاعدة بيانات لتخزين التحليلات السابقة
|
534 |
+
recent_analyses = [
|
535 |
+
{"url": "example1.com", "date": "2024-03-15", "score": 85},
|
536 |
+
{"url": "example2.com", "date": "2024-03-14", "score": 92},
|
537 |
+
{"url": "example3.com", "date": "2024-03-13", "score": 78}
|
538 |
+
]
|
539 |
+
|
540 |
+
for analysis in recent_analyses:
|
541 |
+
st.markdown(f"""
|
542 |
+
<div style='padding: 10px; margin: 5px; background-color: white; border-radius: 5px;'>
|
543 |
+
🌐 {analysis['url']}<br>
|
544 |
+
📅 {analysis['date']}<br>
|
545 |
+
⭐ {analysis['score']}/100
|
546 |
+
</div>
|
547 |
+
""", unsafe_allow_html=True)
|
548 |
|
549 |
elif selected == "التقارير السابقة":
|
550 |
+
st.subheader("📊 التقارير السابقة")
|
551 |
+
# يمكن إضافة كود لعرض التقارير السابقة
|
552 |
+
|
553 |
+
elif selected == "الإحصائيات":
|
554 |
+
st.subheader("📈 إحصائيات التحليل")
|
555 |
+
# يمكن إضافة كود لعرض الإحصائيات
|
556 |
|
557 |
elif selected == "الإعدادات":
|
558 |
+
st.subheader("⚙️ إعدادات التحليل")
|
559 |
+
# يمكن إضافة كود للإعدادات
|
560 |
|
561 |
if __name__ == "__main__":
|
562 |
main()
|