joermd commited on
Commit
5c78dbd
·
verified ·
1 Parent(s): 51463b5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +199 -1
app.py CHANGED
@@ -298,6 +298,21 @@ class WebsiteAnalyzer:
298
  response = requests.get(url)
299
  headers = response.headers
300
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  security_headers = {
302
  'Strict-Transport-Security': 'HSTS',
303
  'Content-Security-Policy': 'CSP',
@@ -509,4 +524,187 @@ class WebsiteAnalyzer:
509
  return "موثوقية متوسطة ⚠️"
510
  else:
511
  return "موثوقية منخفضة ⛔"
512
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  response = requests.get(url)
299
  headers = response.headers
300
 
301
+ security_headers = {
302
+ 'Strict-Transport-Security': 'HSTS',
303
+ 'Content-Security-Policy': 'CSP',
304
+ 'X-Frame-Options': 'X-Frame',
305
+ 'X-Content-Type-Options': 'X-Content-Type',
306
+ 'X-XSS-Protection': 'XSS Protection'
307
+ }
308
+
309
+ results = {}
310
+ for header, name in security_headers.items
311
+ def _check_security_headers(self, url):
312
+ try:
313
+ response = requests.get(url)
314
+ headers = response.headers
315
+
316
  security_headers = {
317
  'Strict-Transport-Security': 'HSTS',
318
  'Content-Security-Policy': 'CSP',
 
524
  return "موثوقية متوسطة ⚠️"
525
  else:
526
  return "موثوقية منخفضة ⛔"
527
+ def _analyze_seo(self, url):
528
+ try:
529
+ response = requests.get(url)
530
+ soup = BeautifulSoup(response.text, 'html.parser')
531
+
532
+ results = {
533
+ "العناصر الأساسية": {},
534
+ "الوسوم الوصفية": {},
535
+ "توصيات": [],
536
+ "درجة SEO": 100
537
+ }
538
+
539
+ # فحص العنوان
540
+ title = soup.find('title')
541
+ if title and title.text.strip():
542
+ title_length = len(title.text.strip())
543
+ results["العناصر الأساسية"]["العنوان"] = {
544
+ "القيمة": title.text.strip(),
545
+ "الطول": title_length,
546
+ "التقييم": "✅" if 30 <= title_length <= 60 else "⚠️"
547
+ }
548
+ if title_length < 30 or title_length > 60:
549
+ results["توصيات"].append("تعديل طول العنوان ليكون بين 30-60 حرف")
550
+ results["درجة SEO"] -= 10
551
+ else:
552
+ results["العناصر الأساسية"]["العنوان"] = {"القيمة": "غير موجود", "التقييم": "❌"}
553
+ results["توصيات"].append("إضافة عنوان للصفحة")
554
+ results["درجة SEO"] -= 20
555
+
556
+ # فحص الوصف
557
+ meta_desc = soup.find('meta', attrs={'name': 'description'})
558
+ if meta_desc and meta_desc.get('content', '').strip():
559
+ desc_length = len(meta_desc['content'].strip())
560
+ results["الوسوم الوصفية"]["الوصف"] = {
561
+ "القيمة": meta_desc['content'].strip(),
562
+ "الطول": desc_length,
563
+ "التقييم": "✅" if 120 <= desc_length <= 160 else "⚠️"
564
+ }
565
+ if desc_length < 120 or desc_length > 160:
566
+ results["توصيات"].append("تعديل طول الوصف ليكون بين 120-160 حرف")
567
+ results["درجة SEO"] -= 10
568
+ else:
569
+ results["الوسوم الوصفية"]["الوصف"] = {"القيمة": "غير موجود", "التقييم": "❌"}
570
+ results["توصيات"].append("إضافة وصف للصفحة")
571
+ results["درجة SEO"] -= 15
572
+
573
+ # فحص الكلمات المفتاحية
574
+ keywords = soup.find('meta', attrs={'name': 'keywords'})
575
+ results["الوسوم الوصفية"]["الكلمات المفتاحية"] = {
576
+ "القيمة": keywords['content'].strip() if keywords else "غير موجود",
577
+ "التقييم": "✅" if keywords else "ℹ️"
578
+ }
579
+
580
+ # فحص العناوين الفرعية
581
+ headings = {f"h{i}": len(soup.find_all(f'h{i}')) for i in range(1, 7)}
582
+ results["العناصر الأساسية"]["العناوين الفرعية"] = headings
583
+ if not headings.get('h1'):
584
+ results["توصيات"].append("إضافة عنوان رئيسي H1")
585
+ results["درجة SEO"] -= 15
586
+ elif headings.get('h1') > 1:
587
+ results["توصيات"].append("يجب أن يكون هناك عنوان H1 واحد فقط")
588
+ results["درجة SEO"] -= 10
589
+
590
+ # فحص الصور
591
+ images = soup.find_all('img')
592
+ missing_alt = sum(1 for img in images if not img.get('alt'))
593
+ results["العناصر الأساسية"]["الصور"] = {
594
+ "العدد الإجمالي": len(images),
595
+ "بدون نص بديل": missing_alt
596
+ }
597
+ if missing_alt:
598
+ results["توصيات"].append(f"إضافة نص بديل لـ {missing_alt} صورة")
599
+ results["درجة SEO"] -= min(15, missing_alt * 2)
600
+
601
+ # تقييم عام
602
+ results["التقييم العام"] = self._get_seo_level(results["درجة SEO"])
603
+
604
+ return results
605
+ except Exception as e:
606
+ return {"error": f"خطأ في تحليل SEO: {str(e)}"}
607
+
608
+ def _get_seo_level(self, score):
609
+ if score >= 90:
610
+ return "ممتاز 🌟"
611
+ elif score >= 70:
612
+ return "جيد ✅"
613
+ elif score >= 50:
614
+ return "متوسط ⚠️"
615
+ else:
616
+ return "ضعيف ⛔"
617
+
618
+ def _analyze_performance(self, url):
619
+ try:
620
+ start_time = time.time()
621
+ response = requests.get(url)
622
+ load_time = time.time() - start_time
623
+
624
+ results = {
625
+ "مقاييس الأداء": {},
626
+ "تحليل المحتوى": {},
627
+ "توصيات": [],
628
+ "درجة الأداء": 100
629
+ }
630
+
631
+ # قياس زمن التحميل
632
+ results["مقاييس الأداء"]["زمن التحميل"] = {
633
+ "القيمة": f"{load_time:.2f} ثانية",
634
+ "التقييم": "✅" if load_time < 2 else "⚠️" if load_time < 4 else "❌"
635
+ }
636
+ if load_time >= 2:
637
+ results["توصيات"].append("تحسين زمن تحميل الصفحة")
638
+ results["درجة الأداء"] -= min(30, int(load_time * 10))
639
+
640
+ # تحليل حجم الصفحة
641
+ page_size = len(response.content) / 1024 # تحويل إلى كيلوبايت
642
+ results["مقاييس الأداء"]["حجم الصفحة"] = {
643
+ "القيمة": f"{page_size:.2f} KB",
644
+ "التقييم": "✅" if page_size < 500 else "⚠️" if page_size < 1000 else "❌"
645
+ }
646
+ if page_size >= 500:
647
+ results["توصيات"].append("تقليل حجم الصفحة")
648
+ results["درجة الأداء"] -= min(20, int(page_size/100))
649
+
650
+ # تحليل المحتوى
651
+ soup = BeautifulSoup(response.text, 'html.parser')
652
+
653
+ # عدد ملفات JavaScript
654
+ scripts = soup.find_all('script')
655
+ results["تحليل المحتوى"]["ملفات JavaScript"] = {
656
+ "العدد": len(scripts),
657
+ "التقييم": "✅" if len(scripts) < 10 else "⚠️" if len(scripts) < 15 else "❌"
658
+ }
659
+ if len(scripts) >= 10:
660
+ results["توصيات"].append("تقليل عدد ملفات JavaScript")
661
+ results["درجة الأداء"] -= min(15, len(scripts))
662
+
663
+ # عدد ملفات CSS
664
+ css_files = soup.find_all('link', rel='stylesheet')
665
+ results["تحليل المحتوى"]["ملفات CSS"] = {
666
+ "العدد": len(css_files),
667
+ "التقييم": "✅" if len(css_files) < 5 else "⚠️" if len(css_files) < 8 else "❌"
668
+ }
669
+ if len(css_files) >= 5:
670
+ results["توصيات"].append("تقليل عدد ملفات CSS")
671
+ results["درجة الأداء"] -= min(10, len(css_files) * 2)
672
+
673
+ # عدد الصور وحجمها
674
+ images = soup.find_all('img')
675
+ total_images_size = 0
676
+ for img in images:
677
+ if img.get('src'):
678
+ try:
679
+ img_response = requests.head(urljoin(url, img['src']))
680
+ total_images_size += int(img_response.headers.get('content-length', 0))
681
+ except:
682
+ continue
683
+
684
+ total_images_size_kb = total_images_size / 1024
685
+ results["تحليل المحتوى"]["الصور"] = {
686
+ "العدد": len(images),
687
+ "الحجم الإجمالي": f"{total_images_size_kb:.2f} KB",
688
+ "التقييم": "✅" if total_images_size_kb < 1000 else "⚠️" if total_images_size_kb < 2000 else "❌"
689
+ }
690
+
691
+ if total_images_size_kb >= 1000:
692
+ results["توصيات"].append("ضغط الصور وتحسين حجمها")
693
+ results["درجة الأداء"] -= min(15, int(total_images_size_kb/200))
694
+
695
+ # تقييم عام
696
+ results["التقييم العام"] = self._get_performance_level(results["درجة الأداء"])
697
+
698
+ return results
699
+ except Exception as e:
700
+ return {"error": f"خطأ في تحليل الأداء: {str(e)}"}
701
+
702
+ def _get_performance_level(self, score):
703
+ if score >= 90:
704
+ return "أداء ممتاز 🚀"
705
+ elif score >= 70:
706
+ return "أداء جيد ✅"
707
+ elif score >= 50:
708
+ return "أداء متوسط ⚠️"
709
+ else:
710
+ return "أداء ضعيف ⛔"