fix(musicseerr): implement session-based conversion triggering and polling in Tubidy scraper
Build and Push Docker Images / deploy (push) Blocked by required conditions
Details
Build and Push Docker Images / build (api) (push) Successful in 1m14s
Details
Build and Push Docker Images / build (musicseerr) (push) Successful in 6m26s
Details
Build and Push Docker Images / build (web) (push) Successful in 2m11s
Details
Build and Push Docker Images / build (nextgen) (push) Successful in 9m49s
Details
Build and Push Docker Images / build (worker) (push) Has been cancelled
Details
Build and Push Docker Images / deploy (push) Blocked by required conditions
Details
Build and Push Docker Images / build (api) (push) Successful in 1m14s
Details
Build and Push Docker Images / build (musicseerr) (push) Successful in 6m26s
Details
Build and Push Docker Images / build (web) (push) Successful in 2m11s
Details
Build and Push Docker Images / build (nextgen) (push) Successful in 9m49s
Details
Build and Push Docker Images / build (worker) (push) Has been cancelled
Details
This commit is contained in:
parent
732f71700c
commit
0bf96f0213
|
|
@ -148,6 +148,7 @@ def search_tubidy(query: str, proxy_url: str) -> list:
|
||||||
def get_tubidy_download_link(content_id: str, proxy_url: str) -> str:
|
def get_tubidy_download_link(content_id: str, proxy_url: str) -> str:
|
||||||
"""
|
"""
|
||||||
Queries watch.php for the given content ID to find the direct MP3 download URL.
|
Queries watch.php for the given content ID to find the direct MP3 download URL.
|
||||||
|
Supports initiating and polling the conversion process if the video is not yet processed.
|
||||||
"""
|
"""
|
||||||
proxies = {"http": proxy_url, "https": proxy_url} if proxy_url else None
|
proxies = {"http": proxy_url, "https": proxy_url} if proxy_url else None
|
||||||
headers = {
|
headers = {
|
||||||
|
|
@ -166,23 +167,64 @@ def get_tubidy_download_link(content_id: str, proxy_url: str) -> str:
|
||||||
|
|
||||||
logger.info(f"Fetching watch.php for content ID '{content_id}'")
|
logger.info(f"Fetching watch.php for content ID '{content_id}'")
|
||||||
try:
|
try:
|
||||||
response = cf_requests.get(watch_url, headers=headers, params=params, proxies=proxies, impersonate="chrome", timeout=15)
|
session = cf_requests.Session()
|
||||||
|
if proxies:
|
||||||
|
session.proxies = proxies
|
||||||
|
session.headers.update(headers)
|
||||||
|
|
||||||
|
response = session.get(watch_url, params=params, impersonate="chrome", timeout=15)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
soup = BeautifulSoup(response.text, "html.parser")
|
def extract_link(html: str) -> str:
|
||||||
for li in soup.find_all("li", class_=lambda x: x and "list-group-item" in x and "big" in x):
|
soup = BeautifulSoup(html, "html.parser")
|
||||||
a_tag = li.find("a")
|
# 1. Search in list-group-item big tags
|
||||||
if a_tag:
|
for li in soup.find_all("li", class_=lambda x: x and "list-group-item" in x and "big" in x):
|
||||||
|
a_tag = li.find("a")
|
||||||
|
if a_tag:
|
||||||
|
text = a_tag.text.lower()
|
||||||
|
href = a_tag.get("href")
|
||||||
|
if href and "download" in text:
|
||||||
|
return urljoin(watch_url, href)
|
||||||
|
# 2. General fallback search for direct download/mp3 links
|
||||||
|
for a_tag in soup.find_all("a", href=True):
|
||||||
text = a_tag.text.lower()
|
text = a_tag.text.lower()
|
||||||
href = a_tag.get("href")
|
href = a_tag["href"]
|
||||||
if href and "download" in text:
|
if "download" in text and "act=process" not in href and "act=down" not in href:
|
||||||
return href
|
return urljoin(watch_url, href)
|
||||||
|
if (".mp3" in href.lower() or "video.mp3.tubidy.cool" in href.lower()) and "act=process" not in href:
|
||||||
# Fallback to general scraping of the watch.php page if structure differs
|
return urljoin(watch_url, href)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
link = extract_link(response.text)
|
||||||
|
if link:
|
||||||
|
return link
|
||||||
|
|
||||||
|
# If no link found, check if there is a process link
|
||||||
|
soup = BeautifulSoup(response.text, "html.parser")
|
||||||
|
process_link = None
|
||||||
for a_tag in soup.find_all("a", href=True):
|
for a_tag in soup.find_all("a", href=True):
|
||||||
text = a_tag.text.lower()
|
if "act=process" in a_tag["href"]:
|
||||||
if "download" in text and "act=process" not in a_tag["href"]:
|
process_link = urljoin(watch_url, a_tag["href"])
|
||||||
return a_tag["href"]
|
break
|
||||||
|
|
||||||
|
if process_link:
|
||||||
|
logger.info(f"Triggering Tubidy processing step for content ID '{content_id}' via {process_link}")
|
||||||
|
proc_resp = session.get(process_link, impersonate="chrome", timeout=15)
|
||||||
|
proc_resp.raise_for_status()
|
||||||
|
|
||||||
|
# Wait for conversion (typically takes 5-10s on Tubidy server)
|
||||||
|
import time
|
||||||
|
wait_time = 10
|
||||||
|
logger.info(f"Waiting {wait_time} seconds for conversion to finish...")
|
||||||
|
time.sleep(wait_time)
|
||||||
|
|
||||||
|
# Re-fetch the download page
|
||||||
|
response = session.get(watch_url, params=params, impersonate="chrome", timeout=15)
|
||||||
|
response.raise_for_status()
|
||||||
|
link = extract_link(response.text)
|
||||||
|
if link:
|
||||||
|
return link
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to fetch download link for {content_id}: {e}")
|
logger.error(f"Failed to fetch download link for {content_id}: {e}")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue