joermd commited on
Commit
a3acd70
·
verified ·
1 Parent(s): da60d2c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +236 -198
app.py CHANGED
@@ -1,212 +1,250 @@
1
- import socket
 
 
2
  import requests
3
- from urllib.parse import urlparse
 
 
 
 
 
 
4
  from bs4 import BeautifulSoup
5
- import streamlit as st
6
- import matplotlib.pyplot as plt
7
- from reportlab.lib.pagesizes import letter
8
- from reportlab.pdfgen import canvas
9
- import geoip2.database
10
-
11
- def analyze_ip_free(url):
12
- """
13
- Analyze IP address and geolocation of a given URL
14
- Uses GeoLite2 database to retrieve location information
15
-
16
- Args:
17
- url (str): Website URL to analyze
18
-
19
- Returns:
20
- dict: IP and location details or error information
21
- """
22
- try:
23
- domain = urlparse(url).netloc
24
- ip = socket.gethostbyname(domain)
25
- with geoip2.database.Reader('GeoLite2-City.mmdb') as reader:
26
- response = reader.city(ip)
27
- return {
28
- "ip": ip,
29
- "city": response.city.name or "Unknown",
30
- "region": response.subdivisions.most_specific.name or "Unknown",
31
- "country": response.country.name or "Unknown",
32
- "latitude": response.location.latitude or "Unknown",
33
- "longitude": response.location.longitude or "Unknown",
34
- }
35
- except Exception as e:
36
- return {"error": str(e)}
37
-
38
- def analyze_uptime_free(url):
39
- """
40
- Check website availability and response status
41
-
42
- Args:
43
- url (str): Website URL to check
44
-
45
- Returns:
46
- dict: Uptime status and status code
47
- """
48
- try:
49
- response = requests.get(url, timeout=5)
50
- return {
51
- "status": "Up" if response.status_code == 200 else "Down",
52
- "status_code": response.status_code,
53
- }
54
- except requests.exceptions.RequestException as e:
55
- return {"status": "Down", "error": str(e)}
56
-
57
- def analyze_seo_free(url):
58
- """
59
- Extract basic SEO information from the website
60
-
61
- Args:
62
- url (str): Website URL to analyze
63
-
64
- Returns:
65
- dict: SEO-related metadata
66
- """
67
- try:
68
- response = requests.get(url)
69
- soup = BeautifulSoup(response.text, 'html.parser')
70
- title = soup.title.string if soup.title else "No Title"
71
- meta_description = soup.find("meta", attrs={"name": "description"})
72
- keywords = soup.find("meta", attrs={"name": "keywords"})
73
-
74
- return {
75
- "title": title,
76
- "meta_description": meta_description["content"] if meta_description else "No Description",
77
- "keywords": keywords["content"] if keywords else "No Keywords",
78
- }
79
- except Exception as e:
80
- return {"error": str(e)}
81
-
82
- def analyze_carbon_free(url):
83
- """
84
- Estimate website's carbon footprint based on page size
85
-
86
- Args:
87
- url (str): Website URL to analyze
88
-
89
- Returns:
90
- dict: Page size and estimated CO2 emissions
91
- """
92
- try:
93
- response = requests.get(url)
94
- page_size = len(response.content) / 1024 # in kilobytes
95
- co2_estimation = page_size * 0.02 # rough CO2 emission estimate
96
- return {
97
- "page_size_kb": round(page_size, 2),
98
- "estimated_co2_g": round(co2_estimation, 2),
99
- }
100
- except Exception as e:
101
- return {"error": str(e)}
102
-
103
- def draw_bar_chart(data, title, xlabel, ylabel):
104
- """
105
- Create a bar chart visualization
106
-
107
- Args:
108
- data (dict): Data to visualize
109
- title (str): Chart title
110
- xlabel (str): X-axis label
111
- ylabel (str): Y-axis label
112
- """
113
- keys, values = list(data.keys()), list(data.values())
114
- plt.figure(figsize=(8, 5))
115
- plt.bar(keys, values, color='skyblue')
116
- plt.title(title)
117
- plt.xlabel(xlabel)
118
- plt.ylabel(ylabel)
119
- plt.tight_layout()
120
- plt.savefig('chart.png')
121
- plt.show()
122
 
123
- def export_to_pdf_free(results, file_path):
124
- """
125
- Export analysis results to a PDF report
126
-
127
- Args:
128
- results (dict): Analysis results
129
- file_path (str): Path to save PDF
130
- """
131
- c = canvas.Canvas(file_path, pagesize=letter)
132
- c.drawString(30, 750, "Website Analysis Report")
133
- c.drawString(30, 730, "=" * 50)
134
- y = 700
135
- for section, content in results.items():
136
- c.drawString(30, y, f"{section}:")
137
- y -= 20
138
- for key, value in content.items():
139
- c.drawString(50, y, f"- {key}: {value}")
140
- y -= 20
141
- y -= 20
142
- c.save()
143
 
144
- def main():
145
- """
146
- Main Streamlit application for website analysis
147
- """
148
- st.title("أداة تحليل المواقع")
149
- st.write("تحليل شامل للمواقع باستخدام أدوات مجانية")
150
 
151
- # URL input
152
- url = st.text_input("أدخل رابط الموقع:", "https://example.com")
153
 
154
- if url:
155
- # IP Analysis
156
- st.subheader("1. تحليل عنوان IP والموقع الجغرافي")
157
- ip_data = analyze_ip_free(url)
158
- if "error" in ip_data:
159
- st.error(ip_data["error"])
160
- else:
161
- st.json(ip_data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
- # Uptime Analysis
164
- st.subheader("2. تحليل توافر الموقع")
165
- uptime_data = analyze_uptime_free(url)
166
- if "error" in uptime_data:
167
- st.error(uptime_data["error"])
168
- else:
169
- st.json(uptime_data)
170
 
171
- # SEO Analysis
172
- st.subheader("3. تحليل تحسين محركات البحث (SEO)")
173
- seo_data = analyze_seo_free(url)
174
- if "error" in seo_data:
175
- st.error(seo_data["error"])
176
- else:
177
- st.json(seo_data)
 
 
 
 
 
 
 
 
178
 
179
- # Carbon Analysis
180
- st.subheader("4. تحليل الأثر البيئي")
181
- carbon_data = analyze_carbon_free(url)
182
- if "error" in carbon_data:
183
- st.error(carbon_data["error"])
184
- else:
185
- st.json(carbon_data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
 
187
- # Carbon Analysis Chart
188
- st.subheader("رسم بياني لتحليل الأثر البيئي")
189
- co2_data = {
190
- "Page Size (KB)": carbon_data["page_size_kb"],
191
- "CO2 Emission (g)": carbon_data["estimated_co2_g"]
 
 
 
 
 
 
 
 
 
 
192
  }
193
- draw_bar_chart(co2_data, "Carbon Analysis", "Category", "Value")
194
- st.image("chart.png")
195
-
196
- # PDF Export
197
- st.subheader("5. تصدير التقرير إلى PDF")
198
- if st.button("تصدير التقرير"):
199
- results = {
200
- "IP Analysis": ip_data,
201
- "Uptime Analysis": uptime_data,
202
- "SEO Analysis": seo_data,
203
- "Carbon Analysis": carbon_data,
 
 
204
  }
205
- file_path = "website_analysis_report.pdf"
206
- export_to_pdf_free(results, file_path)
207
- st.success(f"تم تصدير التقرير إلى {file_path}")
208
- with open(file_path, "rb") as pdf_file:
209
- st.download_button("تحميل التقرير", data=pdf_file, file_name="website_analysis_report.pdf")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
  if __name__ == "__main__":
212
- main()
 
 
1
+ import streamlit as st
2
+ from streamlit_lottie import st_lottie
3
+ 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 json
19
+ import numpy as np
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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
+ # تخصيص المظهر
28
+ st.set_page_config(layout="wide", page_title="محلل المواقع المتقدم")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
+ # تحميل الأنيميشن
31
+ def load_lottieurl(url):
32
+ r = requests.get(url)
33
+ if r.status_code != 200:
34
+ return None
35
+ return r.json()
36
 
37
+ lottie_analyzing = load_lottieurl("https://assets5.lottiefiles.com/packages/lf20_qpwbqki6.json")
 
38
 
39
+ # تصميم CSS مخصص
40
+ st.markdown("""
41
+ <style>
42
+ .main {
43
+ background-color: #f0f2f6;
44
+ }
45
+ .stButton>button {
46
+ color: white;
47
+ background-color: #ff4b4b;
48
+ border-radius: 10px;
49
+ padding: 15px 25px;
50
+ border: none;
51
+ }
52
+ .stButton>button:hover {
53
+ background-color: #ff6b6b;
54
+ border: none;
55
+ }
56
+ .metric-card {
57
+ background-color: white;
58
+ border-radius: 10px;
59
+ padding: 20px;
60
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
61
+ }
62
+ </style>
63
+ """, unsafe_allow_html=True)
64
 
65
+ class WebsiteAnalyzer:
66
+ def __init__(self):
67
+ self.headers = {
68
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
69
+ }
 
 
70
 
71
+ async def analyze_performance(self, url):
72
+ try:
73
+ start_time = time.time()
74
+ async with httpx.AsyncClient() as client:
75
+ response = await client.get(url)
76
+ load_time = time.time() - start_time
77
+ page_size = len(response.content) / 1024 # KB
78
+
79
+ return {
80
+ "load_time": round(load_time, 2),
81
+ "page_size": round(page_size, 2),
82
+ "status_code": response.status_code
83
+ }
84
+ except Exception as e:
85
+ return {"error": str(e)}
86
 
87
+ async def analyze_seo(self, url):
88
+ try:
89
+ async with httpx.AsyncClient() as client:
90
+ response = await client.get(url)
91
+ soup = BeautifulSoup(response.text, 'html.parser')
92
+
93
+ # تحليل العناوين
94
+ headings = {
95
+ 'h1': len(soup.find_all('h1')),
96
+ 'h2': len(soup.find_all('h2')),
97
+ 'h3': len(soup.find_all('h3'))
98
+ }
99
+
100
+ # تحليل الروابط
101
+ links = soup.find_all('a')
102
+ internal_links = len([link for link in links if urlparse(link.get('href', '')).netloc == urlparse(url).netloc])
103
+ external_links = len(links) - internal_links
104
+
105
+ # تحليل الصور
106
+ images = soup.find_all('img')
107
+ images_without_alt = len([img for img in images if not img.get('alt')])
108
+
109
+ return {
110
+ "title": soup.title.string if soup.title else "لا يوجد عنوان",
111
+ "meta_description": soup.find("meta", {"name": "description"}).get("content") if soup.find("meta", {"name": "description"}) else "لا يوجد وصف",
112
+ "headings": headings,
113
+ "internal_links": internal_links,
114
+ "external_links": external_links,
115
+ "images_without_alt": images_without_alt
116
+ }
117
+ except Exception as e:
118
+ return {"error": str(e)}
119
 
120
+ def analyze_security(self, url):
121
+ try:
122
+ domain = urlparse(url).netloc
123
+
124
+ # فحص SSL
125
+ ctx = ssl.create_default_context()
126
+ with ctx.wrap_socket(socket.socket(), server_hostname=domain) as s:
127
+ s.connect((domain, 443))
128
+ cert = s.getpeercert()
129
+
130
+ # فحص DNS
131
+ dns_records = {
132
+ 'A': [str(r) for r in dns.resolver.resolve(domain, 'A')],
133
+ 'MX': [str(r) for r in dns.resolver.resolve(domain, 'MX')],
134
+ 'TXT': [str(r) for r in dns.resolver.resolve(domain, 'TXT')]
135
  }
136
+
137
+ # معلومات WHOIS
138
+ domain_info = whois.whois(domain)
139
+
140
+ return {
141
+ "ssl_valid": True,
142
+ "ssl_expiry": cert['notAfter'],
143
+ "dns_records": dns_records,
144
+ "domain_info": {
145
+ "registrar": domain_info.registrar,
146
+ "creation_date": domain_info.creation_date,
147
+ "expiration_date": domain_info.expiration_date
148
+ }
149
  }
150
+ except Exception as e:
151
+ return {"error": str(e)}
152
+
153
+ async def take_screenshot(self, url):
154
+ try:
155
+ chrome_options = Options()
156
+ chrome_options.add_argument('--headless')
157
+ chrome_options.add_argument('--no-sandbox')
158
+ chrome_options.add_argument('--disable-dev-shm-usage')
159
+
160
+ driver = webdriver.Chrome(ChromeDriverManager().install(), options=chrome_options)
161
+ driver.get(url)
162
+ driver.set_window_size(1920, 1080)
163
+
164
+ screenshot = driver.get_screenshot_as_png()
165
+ driver.quit()
166
+
167
+ return Image.open(io.BytesIO(screenshot))
168
+ except Exception as e:
169
+ return None
170
+
171
+ def main():
172
+ st.title("🔍 محلل المواقع المتقدم")
173
+
174
+ # إضافة قائمة جانبية
175
+ with st.sidebar:
176
+ selected = option_menu(
177
+ menu_title="القائمة الرئيسية",
178
+ options=["تحليل جديد", "التقارير السابقة", "الإعدادات"],
179
+ icons=["search", "file-text", "gear"],
180
+ menu_icon="cast",
181
+ default_index=0,
182
+ )
183
+
184
+ if selected == "تحليل جديد":
185
+ col1, col2 = st.columns([2, 1])
186
+
187
+ with col1:
188
+ url = st.text_input("أدخل رابط الموقع", "https://example.com")
189
+ if st.button("بدء التحليل"):
190
+ with st.spinner("جاري التحليل..."):
191
+ st_lottie(lottie_analyzing, height=200)
192
+
193
+ analyzer = WebsiteAnalyzer()
194
+
195
+ # تحليل متزامن
196
+ loop = asyncio.new_event_loop()
197
+ asyncio.set_event_loop(loop)
198
+ performance_data = loop.run_until_complete(analyzer.analyze_performance(url))
199
+ seo_data = loop.run_until_complete(analyzer.analyze_seo(url))
200
+ security_data = analyzer.analyze_security(url)
201
+ screenshot = loop.run_until_complete(analyzer.take_screenshot(url))
202
+
203
+ # عرض النتائج
204
+ st.success("تم اكتمال التحليل!")
205
+
206
+ # عرض البطاقات الإحصائية
207
+ cols = st.columns(3)
208
+ with cols[0]:
209
+ st.metric("زمن التحميل", f"{performance_data['load_time']}s")
210
+ with cols[1]:
211
+ st.metric("حجم الصفحة", f"{performance_data['page_size']} KB")
212
+ with cols[2]:
213
+ st.metric("الروابط الداخلية", seo_data['internal_links'])
214
+
215
+ # عرض تحليل SEO
216
+ with st.expander("تحليل SEO", expanded=True):
217
+ st.json(seo_data)
218
+
219
+ # رسم بياني للعناوين
220
+ fig = px.bar(
221
+ x=list(seo_data['headings'].keys()),
222
+ y=list(seo_data['headings'].values()),
223
+ title="توزيع العناوين",
224
+ labels={'x': 'نوع العنوان', 'y': 'العدد'}
225
+ )
226
+ st.plotly_chart(fig)
227
+
228
+ # عرض تحليل الأمان
229
+ with st.expander("تحليل الأمان", expanded=True):
230
+ st.json(security_data)
231
+
232
+ # عرض لقطة الشاشة
233
+ if screenshot:
234
+ st.image(screenshot, caption="لقطة شاشة للموقع", use_column_width=True)
235
+
236
+ with col2:
237
+ st.subheader("آخر التحليلات")
238
+ # هنا يمكن إضافة قائمة بآخر المواقع التي تم تحليلها
239
+
240
+ elif selected == "التقارير السابقة":
241
+ st.subheader("التقارير السابقة")
242
+ # هنا يمكن إضافة عرض للتقارير السابقة
243
+
244
+ elif selected == "الإعدادات":
245
+ st.subheader("إعدادات التحليل")
246
+ # هنا يمكن إضافة إعدادات التحليل
247
 
248
  if __name__ == "__main__":
249
+ main()
250
+