joermd commited on
Commit
51463b5
·
verified ·
1 Parent(s): 59844ed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +1 -413
app.py CHANGED
@@ -509,416 +509,4 @@ class WebsiteAnalyzer:
509
  return "موثوقية متوسطة ⚠️"
510
  else:
511
  return "موثوقية منخفضة ⛔"
512
- def _analyze_description(self, description):
513
- if not description:
514
- return {
515
- 'score': "0/10",
516
- 'recommendations': ["يجب إضافة وصف للصفحة"]
517
- }
518
-
519
- score = 10
520
- recommendations = []
521
-
522
- if len(description) < 120:
523
- score -= 2
524
- recommendations.append("الوصف قصير جداً، يُفضل أن يكون بين 120-155 حرفاً")
525
- elif len(description) > 155:
526
- score -= 2
527
- recommendations.append("الوصف طويل جداً، يجب تقصيره إلى 155 حرفاً كحد أقصى")
528
-
529
- if not any(char in description.lower() for char in ['ما', 'كيف', 'لماذا', 'متى', 'أين']):
530
- score -= 1
531
- recommendations.append("أضف كلمات استفهامية لجذب المزيد من النقرات")
532
-
533
- return {
534
- 'score': f"{score}/10",
535
- 'recommendations': recommendations
536
- }
537
-
538
- def _extract_keywords(self, soup):
539
- # استخراج النص من العناصر المهمة
540
- text_elements = []
541
- for tag in ['h1', 'h2', 'h3', 'p', 'li']:
542
- elements = soup.find_all(tag)
543
- for element in elements:
544
- text_elements.append(element.get_text())
545
-
546
- # تنظيف النص
547
- text = ' '.join(text_elements)
548
- words = re.findall(r'\b\w+\b', text.lower())
549
-
550
- # حذف الكلمات الشائعة
551
- stop_words = set(['في', 'من', 'على', 'إلى', 'عن', 'مع', 'هذا', 'هذه', 'تلك', 'ذلك'])
552
- words = [word for word in words if word not in stop_words and len(word) > 2]
553
-
554
- # حساب تكرار الكلمات
555
- word_freq = {}
556
- for word in words:
557
- word_freq[word] = word_freq.get(word, 0) + 1
558
-
559
- # ترتيب الكلمات حسب التكرار
560
- sorted_keywords = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)
561
- return [word for word, freq in sorted_keywords[:10]]
562
-
563
- def _analyze_links(self, soup, base_url):
564
- internal_links = []
565
- external_links = []
566
- base_domain = urlparse(base_url).netloc
567
-
568
- for link in soup.find_all('a', href=True):
569
- href = link['href']
570
- if href.startswith('/') or base_domain in href:
571
- internal_links.append(href)
572
- elif href.startswith('http'):
573
- external_links.append(href)
574
-
575
- return internal_links, external_links
576
-
577
- def _analyze_content(self, soup):
578
- # استخراج النص الكامل
579
- text = ' '.join([p.get_text() for p in soup.find_all('p')])
580
- words = text.split()
581
-
582
- # حساب كثافة الكلمات المفتاحية
583
- keywords = self._extract_keywords(soup)
584
- keyword_count = sum(text.lower().count(keyword) for keyword in keywords)
585
- keyword_density = keyword_count / len(words) if words else 0
586
-
587
- # تقييم تنوع المحتوى
588
- content_types = {
589
- 'صور': len(soup.find_all('img')),
590
- 'فيديوهات': len(soup.find_all(['video', 'iframe'])),
591
- 'جداول': len(soup.find_all('table')),
592
- 'قوائم': len(soup.find_all(['ul', 'ol'])),
593
- 'عناوين': len(soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']))
594
- }
595
-
596
- # حساب قابلية القراءة (مقياس مبسط)
597
- sentences = text.split('.')
598
- avg_words_per_sentence = len(words) / len(sentences) if sentences else 0
599
-
600
- recommendations = []
601
- if len(words) < 300:
602
- recommendations.append("المحتوى قصير جداً، أضف المزيد من النصوص الغنية")
603
- if keyword_density < 0.01:
604
- recommendations.append("كثافة الكلمات المفتاحية منخفضة")
605
- elif keyword_density > 0.05:
606
- recommendations.append("كثافة الكلمات المفتاحية مرتفعة جداً")
607
- if avg_words_per_sentence > 20:
608
- recommendations.append("الجمل طويلة جداً، حاول تقصيرها لتحسين القراءة")
609
-
610
- return {
611
- 'word_count': len(words),
612
- 'keyword_density': f"{keyword_density:.2%}",
613
- 'content_diversity': self._evaluate_diversity(content_types),
614
- 'readability': self._evaluate_readability(avg_words_per_sentence),
615
- 'recommendations': recommendations
616
- }
617
-
618
- def _evaluate_diversity(self, content_types):
619
- score = 0
620
- total_elements = sum(content_types.values())
621
-
622
- if content_types['صور'] > 0:
623
- score += 2
624
- if content_types['فيديوهات'] > 0:
625
- score += 2
626
- if content_types['جداول'] > 0:
627
- score += 1
628
- if content_types['قوائم'] > 0:
629
- score += 1
630
- if content_types['عناوين'] >= 3:
631
- score += 2
632
-
633
- if total_elements > 10:
634
- score += 2
635
-
636
- return f"{score}/10"
637
-
638
- def _evaluate_readability(self, avg_words_per_sentence):
639
- if avg_words_per_sentence <= 12:
640
- return "ممتاز"
641
- elif avg_words_per_sentence <= 15:
642
- return "جيد"
643
- elif avg_words_per_sentence <= 20:
644
- return "متوسط"
645
- else:
646
- return "صعب"
647
-
648
- def _evaluate_speed(self, total_load_time):
649
- if total_load_time < 2:
650
- return "ممتاز ⚡"
651
- elif total_load_time < 3:
652
- return "جيد ✅"
653
- elif total_load_time < 5:
654
- return "متوسط ⚠️"
655
- else:
656
- return "بطيء ❌"
657
-
658
- def _generate_performance_recommendations(self, metrics, resources):
659
- recommendations = []
660
-
661
- if metrics['ttfb'] > 0.5:
662
- recommendations.append("تحسين زمن استجابة الخادم")
663
-
664
- if resources['total_size'] > 1500: # أكثر من 1.5 ميجابايت
665
- recommendations.append("تقليل حجم الصفحة الإجمالي")
666
-
667
- if resources['images'] > 10:
668
- recommendations.append("ضغط وتحسين الصور")
669
-
670
- if resources['scripts'] > 15:
671
- recommendations.append("دمج وضغط ملفات JavaScript")
672
-
673
- if resources['stylesheets'] > 5:
674
- recommendations.append("دمج ملفات CSS")
675
-
676
- return recommendations
677
-
678
- async def _get_similarweb_data(self, domain):
679
- """
680
- الحصول على بيانات حركة المرور من SimilarWeb
681
- تحتاج لمفتاح API حقيقي للاستخدام
682
- """
683
- try:
684
- # هذا مجرد مثال، يجب استبداله بمفتاح API حقيقي
685
- api_key = "YOUR_SIMILARWEB_API_KEY"
686
- url = f"https://api.similarweb.com/v1/website/{domain}/total-traffic-and-engagement/visits"
687
-
688
- async with httpx.AsyncClient() as client:
689
- response = await client.get(url, headers={'Authorization': api_key})
690
- data = response.json()
691
- return data.get('visits', 0)
692
- except:
693
- return None
694
-
695
- async def _get_alexa_rank(self, domain):
696
- """
697
- الحصول على تصنيف Alexa للموقع
698
- ملاحظة: خدمة Alexa متوقفة حالياً، هذا مجرد مثال
699
- """
700
- try:
701
- url = f"http://data.alexa.com/data?cli=10&url={domain}"
702
- async with httpx.AsyncClient() as client:
703
- response = await client.get(url)
704
- soup = BeautifulSoup(response.text, 'xml')
705
- rank = soup.find('REACH')['RANK']
706
- return int(rank)
707
- except:
708
- return None
709
-
710
- def _rank_to_traffic(self, rank):
711
- """تحويل تصنيف Alexa إلى تقدير تقريبي لحركة المرور"""
712
- if not rank:
713
- return None
714
- # معادلة تقريبية جداً
715
- return int(1000000 / (rank ** 0.6))
716
-
717
- def _calculate_security_score(self, ssl_info, security_headers):
718
- score = 0
719
-
720
- # تقييم SSL
721
- if isinstance(ssl_info, dict) and ssl_info.get("الحالة") == "✅ آمن":
722
- score += 40
723
-
724
- # تقييم رؤوس الأمان
725
- headers_score = float(security_headers.get("درجة الأمان", "0/100").split('/')[0])
726
- score += headers_score * 0.6
727
-
728
- return f"{min(score, 100)}/100"
729
-
730
- def analyze_website(self, url):
731
- """
732
- تحليل شامل للموقع يشمل الأداء والأمان وSEO
733
- """
734
- results = {
735
- "url": url,
736
- "تاريخ_التحليل": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
737
- "نتائج_التحليل": {}
738
- }
739
-
740
- try:
741
- # تحليل الأداء
742
- performance_results = asyncio.run(self.analyze_performance(url))
743
- results["نتائج_التحليل"]["الأداء"] = performance_results
744
-
745
- # تحليل الأمان
746
- security_results = self.analyze_security(url)
747
- results["نتائج_التحليل"]["الأمان"] = security_results
748
-
749
- # تحليل SEO
750
- seo_results = asyncio.run(self.analyze_seo(url))
751
- results["نتائج_التحليل"]["SEO"] = seo_results
752
-
753
- return results
754
-
755
- except Exception as e:
756
- return {
757
- "error": f"حدث خطأ أثناء تحليل الموقع: {str(e)}",
758
- "url": url,
759
- "تاريخ_التحليل": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
760
- }
761
-
762
- def generate_report(self, results):
763
- """
764
- إنشاء تقرير مفصل بنتائج التحليل
765
- """
766
- report = {
767
- "ملخص_التحليل": {
768
- "الموقع": results["url"],
769
- "تاريخ_التحليل": results["تاريخ_التحليل"],
770
- "الحالة_العامة": self._calculate_overall_status(results)
771
- },
772
- "تفاصيل_التحليل": results["نتائج_التحليل"],
773
- "توصيات_عامة": self._generate_general_recommendations(results)
774
- }
775
-
776
- return report
777
-
778
- def _calculate_overall_status(self, results):
779
- """
780
- حساب الحالة العامة للموقع بناءً على جميع النتائج
781
- """
782
- if "error" in results:
783
- return "فشل التحل��ل ❌"
784
-
785
- scores = []
786
-
787
- # حساب درجة الأداء
788
- if "الأداء" in results["نتائج_التحليل"]:
789
- performance = results["نتائج_التحليل"]["الأداء"]
790
- if isinstance(performance, dict) and "أداء الموقع" in performance:
791
- speed_rating = performance["أداء الموقع"]["تقييم السرعة"]
792
- scores.append(self._convert_rating_to_score(speed_rating))
793
-
794
- # حساب درجة الأمان
795
- if "الأمان" in results["نتائج_التحليل"]:
796
- security = results["نتائج_التحليل"]["الأمان"]
797
- if isinstance(security, dict) and "تحليل الأمان" in security:
798
- security_score = security["تحليل الأمان"].get("درجة الأمان الكلية", "0/100")
799
- scores.append(float(security_score.split('/')[0]))
800
-
801
- # حساب درجة SEO
802
- if "SEO" in results["نتائج_التحليل"]:
803
- seo = results["نتائج_التحليل"]["SEO"]
804
- if isinstance(seo, dict) and "تحليل العناوين" in seo:
805
- seo_score = float(seo["تحليل العناوين"]["تقييم العنوان"].split('/')[0])
806
- scores.append(seo_score * 10) # تحويل من 10 إلى 100
807
-
808
- if not scores:
809
- return "غير معروف"
810
-
811
- average_score = sum(scores) / len(scores)
812
-
813
- if average_score >= 80:
814
- return "ممتاز 🌟"
815
- elif average_score >= 60:
816
- return "جيد ✅"
817
- elif average_score >= 40:
818
- return "متوسط ⚠️"
819
- else:
820
- return "ضعيف ❌"
821
-
822
- def _convert_rating_to_score(self, rating):
823
- """
824
- تحويل التقييم النصي إلى درجة رقمية
825
- """
826
- ratings = {
827
- "ممتاز ⚡": 100,
828
- "جيد ✅": 75,
829
- "متوسط ⚠️": 50,
830
- "بطيء ❌": 25
831
- }
832
- return ratings.get(rating, 0)
833
-
834
- def _generate_general_recommendations(self, results):
835
- """
836
- توليد توصيات عامة بناءً على نتائج التحليل
837
- """
838
- recommendations = []
839
-
840
- if "نتائج_التحليل" not in results:
841
- return recommendations
842
-
843
- analysis = results["نتائج_التحليل"]
844
-
845
- # توصيات الأداء
846
- if "الأداء" in analysis:
847
- performance = analysis["الأداء"]
848
- if isinstance(performance, dict):
849
- if "التوصيات" in performance:
850
- recommendations.extend(performance["التوصيات"])
851
-
852
- # توصيات الأمان
853
- if "الأمان" in analysis:
854
- security = analysis["الأمان"]
855
- if isinstance(security, dict) and "تحليل الأمان" in security:
856
- security_analysis = security["تحليل الأمان"]
857
- if "رؤوس الأمان" in security_analysis and "التوصيات" in security_analysis["رؤوس الأمان"]:
858
- recommendations.extend(security_analysis["رؤوس الأمان"]["التوصيات"])
859
-
860
- # توصيات SEO
861
- if "SEO" in analysis:
862
- seo = analysis["SEO"]
863
- if isinstance(seo, dict):
864
- for section in ["تحليل العناوين", "تحليل الوصف", "تحليل الكلمات المفتاحية"]:
865
- if section in seo and "التوصيات" in seo[section]:
866
- recommendations.extend(seo[section]["التوصيات"])
867
-
868
- return list(set(recommendations)) # إزالة التوصيات المكررة
869
-
870
- # إنشاء واجهة التطبيق باستخدام Streamlit
871
- def create_app():
872
- st.set_page_config(page_title="محلل المواقع", page_icon="🔍", layout="wide")
873
-
874
- st.title("🔍 محلل المواقع الشامل")
875
- st.markdown("---")
876
-
877
- # إدخال عنوان الموقع
878
- url = st.text_input("أدخل عنوان الموقع المراد تحليله", placeholder="https://example.com")
879
-
880
- if st.button("تحليل الموقع"):
881
- if url:
882
- try:
883
- with st.spinner("جاري تحليل الموقع..."):
884
- analyzer = WebsiteAnalyzer()
885
- results = analyzer.analyze_website(url)
886
- report = analyzer.generate_report(results)
887
-
888
- # عرض النتائج
889
- st.success("تم اكتمال التحليل بنجاح!")
890
-
891
- # عرض الملخص
892
- st.subheader("📊 ملخص التحليل")
893
- col1, col2, col3 = st.columns(3)
894
- with col1:
895
- st.metric("الحالة العامة", report["ملخص_التحليل"]["الحالة_العامة"])
896
-
897
- # عرض تفاصيل التحليل
898
- st.subheader("📝 تفاصيل التحليل")
899
- tabs = st.tabs(["الأداء", "الأمان", "SEO"])
900
-
901
- with tabs[0]:
902
- if "الأداء" in report["تفاصيل_التحليل"]:
903
- st.json(report["تفاصيل_التحليل"]["الأداء"])
904
-
905
- with tabs[1]:
906
- if "الأمان" in report["تفاصيل_التحليل"]:
907
- st.json(report["تفاصيل_التحليل"]["الأمان"])
908
-
909
- with tabs[2]:
910
- if "SEO" in report["تفاصيل_التحليل"]:
911
- st.json(report["تفاصيل_التحليل"]["SEO"])
912
-
913
- # عرض التوصيات
914
- st.subheader("💡 التوصيات")
915
- for i, recommendation in enumerate(report["توصيات_عامة"], 1):
916
- st.markdown(f"{i}. {recommendation}")
917
-
918
- except Exception as e:
919
- st.error(f"حدث خطأ أثناء تحليل الموقع: {str(e)}")
920
- else:
921
- st.warning("الرجاء إدخال عنوان الموقع المراد تحليله")
922
-
923
- if __name__ == "__main__":
924
- create_app()
 
509
  return "موثوقية متوسطة ⚠️"
510
  else:
511
  return "موثوقية منخفضة ⛔"
512
+