Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -18,7 +18,6 @@ from fake_useragent import UserAgent # جديد
|
|
| 18 |
import random # جديد
|
| 19 |
import io
|
| 20 |
import base64
|
| 21 |
-
from tqdm.notebook import tqdm # تم إضافة tqdm هنا لتكون متاحة بشكل عام
|
| 22 |
import random # لاستخدام أخذ العينات العشوائية للتعليقات
|
| 23 |
from urllib.parse import urlparse, parse_qs
|
| 24 |
import math
|
|
@@ -49,7 +48,7 @@ loaded_quality_model = None
|
|
| 49 |
loaded_sentiment_pipeline = None
|
| 50 |
|
| 51 |
try:
|
| 52 |
-
with open('
|
| 53 |
loaded_quality_model = pickle.load(f)
|
| 54 |
logging.info("تم تحميل نموذج جودة الفيديو بنجاح.")
|
| 55 |
except FileNotFoundError:
|
|
@@ -58,7 +57,7 @@ except Exception as e:
|
|
| 58 |
logging.error(f"خطأ غير متوقع أثناء تحميل نموذج جودة الفيديو: {e}")
|
| 59 |
|
| 60 |
try:
|
| 61 |
-
with open('
|
| 62 |
loaded_sentiment_pipeline = pickle.load(f)
|
| 63 |
logging.info("تم تحميل نموذج تصنيف المشاعر بنجاح.")
|
| 64 |
except FileNotFoundError:
|
|
@@ -148,7 +147,7 @@ def process_single_video2(video_url, loaded_quality_model, loaded_sentiment_pipe
|
|
| 148 |
logging.info(f"[فيديو: {video_url}] المشاهدات: {views}, الإعجابات: {likes}")
|
| 149 |
|
| 150 |
upload_date = info_dict.get('upload_date', 'Unknown')
|
| 151 |
-
publish_year = int(upload_date[:4]) if upload_date != 'Unknown' else datetime.
|
| 152 |
|
| 153 |
# --- جلب التعليقات ---
|
| 154 |
sampled_comments = []
|
|
@@ -186,14 +185,14 @@ def process_single_video2(video_url, loaded_quality_model, loaded_sentiment_pipe
|
|
| 186 |
|
| 187 |
input_df = pd.DataFrame([[views, likes, len(sampled_comments), 0, publish_year,
|
| 188 |
like_view_ratio, comment_view_ratio, engagement_score]],
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
|
| 193 |
playlist_quality = "لم يتم التقييم"
|
| 194 |
try:
|
| 195 |
prediction_numeric = loaded_quality_model.predict(input_df)[0]
|
| 196 |
-
logging.info(f"[فيديو: {video_url}] نتيجة التنبؤ: {prediction_numeric}")
|
| 197 |
playlist_quality = "جيد" if prediction_numeric == 1 else "سيء"
|
| 198 |
except Exception as e:
|
| 199 |
playlist_quality = f"خطأ في التقييم: {e}"
|
|
@@ -217,18 +216,21 @@ def process_single_video2(video_url, loaded_quality_model, loaded_sentiment_pipe
|
|
| 217 |
logging.error(f"حدث خطأ في الفيديو {video_url}: {e}")
|
| 218 |
return None
|
| 219 |
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
#
|
| 224 |
-
|
| 225 |
-
|
|
|
|
|
|
|
| 226 |
"""
|
| 227 |
تقييم قائمة تشغيل يوتيوب باستخدام نظام مركب (نسخة 2)
|
| 228 |
"""
|
| 229 |
|
| 230 |
if loaded_quality_model is None or loaded_sentiment_pipeline is None:
|
| 231 |
logging.error("لم يتم تحميل النماذج المطلوبة.")
|
|
|
|
| 232 |
return {"error": "لم يتم تحميل النماذج المطلوبة."}
|
| 233 |
|
| 234 |
video_links = []
|
|
@@ -250,6 +252,7 @@ async def evaluate_youtube_playlist_individually_same_method2(youtube_url, max_c
|
|
| 250 |
|
| 251 |
# --- معالجة الفيديوهات بالتوازي ---
|
| 252 |
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
|
|
| 253 |
futures = [
|
| 254 |
executor.submit(
|
| 255 |
process_single_video2,
|
|
@@ -260,15 +263,15 @@ async def evaluate_youtube_playlist_individually_same_method2(youtube_url, max_c
|
|
| 260 |
) for video_url in video_links
|
| 261 |
]
|
| 262 |
|
| 263 |
-
for future in
|
| 264 |
result = future.result()
|
| 265 |
if result:
|
| 266 |
individual_results.append(result)
|
| 267 |
|
| 268 |
# --- الإحصاء النهائي ---
|
| 269 |
-
num_good_videos = sum(1 for r in individual_results if r
|
| 270 |
-
total_positive_comments = sum(r
|
| 271 |
-
total_negative_comments = sum(r
|
| 272 |
total_classified_comments = total_positive_comments + total_negative_comments
|
| 273 |
|
| 274 |
total_videos = len(individual_results)
|
|
|
|
| 18 |
import random # جديد
|
| 19 |
import io
|
| 20 |
import base64
|
|
|
|
| 21 |
import random # لاستخدام أخذ العينات العشوائية للتعليقات
|
| 22 |
from urllib.parse import urlparse, parse_qs
|
| 23 |
import math
|
|
|
|
| 48 |
loaded_sentiment_pipeline = None
|
| 49 |
|
| 50 |
try:
|
| 51 |
+
with open('final_youtube_quality_model.pkl', 'rb') as f:
|
| 52 |
loaded_quality_model = pickle.load(f)
|
| 53 |
logging.info("تم تحميل نموذج جودة الفيديو بنجاح.")
|
| 54 |
except FileNotFoundError:
|
|
|
|
| 57 |
logging.error(f"خطأ غير متوقع أثناء تحميل نموذج جودة الفيديو: {e}")
|
| 58 |
|
| 59 |
try:
|
| 60 |
+
with open('best_sentiment_pipeline.pkl', 'rb') as f:
|
| 61 |
loaded_sentiment_pipeline = pickle.load(f)
|
| 62 |
logging.info("تم تحميل نموذج تصنيف المشاعر بنجاح.")
|
| 63 |
except FileNotFoundError:
|
|
|
|
| 147 |
logging.info(f"[فيديو: {video_url}] المشاهدات: {views}, الإعجابات: {likes}")
|
| 148 |
|
| 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 = []
|
|
|
|
| 185 |
|
| 186 |
input_df = pd.DataFrame([[views, likes, len(sampled_comments), 0, publish_year,
|
| 187 |
like_view_ratio, comment_view_ratio, engagement_score]],
|
| 188 |
+
columns=['views_count', 'likes_count', 'comments_count',
|
| 189 |
+
'video_duration_seconds', 'publish_year',
|
| 190 |
+
'like_view_ratio', 'comment_view_ratio', 'engagement_score'])
|
| 191 |
|
| 192 |
playlist_quality = "لم يتم التقييم"
|
| 193 |
try:
|
| 194 |
prediction_numeric = loaded_quality_model.predict(input_df)[0]
|
| 195 |
+
logging.info(f"[فيديو: {video_url}] نتيجة التنبؤ: {prediction_numeric}")
|
| 196 |
playlist_quality = "جيد" if prediction_numeric == 1 else "سيء"
|
| 197 |
except Exception as e:
|
| 198 |
playlist_quality = f"خطأ في التقييم: {e}"
|
|
|
|
| 216 |
logging.error(f"حدث خطأ في الفيديو {video_url}: {e}")
|
| 217 |
return None
|
| 218 |
|
| 219 |
+
# دالة FastAPI الأصلية التي ستستدعيها Gradio
|
| 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)
|
| 229 |
"""
|
| 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 |
|
| 253 |
# --- معالجة الفيديوهات بالتوازي ---
|
| 254 |
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
| 255 |
+
# تمت إزالة tqdm هنا لتجنب المشاكل في بيئات غير تفاعلية
|
| 256 |
futures = [
|
| 257 |
executor.submit(
|
| 258 |
process_single_video2,
|
|
|
|
| 263 |
) for video_url in video_links
|
| 264 |
]
|
| 265 |
|
| 266 |
+
for future in futures: # استخدام futures مباشرة بدون tqdm
|
| 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') == 'جيد') # إضافة r and r.get('quality') للتحقق من عدم وجود None
|
| 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
|
| 276 |
|
| 277 |
total_videos = len(individual_results)
|