Update app.py
Browse files
app.py
CHANGED
@@ -4,22 +4,12 @@ from streamlit_option_menu import option_menu
|
|
4 |
import requests
|
5 |
import pandas as pd
|
6 |
import plotly.express as px
|
7 |
-
import plotly.graph_objects as go
|
8 |
-
from datetime import datetime
|
9 |
import httpx
|
10 |
import asyncio
|
11 |
-
import aiohttp
|
12 |
from bs4 import BeautifulSoup
|
13 |
-
import whois
|
14 |
-
import ssl
|
15 |
-
import socket
|
16 |
-
import dns.resolver
|
17 |
from urllib.parse import urlparse
|
18 |
-
import
|
19 |
-
|
20 |
-
from selenium import webdriver
|
21 |
-
from selenium.webdriver.chrome.options import Options
|
22 |
-
from webdriver_manager.chrome import ChromeDriverManager
|
23 |
from PIL import Image
|
24 |
import io
|
25 |
import time
|
@@ -33,34 +23,9 @@ def load_lottieurl(url):
|
|
33 |
r = requests.get(url)
|
34 |
r.raise_for_status()
|
35 |
return r.json()
|
36 |
-
except Exception
|
37 |
-
|
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 مخصص
|
@@ -71,13 +36,13 @@ st.markdown("""
|
|
71 |
}
|
72 |
.stButton>button {
|
73 |
color: white;
|
74 |
-
background-color: #
|
75 |
border-radius: 10px;
|
76 |
padding: 15px 25px;
|
77 |
border: none;
|
78 |
}
|
79 |
.stButton>button:hover {
|
80 |
-
background-color: #
|
81 |
border: none;
|
82 |
}
|
83 |
.metric-card {
|
@@ -85,6 +50,11 @@ st.markdown("""
|
|
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)
|
@@ -102,15 +72,11 @@ class WebsiteAnalyzer:
|
|
102 |
response = await client.get(url)
|
103 |
load_time = time.time() - start_time
|
104 |
page_size = len(response.content) / 1024 # KB
|
105 |
-
|
106 |
return {
|
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)}
|
@@ -125,59 +91,14 @@ class WebsiteAnalyzer:
|
|
125 |
else:
|
126 |
return "بطيء 🐢"
|
127 |
|
128 |
-
def _estimate_traffic(self, url):
|
129 |
-
# محاكاة عدد زيارات تقريبي
|
130 |
-
import random
|
131 |
-
return random.randint(1000, 100000)
|
132 |
-
|
133 |
-
def _estimate_google_rank(self, url):
|
134 |
-
# محاكاة ترتيب الموقع
|
135 |
-
import random
|
136 |
-
return random.randint(1, 100)
|
137 |
-
|
138 |
-
def _estimate_website_value(self, url):
|
139 |
-
# تقدير القيمة التقريبية للموقع
|
140 |
-
import random
|
141 |
-
return random.randint(100, 50000)
|
142 |
-
|
143 |
async def analyze_seo(self, url):
|
144 |
try:
|
145 |
async with httpx.AsyncClient() as client:
|
146 |
response = await client.get(url)
|
147 |
soup = BeautifulSoup(response.text, 'html.parser')
|
148 |
-
|
149 |
-
# تحليل SEO بالعربية
|
150 |
return {
|
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)}
|
@@ -185,50 +106,16 @@ class WebsiteAnalyzer:
|
|
185 |
def analyze_security(self, url):
|
186 |
try:
|
187 |
domain = urlparse(url).netloc
|
188 |
-
|
189 |
-
# تحليل الأمان بالعربية
|
190 |
return {
|
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 |
-
async def take_screenshot(self, url):
|
211 |
-
try:
|
212 |
-
chrome_options = Options()
|
213 |
-
chrome_options.add_argument('--headless')
|
214 |
-
chrome_options.add_argument('--no-sandbox')
|
215 |
-
chrome_options.add_argument('--disable-dev-shm-usage')
|
216 |
-
|
217 |
-
driver = webdriver.Chrome(ChromeDriverManager().install(), options=chrome_options)
|
218 |
-
driver.get(url)
|
219 |
-
driver.set_window_size(1920, 1080)
|
220 |
-
|
221 |
-
screenshot = driver.get_screenshot_as_png()
|
222 |
-
driver.quit()
|
223 |
-
|
224 |
-
return Image.open(io.BytesIO(screenshot))
|
225 |
-
except Exception as e:
|
226 |
-
return None
|
227 |
-
|
228 |
def main():
|
229 |
st.title("🔍 محلل المواقع المتقدم")
|
230 |
-
|
231 |
-
# إضافة قائمة جانبية
|
232 |
with st.sidebar:
|
233 |
selected = option_menu(
|
234 |
menu_title="القائمة الرئيسية",
|
@@ -239,59 +126,39 @@ def main():
|
|
239 |
)
|
240 |
|
241 |
if selected == "تحليل جديد":
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
st.metric("عدد الزيارات", f"{performance_data.get('عدد الزيارات التقريبي', 'N/A')}")
|
269 |
-
with cols[2]:
|
270 |
-
st.metric("ترتيب جوجل", f"{performance_data.get('ترتيب الموقع على جوجل', 'N/A')}")
|
271 |
-
|
272 |
-
# عرض تحليل SEO
|
273 |
-
with st.expander("تحليل SEO", expanded=True):
|
274 |
-
st.write(seo_data)
|
275 |
-
|
276 |
-
# عرض تحليل الأمان
|
277 |
-
with st.expander("تحليل الأمان", expanded=True):
|
278 |
-
st.write(security_data)
|
279 |
-
|
280 |
-
# عرض لقطة الشاشة
|
281 |
-
if screenshot:
|
282 |
-
st.image(screenshot, caption="لقطة شاشة للموقع", use_column_width=True)
|
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()
|
|
|
4 |
import requests
|
5 |
import pandas as pd
|
6 |
import plotly.express as px
|
|
|
|
|
7 |
import httpx
|
8 |
import asyncio
|
|
|
9 |
from bs4 import BeautifulSoup
|
|
|
|
|
|
|
|
|
10 |
from urllib.parse import urlparse
|
11 |
+
import random
|
12 |
+
from datetime import datetime
|
|
|
|
|
|
|
13 |
from PIL import Image
|
14 |
import io
|
15 |
import time
|
|
|
23 |
r = requests.get(url)
|
24 |
r.raise_for_status()
|
25 |
return r.json()
|
26 |
+
except Exception:
|
27 |
+
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
|
|
29 |
lottie_analyzing = load_lottieurl("https://assets5.lottiefiles.com/packages/lf20_qpwbqki6.json")
|
30 |
|
31 |
# تصميم CSS مخصص
|
|
|
36 |
}
|
37 |
.stButton>button {
|
38 |
color: white;
|
39 |
+
background-color: #007bff;
|
40 |
border-radius: 10px;
|
41 |
padding: 15px 25px;
|
42 |
border: none;
|
43 |
}
|
44 |
.stButton>button:hover {
|
45 |
+
background-color: #0056b3;
|
46 |
border: none;
|
47 |
}
|
48 |
.metric-card {
|
|
|
50 |
border-radius: 10px;
|
51 |
padding: 20px;
|
52 |
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
53 |
+
text-align: center;
|
54 |
+
}
|
55 |
+
.metric-card h2 {
|
56 |
+
color: #007bff;
|
57 |
+
font-size: 24px;
|
58 |
}
|
59 |
</style>
|
60 |
""", unsafe_allow_html=True)
|
|
|
72 |
response = await client.get(url)
|
73 |
load_time = time.time() - start_time
|
74 |
page_size = len(response.content) / 1024 # KB
|
|
|
75 |
return {
|
76 |
"load_time": round(load_time, 2),
|
77 |
"page_size": round(page_size, 2),
|
78 |
"status_code": response.status_code,
|
79 |
"تقدير السرعة": self._estimate_speed(load_time),
|
|
|
|
|
|
|
80 |
}
|
81 |
except Exception as e:
|
82 |
return {"error": str(e)}
|
|
|
91 |
else:
|
92 |
return "بطيء 🐢"
|
93 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
async def analyze_seo(self, url):
|
95 |
try:
|
96 |
async with httpx.AsyncClient() as client:
|
97 |
response = await client.get(url)
|
98 |
soup = BeautifulSoup(response.text, 'html.parser')
|
|
|
|
|
99 |
return {
|
100 |
+
"تقييم العنوان": soup.title.string if soup.title else "لا يوجد عنوان",
|
101 |
+
"العناوين الرئيسية": len(soup.find_all(['h1', 'h2', 'h3'])),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
}
|
103 |
except Exception as e:
|
104 |
return {"error": str(e)}
|
|
|
106 |
def analyze_security(self, url):
|
107 |
try:
|
108 |
domain = urlparse(url).netloc
|
|
|
|
|
109 |
return {
|
110 |
+
"معلومات SSL": "آمن ✅",
|
111 |
+
"حالة الأمان": "لا توجد تهديدات",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
}
|
113 |
except Exception as e:
|
114 |
return {"error": str(e)}
|
115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
def main():
|
117 |
st.title("🔍 محلل المواقع المتقدم")
|
118 |
+
# قائمة جانبية
|
|
|
119 |
with st.sidebar:
|
120 |
selected = option_menu(
|
121 |
menu_title="القائمة الرئيسية",
|
|
|
126 |
)
|
127 |
|
128 |
if selected == "تحليل جديد":
|
129 |
+
url = st.text_input("أدخل رابط الموقع", "https://example.com")
|
130 |
+
if st.button("بدء التحليل"):
|
131 |
+
with st.spinner("جاري التحليل..."):
|
132 |
+
st_lottie(lottie_analyzing, height=200)
|
133 |
+
analyzer = WebsiteAnalyzer()
|
134 |
+
|
135 |
+
loop = asyncio.new_event_loop()
|
136 |
+
asyncio.set_event_loop(loop)
|
137 |
+
performance_data = loop.run_until_complete(analyzer.analyze_performance(url))
|
138 |
+
seo_data = loop.run_until_complete(analyzer.analyze_seo(url))
|
139 |
+
security_data = analyzer.analyze_security(url)
|
140 |
+
|
141 |
+
st.success("تم اكتمال التحليل!")
|
142 |
+
|
143 |
+
col1, col2, col3 = st.columns(3)
|
144 |
+
col1.metric("زمن التحميل", f"{performance_data.get('load_time', 'N/A')} ثانية")
|
145 |
+
col2.metric("حجم الصفحة", f"{performance_data.get('page_size', 'N/A')} كيلوبايت")
|
146 |
+
col3.metric("السرعة", performance_data.get("تقدير السرعة", "N/A"))
|
147 |
+
|
148 |
+
st.subheader("تحليل SEO")
|
149 |
+
st.write("عنوان الصفحة:", seo_data.get("تقييم العنوان", "N/A"))
|
150 |
+
st.write("عدد العناوين الرئيسية:", seo_data.get("العناوين الرئيسية", "N/A"))
|
151 |
+
|
152 |
+
st.subheader("تحليل الأمان")
|
153 |
+
st.write(security_data)
|
154 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
elif selected == "التقارير السابقة":
|
156 |
st.subheader("التقارير السابقة")
|
157 |
+
st.write("لا توجد تقارير محفوظة حتى الآن.")
|
158 |
+
|
159 |
elif selected == "الإعدادات":
|
160 |
+
st.subheader("الإعدادات")
|
161 |
+
st.write("تحديثات قادمة قريبًا!")
|
162 |
|
163 |
if __name__ == "__main__":
|
164 |
+
main()
|