Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,82 +1,76 @@
|
|
1 |
-
import
|
|
|
|
|
2 |
import logging
|
3 |
|
4 |
# Configure logging for debugging purposes
|
5 |
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
|
6 |
|
7 |
-
# Function to search YouTube
|
8 |
-
def youtube_search(query, max_results=
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
'simulate': True,
|
14 |
-
'noplaylist': True, # Avoid playlist entries
|
15 |
-
'ignoreerrors': True, # Continue on errors without stopping
|
16 |
-
'force_generic_extractor': False, # Use the best extractor available
|
17 |
-
'default_search': 'ytsearch', # Default search method
|
18 |
}
|
19 |
-
search_url = f"ytsearch{max_results}:{query}"
|
20 |
|
21 |
logging.debug(f"Starting YouTube search for query: {query}")
|
22 |
|
23 |
try:
|
24 |
-
|
25 |
-
|
26 |
|
27 |
-
|
28 |
-
|
29 |
-
return []
|
30 |
|
31 |
-
|
32 |
-
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
print(f"Title: {entry.get('title', 'N/A')}")
|
42 |
-
print(f"Uploader: {entry.get('uploader', 'N/A')}")
|
43 |
-
print(f"Uploader ID: {entry.get('uploader_id', 'N/A')}")
|
44 |
-
print(f"Upload Date: {entry.get('upload_date', 'N/A')}")
|
45 |
-
print(f"Description: {entry.get('description', 'N/A')}")
|
46 |
-
print(f"Duration (seconds): {entry.get('duration', 'N/A')}")
|
47 |
-
print(f"View Count: {entry.get('view_count', 'N/A')}")
|
48 |
-
print(f"Like Count: {entry.get('like_count', 'N/A')}")
|
49 |
-
print(f"Dislike Count: {entry.get('dislike_count', 'N/A')}")
|
50 |
-
print(f"Comment Count: {entry.get('comment_count', 'N/A')}")
|
51 |
-
print(f"Average Rating: {entry.get('average_rating', 'N/A')}")
|
52 |
-
print(f"Thumbnail URL: {entry.get('thumbnail', 'N/A')}")
|
53 |
-
print(f"Webpage URL: {entry.get('webpage_url', 'N/A')}")
|
54 |
-
print(f"Channel URL: {entry.get('channel_url', 'N/A')}")
|
55 |
-
print(f"Categories: {entry.get('categories', 'N/A')}")
|
56 |
-
print(f"Tags: {entry.get('tags', 'N/A')}")
|
57 |
-
print(f"Channel ID: {entry.get('channel_id', 'N/A')}")
|
58 |
-
print(f"Age Restriction: {entry.get('age_limit', 'N/A')}")
|
59 |
-
print(f"Is Live: {entry.get('is_live', 'N/A')}")
|
60 |
-
print(f"FPS: {entry.get('fps', 'N/A')}")
|
61 |
-
print(f"Resolution: {entry.get('resolution', 'N/A')}")
|
62 |
-
print(f"Aspect Ratio: {entry.get('aspect_ratio', 'N/A')}")
|
63 |
-
print(f"Video Codec: {entry.get('vcodec', 'N/A')}")
|
64 |
-
print(f"Audio Codec: {entry.get('acodec', 'N/A')}")
|
65 |
-
print("==============================\n")
|
66 |
|
67 |
-
|
68 |
-
|
69 |
|
70 |
-
|
71 |
|
72 |
-
except
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
except Exception as e:
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
|
81 |
-
#
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import requests
|
2 |
+
from bs4 import BeautifulSoup
|
3 |
+
import gradio as gr
|
4 |
import logging
|
5 |
|
6 |
# Configure logging for debugging purposes
|
7 |
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
|
8 |
|
9 |
+
# Function to search YouTube without using the API
|
10 |
+
def youtube_search(query, max_results=10):
|
11 |
+
# Create the YouTube search URL
|
12 |
+
search_url = f"https://www.youtube.com/results?search_query={query.replace(' ', '+')}"
|
13 |
+
headers = {
|
14 |
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36"
|
|
|
|
|
|
|
|
|
|
|
15 |
}
|
|
|
16 |
|
17 |
logging.debug(f"Starting YouTube search for query: {query}")
|
18 |
|
19 |
try:
|
20 |
+
response = requests.get(search_url, headers=headers)
|
21 |
+
response.raise_for_status() # Raise an error for bad status codes
|
22 |
|
23 |
+
# Parse the HTML response using BeautifulSoup
|
24 |
+
soup = BeautifulSoup(response.text, "html.parser")
|
|
|
25 |
|
26 |
+
# Find all video entries
|
27 |
+
videos = soup.find_all("a", {"href": lambda x: x and "/watch?v=" in x}, limit=max_results)
|
28 |
|
29 |
+
gallery_items = []
|
30 |
+
for video in videos:
|
31 |
+
# Extract details
|
32 |
+
video_id = video['href'].split('=')[1]
|
33 |
+
video_title = video.get('title', 'No Title')
|
34 |
+
video_url = f"https://www.youtube.com{video['href']}"
|
35 |
+
thumbnail_url = f"https://i.ytimg.com/vi/{video_id}/hqdefault.jpg"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
|
37 |
+
# Append video details as a tuple for the gallery display
|
38 |
+
gallery_items.append((thumbnail_url, video_title, video_url))
|
39 |
|
40 |
+
return gallery_items, "" # Return the list of gallery items and no error message
|
41 |
|
42 |
+
except requests.exceptions.RequestException as e:
|
43 |
+
error_message = f"Request error occurred: {e}"
|
44 |
+
logging.error(error_message)
|
45 |
+
return [], error_message
|
46 |
except Exception as e:
|
47 |
+
error_message = f"An unexpected error occurred: {e}"
|
48 |
+
logging.error(error_message)
|
49 |
+
return [], error_message
|
50 |
|
51 |
+
# Function to create a gallery for Gradio
|
52 |
+
def display_videos(query):
|
53 |
+
gallery_items, error_message = youtube_search(query)
|
54 |
+
if error_message:
|
55 |
+
return gr.update(value=[], label="Error: Unable to fetch videos"), error_message
|
56 |
+
|
57 |
+
# Display thumbnails and titles as gallery items
|
58 |
+
formatted_gallery = [(f"<img src='{item[0]}' width='250'/>", f"<a href='{item[2]}' target='_blank'>{item[1]}</a>") for item in gallery_items]
|
59 |
+
return formatted_gallery, ""
|
60 |
+
|
61 |
+
# Gradio interface
|
62 |
+
with gr.Blocks() as demo:
|
63 |
+
gr.Markdown("## YouTube Video Search (Without API)")
|
64 |
+
with gr.Row():
|
65 |
+
with gr.Column(scale=2):
|
66 |
+
search_input = gr.Textbox(label="Search YouTube", placeholder="Enter your search query here")
|
67 |
+
search_button = gr.Button("Search")
|
68 |
+
with gr.Column(scale=4):
|
69 |
+
search_output = gr.Gallery(label="Search Results", columns=2)
|
70 |
+
error_output = gr.Textbox(label="Error Message", interactive=False, visible=False)
|
71 |
+
|
72 |
+
# Define search button behavior
|
73 |
+
search_button.click(display_videos, inputs=search_input, outputs=[search_output, error_output])
|
74 |
+
|
75 |
+
# Launch the Gradio interface
|
76 |
+
demo.launch()
|