diff --git a/downloader.py b/downloader.py index 8d995faf..1282e0ae 100644 --- a/downloader.py +++ b/downloader.py @@ -1852,7 +1852,7 @@ def _tickzoo_extract_video_links_from_html(html: str) -> list: return video_links -async def _tickzoo_scrape_tag_playlist(playlist_url: str, scraper, queue, counter, overall_bar): +async def _tickzoo_scrape_tag_playlist(playlist_url: str, cookies, scraper, queue, counter, overall_bar): """Scrape all video URLs across pages from a tickzoo.tv tag or category playlist.""" seen_videos = set() curr_url = playlist_url @@ -1860,7 +1860,7 @@ async def _tickzoo_scrape_tag_playlist(playlist_url: str, scraper, queue, counte while curr_url: log_info(f"Scraping tag page {page_num}: {curr_url}", indent=1) - html = await asyncio.to_thread(scraper_core.curl_fetch, curr_url, referer="https://tickzoo.tv/") + html = await asyncio.to_thread(scraper_core.curl_fetch, curr_url, cookies=cookies, referer="https://tickzoo.tv/") if not html: log_warn(f"Static fetch returned empty/blocked. Trying browser for tag page {page_num}...", indent=2) page = await scraper.new_page() @@ -1907,13 +1907,13 @@ async def _tickzoo_scrape_tag_playlist(playlist_url: str, scraper, queue, counte break -async def _tickzoo_producer(urls, scraper, queue, counter, overall_bar): +async def _tickzoo_producer(urls, cookies, scraper, queue, counter, overall_bar): """Feed direct video URLs or scrape tag playlists dynamically into the queue.""" for url in urls: if _tickzoo_is_tag_or_playlist(url): log_info(f"Scraping tag archive: {url}", indent=1) try: - await _tickzoo_scrape_tag_playlist(url, scraper, queue, counter, overall_bar) + await _tickzoo_scrape_tag_playlist(url, cookies, scraper, queue, counter, overall_bar) except Exception as e: log_error(f"Error scraping tag {url}: {e}", indent=1) elif _tickzoo_is_video_link(url): @@ -1928,7 +1928,7 @@ async def _tickzoo_producer(urls, scraper, queue, counter, overall_bar): await asyncio.sleep(random.uniform(0.3, 0.8)) -async def _tickzoo_worker(queue, scraper, download_dir, skip_existing, overall_bar, bar_pool): +async def _tickzoo_worker(queue, cookies, scraper, download_dir, skip_existing, overall_bar, bar_pool): """Worker processing video URLs sequentially or concurrently with shared browser.""" while True: url = await queue.get() @@ -1936,7 +1936,7 @@ async def _tickzoo_worker(queue, scraper, download_dir, skip_existing, overall_b queue.task_done() break try: - await _tickzoo_process_one(scraper, url, download_dir, skip_existing, overall_bar, bar_pool) + await _tickzoo_process_one(scraper, url, cookies, download_dir, skip_existing, overall_bar, bar_pool) except Exception as e: log_error(f"Error processing {url}: {e}", indent=1) overall_bar.update(1) @@ -1949,15 +1949,18 @@ async def _tickzoo_worker(queue, scraper, download_dir, skip_existing, overall_b def _tickzoo_extract_embed(html: str) -> str: """Pull the video iframe src out of the ", html, re.S | re.I) + if not m: + # Also check any textarea containing iframe + m = re.search(r"]*>(.*?<iframe.*?)", html, re.S | re.I) if not m: return "" - inner = m.group(1) + inner = unescape(m.group(1)) m = re.search(r"]*\bsrc\s*=\s*[\"']([^\"']+)[\"']", inner, re.I) if not m: m = re.search(r"]*\bsrc\s*=\s*([^\"'>\s]+)", inner, re.I) if not m: return "" - src = unescape(m.group(1).strip()) + src = m.group(1).strip() if any(ad in src.lower() for ad in _TICKZOO_AD_HOSTS): return "" return src @@ -2003,13 +2006,13 @@ async def _tickzoo_resolve_media(scraper, embed_url: str, referer_url: str) -> s """Resolve the direct media URL from a tickzoo embed host via headless Chrome. Handles every embed host seen on tickzoo.tv: - * firestream.to -> POST /api/videos//resolve returns JSON - {signedVideoUrl: "", ...} - * hgcloud.to -> HLS master manifest fires as a network response (jwplayer) - * rubyvidhub.com -> HLS master manifest fires as a network response - * veev.to -> the mp4 URL lives in