Sayiqa commited on
Commit
8bbbafb
·
verified ·
1 Parent(s): 6250800

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -124
app.py CHANGED
@@ -272,6 +272,12 @@ from youtube_transcript_api import YouTubeTranscriptApi, TranscriptsDisabled, No
272
  import re
273
  from collections import Counter
274
  from googleapiclient.discovery import build
 
 
 
 
 
 
275
 
276
  def process_youtube_video(url=""):
277
  """
@@ -292,11 +298,17 @@ def process_youtube_video(url=""):
292
  if isinstance(text, dict) and "error" in text:
293
  return text
294
 
 
 
 
 
 
295
  # Perform sentiment analysis
296
  sentiment_result = analyze_sentiment(text)
297
 
298
  return {
299
  "success": True,
 
300
  "sentiment": sentiment_result,
301
  "video_id": video_id
302
  }
@@ -304,140 +316,66 @@ def process_youtube_video(url=""):
304
  except Exception as e:
305
  return {"error": f"An error occurred: {str(e)}"}
306
 
307
- def get_video_transcript(video_id):
308
- """
309
- Fetch and return the transcript of a YouTube video.
310
- """
311
- try:
312
- transcript_list = YouTubeTranscriptApi.list_transcripts(video_id)
313
-
314
- # Try to get English transcript
315
- try:
316
- transcript = transcript_list.find_transcript(['en'])
317
- except:
318
- # Try to get auto-generated English transcript
319
- try:
320
- transcript = transcript_list.find_generated_transcript(['en'])
321
- except:
322
- return {"error": "No English transcript available"}
323
-
324
- # Combine all transcript pieces
325
- text = " ".join([t['text'] for t in transcript.fetch()])
326
-
327
- if not text.strip():
328
- return {"error": "Empty transcript"}
329
-
330
- return text
331
-
332
- except TranscriptsDisabled:
333
- return {"error": "Transcripts are disabled for this video"}
334
- except NoTranscriptFound:
335
- return {"error": "No transcript found for this video"}
336
- except Exception as e:
337
- return {"error": f"Error fetching transcript: {str(e)}"}
338
-
339
- def analyze_sentiment(text):
340
  """
341
- Perform detailed sentiment analysis on the text.
342
  """
343
  try:
344
- # Clean the text
345
- cleaned_text = clean_text_for_analysis(text)
346
-
347
- # Create TextBlob object
348
- blob = TextBlob(cleaned_text)
349
-
350
- # Analyze sentiment for each sentence
351
- sentences = blob.sentences
352
- sentence_sentiments = [sentence.sentiment.polarity for sentence in sentences]
353
-
354
- # Calculate overall metrics
355
- total_sentences = len(sentences)
356
- avg_polarity = sum(sentence_sentiments) / total_sentences if total_sentences > 0 else 0
357
-
358
- # Count sentiment distributions
359
- positive_sentences = sum(1 for s in sentence_sentiments if s > 0)
360
- negative_sentences = sum(1 for s in sentence_sentiments if s < 0)
361
- neutral_sentences = sum(1 for s in sentence_sentiments if s == 0)
362
-
363
- # Get detailed sentiment classification
364
- sentiment_category = get_detailed_sentiment(avg_polarity)
365
-
366
- return {
367
- "overall_sentiment": sentiment_category,
368
- "average_polarity": round(avg_polarity, 3),
369
- "total_sentences": total_sentences,
370
- "sentiment_distribution": {
371
- "positive": positive_sentences,
372
- "negative": negative_sentences,
373
- "neutral": neutral_sentences
374
  }
375
- }
376
-
377
- except Exception as e:
378
- return {"error": f"Error in sentiment analysis: {str(e)}"}
379
 
380
- def extract_video_id(url):
381
- """
382
- Extract video ID from various forms of YouTube URLs.
383
- """
384
- patterns = [
385
- r'(?:v=|\/)([0-9A-Za-z_-]{11}).*', # Standard and shared URLs
386
- r'(?:embed\/)([0-9A-Za-z_-]{11})', # Embed URLs
387
- r'(?:youtu\.be\/)([0-9A-Za-z_-]{11})' # Short URLs
388
- ]
389
-
390
- for pattern in patterns:
391
- match = re.search(pattern, url)
392
- if match:
393
- return match.group(1)
394
- return None
395
-
396
- def clean_text_for_analysis(text):
397
- """
398
- Clean and normalize text for analysis.
399
- """
400
- # Remove extra whitespace
401
- text = " ".join(text.split())
402
-
403
- # Remove special characters and numbers (keep punctuation for sentiment analysis)
404
- text = re.sub(r'[^a-zA-Z\s.,!?\'"-]', '', text)
405
-
406
- return text
407
 
408
- def get_detailed_sentiment(polarity):
409
- """
410
- Get detailed sentiment classification based on polarity score.
411
- """
412
- if polarity > 0.75:
413
- return "Very Positive"
414
- elif polarity > 0.25:
415
- return "Positive"
416
- elif polarity > -0.25:
417
- return "Neutral"
418
- elif polarity > -0.75:
419
- return "Negative"
420
- else:
421
- return "Very Negative"
422
 
423
- # Example usage:
424
  if __name__ == "__main__":
425
- # Example URL
426
- url = "https://www.youtube.com/watch?v=your_video_id"
427
- result = process_youtube_video(url)
428
 
429
- if "error" in result:
430
- print(f"Error: {result['error']}")
 
431
  else:
432
- print("Sentiment Analysis Results:")
433
- print(f"Overall Sentiment: {result['sentiment']['overall_sentiment']}")
434
- print(f"Average Polarity: {result['sentiment']['average_polarity']}")
435
- print("\nSentiment Distribution:")
436
- dist = result['sentiment']['sentiment_distribution']
437
- print(f"Positive Sentences: {dist['positive']}")
438
- print(f"Negative Sentences: {dist['negative']}")
439
- print(f"Neutral Sentences: {dist['neutral']}")
440
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
441
 
442
 
443
 
 
272
  import re
273
  from collections import Counter
274
  from googleapiclient.discovery import build
275
+ import os
276
+
277
+ # Set your YouTube API key
278
+ YOUTUBE_API_KEY = "YOUR_API_KEY_HERE" # Replace with your actual API key
279
+ # Alternatively, you can set it as an environment variable:
280
+ # YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY')
281
 
282
  def process_youtube_video(url=""):
283
  """
 
298
  if isinstance(text, dict) and "error" in text:
299
  return text
300
 
301
+ # Get video metadata
302
+ metadata = get_video_metadata(video_id)
303
+ if "error" in metadata:
304
+ return metadata
305
+
306
  # Perform sentiment analysis
307
  sentiment_result = analyze_sentiment(text)
308
 
309
  return {
310
  "success": True,
311
+ "metadata": metadata,
312
  "sentiment": sentiment_result,
313
  "video_id": video_id
314
  }
 
316
  except Exception as e:
317
  return {"error": f"An error occurred: {str(e)}"}
318
 
319
+ def get_video_metadata(video_id):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  """
321
+ Fetches video metadata using the YouTube Data API.
322
  """
323
  try:
324
+ youtube = build("youtube", "v3", developerKey=YOUTUBE_API_KEY)
325
+ request = youtube.videos().list(
326
+ part="snippet",
327
+ id=video_id
328
+ )
329
+ response = request.execute()
330
+
331
+ if response.get("items"):
332
+ snippet = response["items"][0]["snippet"]
333
+ return {
334
+ "title": snippet.get("title", ""),
335
+ "description": snippet.get("description", ""),
336
+ "publishedAt": snippet.get("publishedAt", ""),
337
+ "channelTitle": snippet.get("channelTitle", "")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  }
339
+ return {"error": "Video not found"}
 
 
 
340
 
341
+ except Exception as e:
342
+ return {"error": f"Error fetching metadata: {str(e)}"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
 
344
+ # [Previous functions remain the same: get_video_transcript, analyze_sentiment,
345
+ # extract_video_id, clean_text_for_analysis, get_detailed_sentiment]
 
 
 
 
 
 
 
 
 
 
 
 
346
 
347
+ # Example usage with proper error handling:
348
  if __name__ == "__main__":
349
+ # Example with a real YouTube URL
350
+ test_url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ" # Replace with any YouTube URL
 
351
 
352
+ # Check if API key is set
353
+ if YOUTUBE_API_KEY == "AIzaSyD_SDF4lC3vpHVAMnBOcN2ZCTz7dRjUc98":
354
+ print("Error: Please set your YouTube API key first!")
355
  else:
356
+ result = process_youtube_video(test_url)
357
+
358
+ if "error" in result:
359
+ print(f"Error: {result['error']}")
360
+ else:
361
+ print("\n=== Video Information ===")
362
+ print(f"Title: {result['metadata']['title']}")
363
+ print(f"Channel: {result['metadata']['channelTitle']}")
364
+
365
+ print("\n=== Sentiment Analysis Results ===")
366
+ sentiment = result['sentiment']
367
+ print(f"Overall Sentiment: {sentiment['overall_sentiment']}")
368
+ print(f"Average Polarity: {sentiment['average_polarity']}")
369
+
370
+ print("\nSentiment Distribution:")
371
+ dist = sentiment['sentiment_distribution']
372
+ total = sum(dist.values())
373
+ if total > 0:
374
+ print(f"Positive: {dist['positive']} ({(dist['positive']/total*100):.1f}%)")
375
+ print(f"Neutral: {dist['neutral']} ({(dist['neutral']/total*100):.1f}%)")
376
+ print(f"Negative: {dist['negative']} ({(dist['negative']/total*100):.1f}%)")
377
+
378
+ print(f"\nTotal Sentences Analyzed: {sentiment['total_sentences']}")
379
 
380
 
381