Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -12,15 +12,14 @@ import nltk
|
|
| 12 |
import emoji
|
| 13 |
from urllib.parse import urlparse, parse_qs
|
| 14 |
from nltk.corpus import stopwords
|
| 15 |
-
import logging
|
| 16 |
-
from concurrent.futures import ThreadPoolExecutor
|
| 17 |
-
from fake_useragent import UserAgent
|
| 18 |
-
import random
|
| 19 |
import io
|
| 20 |
import base64
|
| 21 |
-
import random # لاستخدام أخذ العينات العشوائية للتعليقات
|
| 22 |
-
from urllib.parse import urlparse, parse_qs
|
| 23 |
import math
|
|
|
|
| 24 |
|
| 25 |
# --- إعدادات NLTK و Logging ---
|
| 26 |
# ضبط مسار بيانات NLTK ليطابق Dockerfile
|
|
@@ -78,8 +77,6 @@ selected_user_agent = get_desktop_user_agent()
|
|
| 78 |
|
| 79 |
headers = {'User-Agent': selected_user_agent}
|
| 80 |
|
| 81 |
-
|
| 82 |
-
|
| 83 |
ydl_opts_video_info = {
|
| 84 |
'quiet': True,
|
| 85 |
'skip_download': True,
|
|
@@ -103,10 +100,7 @@ def extract_video_id(url):
|
|
| 103 |
return parse_qs(urlparse(url).query).get('v', [None])[0]
|
| 104 |
return None
|
| 105 |
|
| 106 |
-
|
| 107 |
-
# # --- تنظيف التعليقات ---
|
| 108 |
-
# arabic_stopwords = set(stopwords.words('arabic'))
|
| 109 |
-
|
| 110 |
def preprocess_text(text):
|
| 111 |
if not isinstance(text, str):
|
| 112 |
return ""
|
|
@@ -130,6 +124,9 @@ def process_single_video2(video_url, loaded_quality_model, loaded_sentiment_pipe
|
|
| 130 |
return None
|
| 131 |
|
| 132 |
try:
|
|
|
|
|
|
|
|
|
|
| 133 |
with yt_dlp.YoutubeDL(ydl_opts_video_info) as ydl:
|
| 134 |
info_dict = ydl.extract_info(video_url, download=False)
|
| 135 |
|
|
@@ -149,6 +146,9 @@ def process_single_video2(video_url, loaded_quality_model, loaded_sentiment_pipe
|
|
| 149 |
upload_date = info_dict.get('upload_date', 'Unknown')
|
| 150 |
publish_year = int(upload_date[:4]) if upload_date != 'Unknown' else datetime.now().year
|
| 151 |
|
|
|
|
|
|
|
|
|
|
| 152 |
# --- جلب التعليقات ---
|
| 153 |
sampled_comments = []
|
| 154 |
try:
|
|
@@ -216,13 +216,7 @@ def process_single_video2(video_url, loaded_quality_model, loaded_sentiment_pipe
|
|
| 216 |
logging.error(f"حدث خطأ في الفيديو {video_url}: {e}")
|
| 217 |
return None
|
| 218 |
|
| 219 |
-
|
| 220 |
-
# قم بإزالة @app.post إذا لم تعد هذه نقطة نهاية API
|
| 221 |
-
# ولكن بما أنك تستخدم هذا الملف كجزء من تطبيق FastAPI، فلا تزل @app.post.
|
| 222 |
-
# بدلاً من ذلك، سنعدل كيفية استدعاء tqdm في هذه الدالة.
|
| 223 |
-
# async def evaluate_youtube_playlist_individually_same_method2(youtube_url, max_comments_per_video=50, max_workers=3):
|
| 224 |
-
# بما أننا نستدعيها من Gradio، يمكننا تمرير المعلمات مباشرة دون الحاجة لـ Pydantic BaseModel
|
| 225 |
-
@app.post("/evaluate_youtube_playlist_individually_same_method2/") # أبقِ على هذا إذا كان لا يزال FastAPI API
|
| 226 |
async def evaluate_youtube_playlist_individually_same_method2(youtube_url: str, max_comments_per_video: int = 50, max_workers: int = 3):
|
| 227 |
"""
|
| 228 |
تقييم قائمة تشغيل يوتيوب باستخدام نظام مركب (نسخة 2)
|
|
@@ -230,7 +224,6 @@ async def evaluate_youtube_playlist_individually_same_method2(youtube_url: str,
|
|
| 230 |
|
| 231 |
if loaded_quality_model is None or loaded_sentiment_pipeline is None:
|
| 232 |
logging.error("لم يتم تحميل النماذج المطلوبة.")
|
| 233 |
-
# تغيير الاستجابة لتكون متناسقة مع Gradio
|
| 234 |
return {"error": "لم يتم تحميل النماذج المطلوبة."}
|
| 235 |
|
| 236 |
video_links = []
|
|
@@ -252,7 +245,6 @@ async def evaluate_youtube_playlist_individually_same_method2(youtube_url: str,
|
|
| 252 |
|
| 253 |
# --- معالجة الفيديوهات بالتوازي ---
|
| 254 |
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
| 255 |
-
# تمت إزالة tqdm هنا لتجنب المشاكل في بيئات غير تفاعلية
|
| 256 |
futures = [
|
| 257 |
executor.submit(
|
| 258 |
process_single_video2,
|
|
@@ -267,9 +259,11 @@ async def evaluate_youtube_playlist_individually_same_method2(youtube_url: str,
|
|
| 267 |
result = future.result()
|
| 268 |
if result:
|
| 269 |
individual_results.append(result)
|
|
|
|
|
|
|
| 270 |
|
| 271 |
# --- الإحصاء النهائي ---
|
| 272 |
-
num_good_videos = sum(1 for r in individual_results if r and r.get('quality') == 'جيد')
|
| 273 |
total_positive_comments = sum(r.get('positive_comments', 0) for r in individual_results if r)
|
| 274 |
total_negative_comments = sum(r.get('negative_comments', 0) for r in individual_results if r)
|
| 275 |
total_classified_comments = total_positive_comments + total_negative_comments
|
|
|
|
| 12 |
import emoji
|
| 13 |
from urllib.parse import urlparse, parse_qs
|
| 14 |
from nltk.corpus import stopwords
|
| 15 |
+
import logging
|
| 16 |
+
from concurrent.futures import ThreadPoolExecutor
|
| 17 |
+
from fake_useragent import UserAgent
|
| 18 |
+
import random
|
| 19 |
import io
|
| 20 |
import base64
|
|
|
|
|
|
|
| 21 |
import math
|
| 22 |
+
import time # تم إضافة هذه المكتبة للتحكم في التأخير
|
| 23 |
|
| 24 |
# --- إعدادات NLTK و Logging ---
|
| 25 |
# ضبط مسار بيانات NLTK ليطابق Dockerfile
|
|
|
|
| 77 |
|
| 78 |
headers = {'User-Agent': selected_user_agent}
|
| 79 |
|
|
|
|
|
|
|
| 80 |
ydl_opts_video_info = {
|
| 81 |
'quiet': True,
|
| 82 |
'skip_download': True,
|
|
|
|
| 100 |
return parse_qs(urlparse(url).query).get('v', [None])[0]
|
| 101 |
return None
|
| 102 |
|
| 103 |
+
# --- تنظيف التعليقات ---
|
|
|
|
|
|
|
|
|
|
| 104 |
def preprocess_text(text):
|
| 105 |
if not isinstance(text, str):
|
| 106 |
return ""
|
|
|
|
| 124 |
return None
|
| 125 |
|
| 126 |
try:
|
| 127 |
+
# إضافة تأخير عشوائي قبل كل طلب معلومات فيديو
|
| 128 |
+
time.sleep(random.uniform(1, 3)) # تأخير بين 1 و 3 ثوانٍ
|
| 129 |
+
|
| 130 |
with yt_dlp.YoutubeDL(ydl_opts_video_info) as ydl:
|
| 131 |
info_dict = ydl.extract_info(video_url, download=False)
|
| 132 |
|
|
|
|
| 146 |
upload_date = info_dict.get('upload_date', 'Unknown')
|
| 147 |
publish_year = int(upload_date[:4]) if upload_date != 'Unknown' else datetime.now().year
|
| 148 |
|
| 149 |
+
# إضافة تأخير عشوائي قبل كل طلب جلب تعليقات
|
| 150 |
+
time.sleep(random.uniform(1, 3)) # تأخير بين 1 و 3 ثوانٍ
|
| 151 |
+
|
| 152 |
# --- جلب التعليقات ---
|
| 153 |
sampled_comments = []
|
| 154 |
try:
|
|
|
|
| 216 |
logging.error(f"حدث خطأ في الفيديو {video_url}: {e}")
|
| 217 |
return None
|
| 218 |
|
| 219 |
+
@app.post("/evaluate_youtube_playlist_individually_same_method2/")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
async def evaluate_youtube_playlist_individually_same_method2(youtube_url: str, max_comments_per_video: int = 50, max_workers: int = 3):
|
| 221 |
"""
|
| 222 |
تقييم قائمة تشغيل يوتيوب باستخدام نظام مركب (نسخة 2)
|
|
|
|
| 224 |
|
| 225 |
if loaded_quality_model is None or loaded_sentiment_pipeline is None:
|
| 226 |
logging.error("لم يتم تحميل النماذج المطلوبة.")
|
|
|
|
| 227 |
return {"error": "لم يتم تحميل النماذج المطلوبة."}
|
| 228 |
|
| 229 |
video_links = []
|
|
|
|
| 245 |
|
| 246 |
# --- معالجة الفيديوهات بالتوازي ---
|
| 247 |
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
|
|
| 248 |
futures = [
|
| 249 |
executor.submit(
|
| 250 |
process_single_video2,
|
|
|
|
| 259 |
result = future.result()
|
| 260 |
if result:
|
| 261 |
individual_results.append(result)
|
| 262 |
+
# تأخير إضافي بين معالجة نتائج الفيديوهات (اختياري)
|
| 263 |
+
time.sleep(random.uniform(0.5, 1.5)) # تأخير بين 0.5 و 1.5 ثانية
|
| 264 |
|
| 265 |
# --- الإحصاء النهائي ---
|
| 266 |
+
num_good_videos = sum(1 for r in individual_results if r and r.get('quality') == 'جيد')
|
| 267 |
total_positive_comments = sum(r.get('positive_comments', 0) for r in individual_results if r)
|
| 268 |
total_negative_comments = sum(r.get('negative_comments', 0) for r in individual_results if r)
|
| 269 |
total_classified_comments = total_positive_comments + total_negative_comments
|