d3evil4 commited on
Commit
2796280
·
verified ·
1 Parent(s): be531de

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +137 -227
app.py CHANGED
@@ -1,228 +1,138 @@
1
- from fastapi import FastAPI, HTTPException, BackgroundTasks
2
- from fastapi.responses import JSONResponse
3
- import asyncio
4
- import random
5
- import logging
6
- from typing import List, Dict, Optional, Any
7
- from playwright.async_api import async_playwright
8
- import uvicorn
9
- from pydantic import BaseModel
10
-
11
- # Set up logging
12
- logging.basicConfig(level=logging.INFO,
13
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
14
- logger = logging.getLogger(__name__)
15
-
16
- app = FastAPI(title="Kling Video Fetcher",
17
- description="API to fetch random videos from Kling AI gallery")
18
-
19
- # Model for the response
20
- class VideoResponse(BaseModel):
21
- url: str
22
- thumbnail: Optional[str] = None
23
- title: Optional[str] = None
24
- status: str = "success"
25
-
26
- # Cache to store recent video URLs
27
- video_cache: List[Dict[str, Any]] = []
28
- last_fetch_time = 0
29
-
30
- async def fetch_random_video_from_kling() -> Dict[str, Any]:
31
- """
32
- Fetches a random video from Kling AI gallery and returns its URL.
33
- Returns a dictionary with video information.
34
- """
35
- try:
36
- async with async_playwright() as p:
37
- # Configure browser with a realistic user agent and longer timeout
38
- browser_context_options = {
39
- 'viewport': {'width': 1280, 'height': 800},
40
- 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
41
- }
42
-
43
- # Launch the browser in headless mode with anti-detection args
44
- browser = await p.chromium.launch(
45
- headless=True,
46
- args=[
47
- '--no-sandbox',
48
- '--disable-setuid-sandbox',
49
- '--disable-dev-shm-usage',
50
- '--disable-accelerated-2d-canvas',
51
- '--no-first-run',
52
- '--no-zygote',
53
- '--disable-gpu',
54
- '--disable-web-security',
55
- ]
56
- )
57
- context = await browser.new_context(**browser_context_options)
58
- page = await context.new_page()
59
-
60
- try:
61
- logger.info("Navigating to Kling AI gallery...")
62
- # Use a longer timeout and wait until networkidle
63
- await page.goto(
64
- "https://app.klingai.com/global/community/material",
65
- timeout=90000,
66
- wait_until="networkidle"
67
- )
68
- logger.info("Successfully loaded gallery page")
69
- except Exception as e:
70
- logger.error(f"Error navigating to gallery: {e}")
71
- raise HTTPException(status_code=504, detail=f"Unable to access Kling AI gallery: {str(e)}")
72
-
73
- # Wait for dynamic content to load
74
- logger.info("Waiting for dynamic content to load...")
75
- await page.wait_for_timeout(5000)
76
-
77
- # Scroll to load content
78
- logger.info("Scrolling to load gallery content...")
79
- scroll_attempts = 6
80
- for i in range(scroll_attempts):
81
- logger.info(f"Scroll {i+1}/{scroll_attempts}")
82
- await page.evaluate("window.scrollBy(0, 800)")
83
- await page.wait_for_timeout(1500)
84
-
85
- # Find potential video elements
86
- logger.info("Searching for video elements...")
87
- all_potential_elements = []
88
-
89
- # Direct video elements
90
- videos = await page.query_selector_all("video")
91
- if videos:
92
- logger.info(f"Found {len(videos)} direct video elements")
93
- all_potential_elements.extend(videos)
94
-
95
- # Look for video containers
96
- video_containers = await page.query_selector_all(
97
- '[class*="video"], [class*="player"], [class*="media"], ' +
98
- '[class*="thumbnail"], [class*="card"], [class*="item"]'
99
- )
100
- if video_containers:
101
- logger.info(f"Found {len(video_containers)} potential video containers")
102
- all_potential_elements.extend(video_containers)
103
-
104
- # Filter to keep only visible elements
105
- visible_elements = []
106
- for element in all_potential_elements:
107
- try:
108
- is_visible = await element.is_visible()
109
- if is_visible:
110
- visible_elements.append(element)
111
- except Exception:
112
- continue
113
-
114
- if visible_elements:
115
- logger.info(f"Found {len(visible_elements)} visible elements")
116
- all_potential_elements = visible_elements
117
-
118
- if not all_potential_elements:
119
- logger.error("No potential video elements found")
120
- raise HTTPException(status_code=404, detail="No video elements found on the page")
121
-
122
- # Try multiple elements until we find a video
123
- # Shuffling the elements to increase randomness
124
- random.shuffle(all_potential_elements)
125
-
126
- # We'll try up to 5 random elements
127
- max_attempts = min(5, len(all_potential_elements))
128
-
129
- for attempt in range(max_attempts):
130
- selected_element = all_potential_elements[attempt]
131
-
132
- try:
133
- # Scroll the element into view
134
- await selected_element.scroll_into_view_if_needed()
135
- await page.wait_for_timeout(1000)
136
-
137
- # Click on the selected element
138
- logger.info(f"Clicking on element (attempt {attempt+1}/{max_attempts})...")
139
- await selected_element.click()
140
- await page.wait_for_timeout(3000)
141
-
142
- # Look for video elements that appeared after clicking
143
- post_click_videos = await page.query_selector_all("video")
144
-
145
- if post_click_videos:
146
- logger.info(f"Found {len(post_click_videos)} video elements after clicking!")
147
-
148
- # Find a video with a source
149
- for video in post_click_videos:
150
- try:
151
- video_src = await video.evaluate("el => el.src || ''")
152
- poster_src = await video.evaluate("el => el.poster || ''")
153
-
154
- if video_src:
155
- # Try to get title from page
156
- title = await page.title()
157
- # Check if we're on a different page now
158
- current_url = page.url
159
-
160
- result = {
161
- "url": video_src,
162
- "thumbnail": poster_src if poster_src else None,
163
- "title": title if title != "Kling AI" else None,
164
- "page_url": current_url
165
- }
166
-
167
- await browser.close()
168
- return result
169
- except Exception as e:
170
- logger.error(f"Error extracting video details: {e}")
171
- continue
172
-
173
- except Exception as e:
174
- logger.error(f"Error with element attempt {attempt+1}: {e}")
175
- continue
176
-
177
- # If we get here, we couldn't find a video after multiple attempts
178
- await browser.close()
179
- raise HTTPException(status_code=404, detail="Could not find any video with a valid source")
180
-
181
- except Exception as e:
182
- logger.error(f"Unexpected error: {e}")
183
- raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}")
184
-
185
- @app.get("/api/random-video", response_model=VideoResponse)
186
- async def get_random_video():
187
- """
188
- Endpoint to get a random video from Kling AI gallery.
189
- Returns the video URL and metadata.
190
- """
191
- try:
192
- # Fetch a random video
193
- video_info = await fetch_random_video_from_kling()
194
-
195
- # Return the video information
196
- return {
197
- "url": video_info["url"],
198
- "thumbnail": video_info.get("thumbnail"),
199
- "title": video_info.get("title"),
200
- "status": "success"
201
- }
202
- except HTTPException as e:
203
- # Re-raise HTTP exceptions
204
- raise e
205
- except Exception as e:
206
- # Log and convert other exceptions to HTTPException
207
- logger.error(f"Error in endpoint: {e}")
208
- raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}")
209
-
210
- @app.get("/")
211
- async def root():
212
- """Root endpoint with API information"""
213
- return {
214
- "name": "Kling Video Fetcher API",
215
- "version": "1.0",
216
- "endpoints": {
217
- "/api/random-video": "Get a random video URL from Kling AI gallery"
218
- }
219
- }
220
-
221
- @app.get("/health")
222
- async def health_check():
223
- """Health check endpoint"""
224
- return {"status": "healthy"}
225
-
226
- # Run the server
227
- if __name__ == "__main__":
228
  uvicorn.run("app:app", host="0.0.0.0", port=8000, reload=True)
 
1
+ from fastapi import FastAPI, HTTPException, BackgroundTasks
2
+ from fastapi.responses import JSONResponse
3
+ import asyncio
4
+ import random
5
+ import logging
6
+ from typing import List, Dict, Optional, Any
7
+ from playwright.async_api import async_playwright
8
+ import uvicorn
9
+ from pydantic import BaseModel
10
+
11
+ # Set up logging
12
+ logging.basicConfig(level=logging.INFO,
13
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
14
+ logger = logging.getLogger(__name__)
15
+
16
+ app = FastAPI(title="Kling Video Fetcher",
17
+ description="API to fetch random videos from Kling AI gallery")
18
+
19
+ # Model for the response
20
+ class VideoResponse(BaseModel):
21
+ url: str
22
+ thumbnail: Optional[str] = None
23
+ title: Optional[str] = None
24
+ status: str = "success"
25
+
26
+ # Cache to store recent video URLs
27
+ video_cache: List[Dict[str, Any]] = []
28
+ last_fetch_time = 0
29
+
30
+ async def fetch_random_video_from_kling() -> Dict[str, Any]:
31
+ try:
32
+ async with async_playwright() as p:
33
+ browser = await p.chromium.launch(headless=True, args=[
34
+ '--no-sandbox',
35
+ '--disable-setuid-sandbox',
36
+ '--disable-dev-shm-usage',
37
+ '--disable-accelerated-2d-canvas',
38
+ '--no-first-run',
39
+ '--no-zygote',
40
+ '--disable-gpu',
41
+ '--disable-web-security',
42
+ ])
43
+ context = await browser.new_context(viewport={'width': 1280, 'height': 800})
44
+ page = await context.new_page()
45
+
46
+ video_urls = []
47
+
48
+ # Intercept requests to capture video URLs
49
+ async def on_response(response):
50
+ try:
51
+ url = response.url
52
+ content_type = response.headers.get("content-type", "")
53
+ if ".mp4" in url or "video" in content_type:
54
+ video_urls.append(url)
55
+ except Exception as e:
56
+ logger.error(f"Error processing response: {e}")
57
+
58
+ page.on("response", on_response)
59
+
60
+ await page.goto("https://app.klingai.com/global/community/material", timeout=90000, wait_until="networkidle")
61
+ await page.wait_for_timeout(5000)
62
+
63
+ for _ in range(6):
64
+ await page.evaluate("window.scrollBy(0, 800)")
65
+ await page.wait_for_timeout(1500)
66
+
67
+ elements = await page.query_selector_all("video, [class*='video'], [class*='card'], [class*='media']")
68
+ elements = [e for e in elements if await e.is_visible()]
69
+ random.shuffle(elements)
70
+
71
+ for element in elements[:5]:
72
+ try:
73
+ await element.scroll_into_view_if_needed()
74
+ await page.wait_for_timeout(1000)
75
+ await element.click()
76
+ await page.wait_for_timeout(3000)
77
+
78
+ if video_urls:
79
+ video_url = video_urls[0]
80
+ title = await page.title()
81
+ return {
82
+ "url": video_url,
83
+ "thumbnail": None,
84
+ "title": title if title != "Kling AI" else None,
85
+ "status": "success"
86
+ }
87
+ except Exception as e:
88
+ logger.warning(f"Element interaction failed: {e}")
89
+
90
+ raise HTTPException(status_code=404, detail="Could not find a downloadable video")
91
+ except Exception as e:
92
+ logger.error(f"Unexpected error: {e}")
93
+ raise HTTPException(status_code=500, detail=str(e))
94
+
95
+ @app.get("/api/random-video", response_model=VideoResponse)
96
+ async def get_random_video():
97
+ """
98
+ Endpoint to get a random video from Kling AI gallery.
99
+ Returns the video URL and metadata.
100
+ """
101
+ try:
102
+ # Fetch a random video
103
+ video_info = await fetch_random_video_from_kling()
104
+
105
+ # Return the video information
106
+ return {
107
+ "url": video_info["url"],
108
+ "thumbnail": video_info.get("thumbnail"),
109
+ "title": video_info.get("title"),
110
+ "status": "success"
111
+ }
112
+ except HTTPException as e:
113
+ # Re-raise HTTP exceptions
114
+ raise e
115
+ except Exception as e:
116
+ # Log and convert other exceptions to HTTPException
117
+ logger.error(f"Error in endpoint: {e}")
118
+ raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}")
119
+
120
+ @app.get("/")
121
+ async def root():
122
+ """Root endpoint with API information"""
123
+ return {
124
+ "name": "Kling Video Fetcher API",
125
+ "version": "1.0",
126
+ "endpoints": {
127
+ "/api/random-video": "Get a random video URL from Kling AI gallery"
128
+ }
129
+ }
130
+
131
+ @app.get("/health")
132
+ async def health_check():
133
+ """Health check endpoint"""
134
+ return {"status": "healthy"}
135
+
136
+ # Run the server
137
+ if __name__ == "__main__":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  uvicorn.run("app:app", host="0.0.0.0", port=8000, reload=True)