joermd commited on
Commit
d373a49
·
verified ·
1 Parent(s): e15250c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +191 -169
app.py CHANGED
@@ -1,175 +1,197 @@
1
  import streamlit as st
2
  import requests
 
 
 
3
  import whois
4
- import socket
5
  import ssl
6
- from bs4 import BeautifulSoup
 
7
  from datetime import datetime
 
 
8
  import matplotlib.pyplot as plt
9
- from wordcloud import WordCloud
10
- # تم إزالة TextBlob و NLTK
11
-
12
- # إعداد العربية في Streamlit
13
- st.set_page_config(page_title="أداة تحليل المواقع", layout="wide")
14
-
15
- def get_ssl_expiry_date(hostname):
16
- try:
17
- context = ssl.create_default_context()
18
- with socket.create_connection((hostname, 443), timeout=3) as sock:
19
- with context.wrap_socket(sock, server_hostname=hostname) as ssock:
20
- ssl_info = ssock.getpeercert()
21
- expire_date = datetime.strptime(ssl_info['notAfter'], '%b %d %H:%M:%S %Y %Z')
22
- days_left = (expire_date - datetime.utcnow()).days
23
- return days_left
24
- except Exception:
25
- return None
26
-
27
- def main():
28
- st.title("🕵️‍♂️ أداة تحليل المواقع الشاملة")
29
-
30
- url = st.text_input("أدخل رابط الموقع (مثال: https://www.example.com)")
31
-
32
- if st.button("تحليل") and url:
33
- if not url.startswith("http"):
34
- url = "http://" + url
35
-
36
- try:
37
- response = requests.get(url, timeout=5)
38
- status_code = response.status_code
39
-
40
- if status_code != 200:
41
- st.error(f"الموقع غير متاح. رمز الحالة: {status_code}")
42
- return
43
-
44
- # تحليل SEO
45
- soup = BeautifulSoup(response.content, 'html.parser')
46
- title = soup.title.string.strip() if soup.title else "لم يتم العثور على وسم العنوان"
47
- meta_desc = soup.find('meta', attrs={'name': 'description'})
48
- meta_desc_content = meta_desc['content'].strip() if meta_desc else "لم يتم العثور على ميتا الوصف"
49
-
50
- # تحليل الكلمات المفتاحية (بدون TextBlob و NLTK)
51
- texts = soup.get_text()
52
- # تقسيم النص إلى كلمات واستبعاد الكلمات الشائعة
53
- words = texts.lower().split()
54
- common_words = set(['و', 'في', 'من', 'على', 'أن', 'إلى', 'عن', 'هو', 'مع', 'هذا', 'ما', 'لم', 'كما', 'كل'])
55
- filtered_words = [word for word in words if word.isalpha() and word not in common_words]
56
- word_counts = {}
57
- for word in filtered_words:
58
- word_counts[word] = word_counts.get(word, 0) + 1
59
- sorted_keywords = sorted(word_counts.items(), key=lambda x: x[1], reverse=True)[:10]
60
-
61
- # رسم سحابة الكلمات
62
- wordcloud = WordCloud(width=800, height=400, background_color='white', font_path='arial').generate(' '.join(filtered_words))
63
- fig_wc, ax_wc = plt.subplots(figsize=(12, 6))
64
- ax_wc.imshow(wordcloud, interpolation='bilinear')
65
- ax_wc.axis('off')
66
-
67
- # معلومات WHOIS
68
- domain = url.replace("http://", "").replace("https://", "").split('/')[0]
69
- domain_info = whois.whois(domain)
70
-
71
- # فحص SSL
72
- ssl_days_left = get_ssl_expiry_date(domain)
73
- if ssl_days_left is not None:
74
- ssl_status = f"شهادة SSL تنتهي صلاحيتها خلال {ssl_days_left} يومًا"
75
- else:
76
- ssl_status = "لم يتم العثور على شهادة SSL"
77
-
78
- # فحص الأمان
79
- security_score = 0
80
- headers = response.headers
81
-
82
- security_headers = {
83
- 'X-Frame-Options': 'حماية من النقر',
84
- 'X-Content-Type-Options': 'منع نوع المحتوى',
85
- 'Content-Security-Policy': 'سياسة أمان المحتوى',
86
- 'Strict-Transport-Security': 'أمان النقل الصارم',
87
- 'Referrer-Policy': 'سياسة المرجع'
88
- }
89
-
90
- for header in security_headers:
91
- if header in headers:
92
- security_score += 10
93
-
94
- # حساب التقييم الكلي
95
- total_score = security_score
96
- if title != "لم يتم العثور على وسم العنوان":
97
- total_score += 15
98
- if meta_desc_content != "لم يتم العثور على ميتا الوصف":
99
- total_score += 15
100
- if ssl_days_left is not None:
101
- total_score += 20
102
-
103
- # الحد الأقصى للتقييم هو 100
104
- if total_score > 100:
105
- total_score = 100
106
-
107
- # عرض النتائج
108
- st.header("📊 نتائج التحليل")
109
-
110
- col1, col2 = st.columns(2)
111
-
112
- with col1:
113
- st.subheader("تحليل SEO")
114
- st.write(f"**وسم العنوان:** {title}")
115
- st.write(f"**ميتا الوصف:** {meta_desc_content}")
116
-
117
- st.subheader("أهم الكلمات تكرارًا")
118
- for word, count in sorted_keywords:
119
- st.write(f"- {word}: {count} مرة")
120
-
121
- st.pyplot(fig_wc)
122
-
123
- with col2:
124
- st.subheader("تحليل الأمان")
125
- st.write(f"**حالة SSL:** {ssl_status}")
126
- st.write("**عناوين الأمان:**")
127
- for header, desc in security_headers.items():
128
- if header in headers:
129
- st.write(f"- {header}: متوفر ({desc})")
130
- else:
131
- st.write(f"- {header}: غير متوفر ({desc})")
132
-
133
- st.subheader("معلومات WHOIS")
134
- st.write(f"**اسم النطاق:** {domain_info.domain_name}")
135
- st.write(f"**المسجل:** {domain_info.registrar}")
136
- st.write(f"**تاريخ الإنشاء:** {domain_info.creation_date}")
137
- st.write(f"**تاريخ الانتهاء:** {domain_info.expiration_date}")
138
-
139
- st.header("🏆 التقييم الكلي")
140
- st.write(f"**التقييم الإجمالي:** {total_score} / 100")
141
-
142
- # رسم بياني للتقييم
143
- labels = ['SEO', 'الأمان', 'SSL', 'أخرى']
144
- sizes = [30 if title != "لم يتم العثور على وسم العنوان" else 0,
145
- security_score,
146
- 20 if ssl_days_left is not None else 0,
147
- 100 - (30 + security_score + (20 if ssl_days_left is not None else 0))]
148
- fig_score, ax_score = plt.subplots()
149
- ax_score.pie(sizes, labels=labels, autopct='%1.1f%%', startangle=140)
150
- ax_score.axis('equal')
151
- st.pyplot(fig_score)
152
-
153
- st.header("💡 اقتراحات للتحسين")
154
- suggestions = []
155
- if title == "لم يتم العثور على وسم العنوان":
156
- suggestions.append("- أضف وسم العنوان إلى صفحتك الرئيسية.")
157
- if meta_desc_content == "لم يتم العثور على ميتا الوصف":
158
- suggestions.append("- أضف ميتا الوصف إلى صفحتك لتحسين SEO.")
159
- if ssl_days_left is None:
160
- suggestions.append("- قم بتثبيت شهادة SSL لتأمين موقعك باستخدام HTTPS.")
161
- for header in security_headers:
162
- if header not in headers:
163
- suggestions.append(f"- أضف عنوان {header} ({security_headers[header]}) لتعزيز الأمان.")
164
-
165
- if suggestions:
166
- for suggestion in suggestions:
167
- st.write(suggestion)
168
- else:
169
- st.write("لا توجد اقتراحات. الموقع يبدو ممتازًا!")
170
-
171
- except Exception as e:
172
- st.error(f"حدث خطأ: {e}")
173
-
174
- if __name__ == "__main__":
175
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
  import requests
3
+ from bs4 import BeautifulSoup
4
+ import pandas as pd
5
+ import plotly.express as px
6
  import whois
 
7
  import ssl
8
+ import socket
9
+ import urllib3
10
  from datetime import datetime
11
+ import numpy as np
12
+ from urllib.parse import urlparse
13
  import matplotlib.pyplot as plt
14
+ import seaborn as sns
15
+ from requests.exceptions import RequestException
16
+ import json
17
+ from transformers import pipeline
18
+ import plotly.graph_objects as go
19
+
20
+ # تهيئة الصفحة
21
+ st.set_page_config(page_title="محلل المواقع الذكي", layout="wide", initial_sidebar_state="expanded")
22
+
23
+ # تصميم CSS
24
+ st.markdown("""
25
+ <style>
26
+ .main {
27
+ background-color: #f5f5f5;
28
+ }
29
+ .stButton>button {
30
+ background-color: #0066cc;
31
+ color: white;
32
+ border-radius: 5px;
33
+ padding: 10px 20px;
34
+ }
35
+ .metric-card {
36
+ background-color: white;
37
+ padding: 20px;
38
+ border-radius: 10px;
39
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
40
+ }
41
+ </style>
42
+ """, unsafe_allow_html=True)
43
+
44
+ # العنوان الرئيسي
45
+ st.title("🌐 محلل المواقع والسيو الذكي")
46
+ st.markdown("---")
47
+
48
+ # إدخال رابط الموقع
49
+ url = st.text_input("أدخل رابط الموقع للتحليل", "https://example.com")
50
+
51
+ if st.button("تحليل الموقع"):
52
+ try:
53
+ # التحقق من صحة الرابط
54
+ if not url.startswith(('http://', 'https://')):
55
+ url = 'https://' + url
56
+
57
+ # تحليل الأمان
58
+ def analyze_security(url):
59
+ try:
60
+ domain = urlparse(url).netloc
61
+ context = ssl.create_default_context()
62
+ with socket.create_connection((domain, 443)) as sock:
63
+ with context.wrap_socket(sock, server_hostname=domain) as ssock:
64
+ cert = ssock.getpeercert()
65
+ ssl_version = ssock.version()
66
+ return {
67
+ "ssl_version": ssl_version,
68
+ "cert_expiry": datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z'),
69
+ "secure": True
70
+ }
71
+ except Exception as e:
72
+ return {"secure": False, "error": str(e)}
73
+
74
+ # تحليل SEO
75
+ def analyze_seo(soup, url):
76
+ seo_data = {
77
+ "title": soup.title.string if soup.title else "لا يوجد عنوان",
78
+ "meta_description": soup.find("meta", {"name": "description"})["content"] if soup.find("meta", {"name": "description"}) else "لا يوجد وصف",
79
+ "h1_count": len(soup.find_all("h1")),
80
+ "h2_count": len(soup.find_all("h2")),
81
+ "images_without_alt": len([img for img in soup.find_all("img") if not img.get("alt")]),
82
+ "links_count": len(soup.find_all("a")),
83
+ }
84
+ return seo_data
85
+
86
+ # جلب البيانات وتحليلها
87
+ response = requests.get(url, verify=False)
88
+ soup = BeautifulSoup(response.text, 'html.parser')
89
+
90
+ # تحليل الأمان
91
+ security_info = analyze_security(url)
92
+
93
+ # تحليل SEO
94
+ seo_info = analyze_seo(soup, url)
95
+
96
+ # عرض النتائج في أقسام
97
+ col1, col2, col3 = st.columns(3)
98
+
99
+ with col1:
100
+ st.markdown("<div class='metric-card'>", unsafe_allow_html=True)
101
+ st.subheader("🔒 تحليل الأمان")
102
+ st.write(f"حالة SSL: {'آمن' if security_info['secure'] else 'غير آمن'}")
103
+ if security_info['secure']:
104
+ st.write(f"نسخة SSL: {security_info['ssl_version']}")
105
+ st.write(f"تاريخ انتهاء الشهادة: {security_info['cert_expiry'].strftime('%Y-%m-%d')}")
106
+ st.markdown("</div>", unsafe_allow_html=True)
107
+
108
+ with col2:
109
+ st.markdown("<div class='metric-card'>", unsafe_allow_html=True)
110
+ st.subheader("🎯 تحليل SEO")
111
+ st.write(f"العنوان: {seo_info['title']}")
112
+ st.write(f"عدد العناوين H1: {seo_info['h1_count']}")
113
+ st.write(f"عدد العناوين H2: {seo_info['h2_count']}")
114
+ st.write(f"عدد الروابط: {seo_info['links_count']}")
115
+ st.markdown("</div>", unsafe_allow_html=True)
116
+
117
+ with col3:
118
+ st.markdown("<div class='metric-card'>", unsafe_allow_html=True)
119
+ st.subheader("📊 التقييم العام")
120
+ # حساب التقييم العام
121
+ security_score = 100 if security_info['secure'] else 0
122
+ seo_score = min(100, (seo_info['h1_count'] * 10 +
123
+ seo_info['h2_count'] * 5 +
124
+ (seo_info['links_count'] > 0) * 20 +
125
+ (len(seo_info['title']) > 0) * 20))
126
+ total_score = (security_score + seo_score) / 2
127
+
128
+ # رسم مقياس دائري للتقييم
129
+ fig = go.Figure(go.Indicator(
130
+ mode = "gauge+number",
131
+ value = total_score,
132
+ domain = {'x': [0, 1], 'y': [0, 1]},
133
+ title = {'text': "التقييم العام"},
134
+ gauge = {
135
+ 'axis': {'range': [0, 100]},
136
+ 'bar': {'color': "darkblue"},
137
+ 'steps': [
138
+ {'range': [0, 50], 'color': "lightgray"},
139
+ {'range': [50, 75], 'color': "gray"},
140
+ {'range': [75, 100], 'color': "darkgray"}
141
+ ],
142
+ }))
143
+ st.plotly_chart(fig)
144
+ st.markdown("</div>", unsafe_allow_html=True)
145
+
146
+ # التوصيات والتحسينات
147
+ st.markdown("### 📝 التوصيات والتحسينات")
148
+ recommendations = []
149
+
150
+ if not security_info['secure']:
151
+ recommendations.append("🔒 يجب تفعيل شهادة SSL للموقع")
152
+ if seo_info['h1_count'] == 0:
153
+ recommendations.append("📌 يجب إضافة عنوان H1 للصفحة الرئيسية")
154
+ if len(seo_info['title']) < 30:
155
+ recommendations.append("📑 يجب تحسين عنوان الصفحة ليكون أكثر تفصيلاً")
156
+ if seo_info['images_without_alt'] > 0:
157
+ recommendations.append(f"🖼️ يجب إضافة نص بديل لـ {seo_info['images_without_alt']} صورة")
158
+
159
+ for rec in recommendations:
160
+ st.write(rec)
161
+
162
+ # رسم بياني للمقارنة
163
+ st.markdown("### 📊 تحليل مقارن")
164
+ comparison_data = {
165
+ 'المعيار': ['الأمان', 'SEO', 'التقييم العام'],
166
+ 'النتيجة': [security_score, seo_score, total_score]
167
+ }
168
+ df = pd.DataFrame(comparison_data)
169
+ fig = px.bar(df, x='المعيار', y='النتيجة',
170
+ title='مقارنة نتائج التحليل',
171
+ color='النتيجة',
172
+ color_continuous_scale='Viridis')
173
+ st.plotly_chart(fig)
174
+
175
+ except Exception as e:
176
+ st.error(f"حدث خطأ أثناء تحليل الموقع: {str(e)}")
177
+
178
+ # إضافة معلومات إضافية في الشريط الجانبي
179
+ with st.sidebar:
180
+ st.header("ℹ️ معلومات إضافية")
181
+ st.write("""
182
+ هذا التطبيق يقوم بتحليل:
183
+ - 🔒 أمان الموقع وشهادات SSL
184
+ - 📊 تحليل SEO
185
+ - 📈 تقييم أداء الموقع
186
+ - 🎯 تقديم توصيات للتحسين
187
+ """)
188
+
189
+ st.markdown("---")
190
+ st.markdown("### 📚 مصادر مفيدة")
191
+ st.markdown("""
192
+ - [دليل SEO](https://developers.google.com/search/docs)
193
+ - [أفضل ممارسات الأمان](https://www.cloudflare.com/learning/security/what-is-web-security/)
194
+ """)
195
+
196
+ # Created/Modified files during execution:
197
+ # No files are created or modified during execution as this is a Streamlit web application