QJMKWB2 / scraper5.py
QJMKWB's picture
Update scraper5.py
804e7ad verified
import asyncio
import urllib.parse
import json
from playwright.async_api import async_playwright
from bs4 import BeautifulSoup
import re
from xray_manager import setup_and_start_xray
DOMENA = "https://mrkaj.me"
class XrayBrowserManager:
_instance = None
def __init__(self):
self.playwright = None
self.context = None
self._setup_done = False
self._lock = asyncio.Lock()
@classmethod
def get_instance(cls):
if cls._instance is None: cls._instance = cls()
return cls._instance
async def start(self):
async with self._lock:
if self._setup_done: return
setup_and_start_xray()
self.playwright = await async_playwright().start()
self.context = await self.playwright.chromium.launch_persistent_context(
"/tmp/xray_profile",
headless=True,
proxy={"server": "socks5://127.0.0.1:10808"},
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
)
# --- OVERENIE IP ADRESY ---
test_page = await self.context.new_page()
try:
print("[DEBUG] Overujem IP cez tunel...")
await test_page.goto("https://api.ipify.org", timeout=15000)
ip = await test_page.inner_text("body")
print(f"[DEBUG] Tvoja IP v tuneli je: {ip}")
except Exception as e:
print(f"[DEBUG ERROR] Tunel nefunguje: {e}")
finally:
await test_page.close()
# ---------------------------
self._setup_done = True
async def get_page(self):
if not self._setup_done: await self.start()
return await self.context.new_page()
manager = XrayBrowserManager.get_instance()
async def search_movies(query):
page = await manager.get_page()
try:
url = f"{DOMENA}/se/j/json?q={urllib.parse.quote(query)}"
print(f"[TUNNEL] Vyhľadávam: {query}")
# Otestujeme aj klasickú HTML stránku, či nás pustí
await page.goto(url, wait_until="networkidle", timeout=30000)
# Získame surový obsah
raw_content = await page.content()
print(f"[DEBUG] Surová dĺžka obsahu: {len(raw_content)}")
if len(raw_content) < 200:
print(f"[DEBUG] POZOR! Web vrátil podozrivo málo dát: {raw_content}")
content = await page.evaluate("() => document.body.innerText")
return json.loads(content)
except Exception as e:
print(f"[SEARCH ERROR] {e}")
return []
finally: await page.close()
async def get_details(slug, media_type):
page = await manager.get_page()
url = f"{DOMENA}/p/{slug}" if media_type in ["movie", "film"] else f"{DOMENA}/tv/{slug}/S01E01"
res = {"languages": [], "seasons": []}
try:
await page.goto(url, timeout=30000)
soup = BeautifulSoup(await page.content(), "html.parser")
kw = soup.find("div", class_="movie-keyword")
if kw: res["languages"] = [p.get_text(strip=True) for p in kw.find_all(recursive=False)]
matches = re.findall(r'Séria\s+(\d+)', soup.get_text())
for s in sorted(set(matches), key=int): res["seasons"].append({"season": int(s), "episodes": 0})
except: pass
finally: await page.close()
return res
async def get_stream_url(slug, media_type, season=None, episode=None, lang=None, source_idx=0):
print(f"[STREAM] Skenujem stream: {slug} (Zdroj: {source_idx})")
page = await manager.get_page()
# Príprava URL
url = f"{DOMENA}/p/{slug}" if media_type in ["movie", "film"] else f"{DOMENA}/tv/{slug}/S{int(season):02d}E{int(episode):02d}"
url += f"?source={source_idx}"
if lang: url += f"&lng={urllib.parse.quote(lang)}"
found = {"stream": None, "vtt": None}
# Interceptor na zachytávanie sieťovej komunikácie
async def handle_request(request):
u = request.url
if (".m3u8" in u or ".mp4" in u) and not found["stream"]:
if "master.m3u8" not in u:
# Filtrujeme reklamy, chceme len reálne streamy
if "ads" not in u and "google" not in u:
print(f"[ZACHYTENÉ VIDEO] {u[:80]}...")
found["stream"] = u
if u.endswith(".vtt") and not found["vtt"]:
found["vtt"] = u
page.on("request", handle_request)
try:
# 1. Načítame stránku (predĺžený timeout na 60s kvôli tunelu)
await page.goto(url, wait_until="domcontentloaded", timeout=60000)
# 2. Skúsime počkať, či sa stream nespustí sám
for _ in range(15):
if found["stream"]: break
await asyncio.sleep(1)
# 3. Ak stále nič, skúsime KLIKNÚŤ na stred prehrávača
if not found["stream"]:
print("[STREAM] Video sa nenačítalo samo, skúšam KLIK na stred...")
# Hľadáme iframe alebo video element
locators = ["iframe#frm", "iframe[src*='api']", "video", ".play-button"]
for loc in locators:
target = page.locator(loc).first
if await target.count() > 0:
try:
# Klikneme presne na stred elementu
await target.click(force=True, timeout=5000)
await asyncio.sleep(2)
if found["stream"]: break
except: continue
# 4. Finálne čakanie
for _ in range(15):
if found["stream"]: break
await asyncio.sleep(1)
except Exception as e:
print(f"[STREAM ERROR] {e}")
finally:
await page.close()
return found
def zachyt(req, found):
if ".m3u8" in req.url and not found["stream"]:
print("[Zachytený stream neoverený]",req.url)
print("[stav zoznamu]",found)
if "master.m3u8" not in req.url:
found["stream"] = req.url
if req.url.endswith(".vtt") and not found["vtt"]: found["vtt"] = req.url