|
import streamlit as st |
|
from streamlit_lottie import st_lottie |
|
from streamlit_option_menu import option_menu |
|
import requests |
|
import pandas as pd |
|
import plotly.express as px |
|
import plotly.graph_objects as go |
|
from datetime import datetime |
|
import httpx |
|
import asyncio |
|
import aiohttp |
|
from bs4 import BeautifulSoup |
|
import whois |
|
import ssl |
|
import socket |
|
import dns.resolver |
|
from urllib.parse import urlparse |
|
import json |
|
import numpy as np |
|
from selenium import webdriver |
|
from selenium.webdriver.chrome.options import Options |
|
from webdriver_manager.chrome import ChromeDriverManager |
|
from PIL import Image |
|
import io |
|
import time |
|
|
|
|
|
st.set_page_config(layout="wide", page_title="محلل المواقع المتقدم") |
|
|
|
|
|
def load_lottieurl(url): |
|
r = requests.get(url) |
|
if r.status_code != 200: |
|
return None |
|
return r.json() |
|
|
|
lottie_analyzing = load_lottieurl("https://assets5.lottiefiles.com/packages/lf20_qpwbqki6.json") |
|
|
|
|
|
st.markdown(""" |
|
<style> |
|
.main { |
|
background-color: #f0f2f6; |
|
} |
|
.stButton>button { |
|
color: white; |
|
background-color: #ff4b4b; |
|
border-radius: 10px; |
|
padding: 15px 25px; |
|
border: none; |
|
} |
|
.stButton>button:hover { |
|
background-color: #ff6b6b; |
|
border: none; |
|
} |
|
.metric-card { |
|
background-color: white; |
|
border-radius: 10px; |
|
padding: 20px; |
|
box-shadow: 0 4px 6px rgba(0,0,0,0.1); |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
|
|
class WebsiteAnalyzer: |
|
def __init__(self): |
|
self.headers = { |
|
'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' |
|
} |
|
|
|
async def analyze_performance(self, url): |
|
try: |
|
start_time = time.time() |
|
async with httpx.AsyncClient() as client: |
|
response = await client.get(url) |
|
load_time = time.time() - start_time |
|
page_size = len(response.content) / 1024 |
|
|
|
return { |
|
"load_time": round(load_time, 2), |
|
"page_size": round(page_size, 2), |
|
"status_code": response.status_code |
|
} |
|
except Exception as e: |
|
return {"error": str(e)} |
|
|
|
async def analyze_seo(self, url): |
|
try: |
|
async with httpx.AsyncClient() as client: |
|
response = await client.get(url) |
|
soup = BeautifulSoup(response.text, 'html.parser') |
|
|
|
|
|
headings = { |
|
'h1': len(soup.find_all('h1')), |
|
'h2': len(soup.find_all('h2')), |
|
'h3': len(soup.find_all('h3')) |
|
} |
|
|
|
|
|
links = soup.find_all('a') |
|
internal_links = len([link for link in links if urlparse(link.get('href', '')).netloc == urlparse(url).netloc]) |
|
external_links = len(links) - internal_links |
|
|
|
|
|
images = soup.find_all('img') |
|
images_without_alt = len([img for img in images if not img.get('alt')]) |
|
|
|
return { |
|
"title": soup.title.string if soup.title else "لا يوجد عنوان", |
|
"meta_description": soup.find("meta", {"name": "description"}).get("content") if soup.find("meta", {"name": "description"}) else "لا يوجد وصف", |
|
"headings": headings, |
|
"internal_links": internal_links, |
|
"external_links": external_links, |
|
"images_without_alt": images_without_alt |
|
} |
|
except Exception as e: |
|
return {"error": str(e)} |
|
|
|
def analyze_security(self, url): |
|
try: |
|
domain = urlparse(url).netloc |
|
|
|
|
|
ctx = ssl.create_default_context() |
|
with ctx.wrap_socket(socket.socket(), server_hostname=domain) as s: |
|
s.connect((domain, 443)) |
|
cert = s.getpeercert() |
|
|
|
|
|
dns_records = { |
|
'A': [str(r) for r in dns.resolver.resolve(domain, 'A')], |
|
'MX': [str(r) for r in dns.resolver.resolve(domain, 'MX')], |
|
'TXT': [str(r) for r in dns.resolver.resolve(domain, 'TXT')] |
|
} |
|
|
|
|
|
domain_info = whois.whois(domain) |
|
|
|
return { |
|
"ssl_valid": True, |
|
"ssl_expiry": cert['notAfter'], |
|
"dns_records": dns_records, |
|
"domain_info": { |
|
"registrar": domain_info.registrar, |
|
"creation_date": domain_info.creation_date, |
|
"expiration_date": domain_info.expiration_date |
|
} |
|
} |
|
except Exception as e: |
|
return {"error": str(e)} |
|
|
|
async def take_screenshot(self, url): |
|
try: |
|
chrome_options = Options() |
|
chrome_options.add_argument('--headless') |
|
chrome_options.add_argument('--no-sandbox') |
|
chrome_options.add_argument('--disable-dev-shm-usage') |
|
|
|
driver = webdriver.Chrome(ChromeDriverManager().install(), options=chrome_options) |
|
driver.get(url) |
|
driver.set_window_size(1920, 1080) |
|
|
|
screenshot = driver.get_screenshot_as_png() |
|
driver.quit() |
|
|
|
return Image.open(io.BytesIO(screenshot)) |
|
except Exception as e: |
|
return None |
|
|
|
def main(): |
|
st.title("🔍 محلل المواقع المتقدم") |
|
|
|
|
|
with st.sidebar: |
|
selected = option_menu( |
|
menu_title="القائمة الرئيسية", |
|
options=["تحليل جديد", "التقارير السابقة", "الإعدادات"], |
|
icons=["search", "file-text", "gear"], |
|
menu_icon="cast", |
|
default_index=0, |
|
) |
|
|
|
if selected == "تحليل جديد": |
|
col1, col2 = st.columns([2, 1]) |
|
|
|
with col1: |
|
url = st.text_input("أدخل رابط الموقع", "https://example.com") |
|
if st.button("بدء التحليل"): |
|
with st.spinner("جاري التحليل..."): |
|
st_lottie(lottie_analyzing, height=200) |
|
|
|
analyzer = WebsiteAnalyzer() |
|
|
|
|
|
loop = asyncio.new_event_loop() |
|
asyncio.set_event_loop(loop) |
|
performance_data = loop.run_until_complete(analyzer.analyze_performance(url)) |
|
seo_data = loop.run_until_complete(analyzer.analyze_seo(url)) |
|
security_data = analyzer.analyze_security(url) |
|
screenshot = loop.run_until_complete(analyzer.take_screenshot(url)) |
|
|
|
|
|
st.success("تم اكتمال التحليل!") |
|
|
|
|
|
cols = st.columns(3) |
|
with cols[0]: |
|
st.metric("زمن التحميل", f"{performance_data['load_time']}s") |
|
with cols[1]: |
|
st.metric("حجم الصفحة", f"{performance_data['page_size']} KB") |
|
with cols[2]: |
|
st.metric("الروابط الداخلية", seo_data['internal_links']) |
|
|
|
|
|
with st.expander("تحليل SEO", expanded=True): |
|
st.json(seo_data) |
|
|
|
|
|
fig = px.bar( |
|
x=list(seo_data['headings'].keys()), |
|
y=list(seo_data['headings'].values()), |
|
title="توزيع العناوين", |
|
labels={'x': 'نوع العنوان', 'y': 'العدد'} |
|
) |
|
st.plotly_chart(fig) |
|
|
|
|
|
with st.expander("تحليل الأمان", expanded=True): |
|
st.json(security_data) |
|
|
|
|
|
if screenshot: |
|
st.image(screenshot, caption="لقطة شاشة للموقع", use_column_width=True) |
|
|
|
with col2: |
|
st.subheader("آخر التحليلات") |
|
|
|
|
|
elif selected == "التقارير السابقة": |
|
st.subheader("التقارير السابقة") |
|
|
|
|
|
elif selected == "الإعدادات": |
|
st.subheader("إعدادات التحليل") |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |
|
|