- Scraper DataLife Engine : recherche AJAX, fiches par saison, épisodes via ep-data.php (VF/VOSTFR), films via film_api.php, nouveautés /series/ - Config YAML externalisée (sélecteurs réparables sans coder) - Domaines étendus : uqload.vc, vidzy.cc/.live - 11 tests (126 au total)
46 lines
1.7 KiB
Python
46 lines
1.7 KiB
Python
"""Extracteur Uqload (uqload.to/.co/.com/.io/.vc) — page embed → mp4/m3u8.
|
|
|
|
La page embed contient un jwplayer configuré dans du JS packé
|
|
(p,a,c,k,e,d) : `sources:[{file:"https://.../master.m3u8?..."}]`.
|
|
On dépacke puis on extrait par regex.
|
|
"""
|
|
|
|
import logging
|
|
import re
|
|
|
|
from app.scrapers.base import HosterExtractor, ScrapeError, VideoLink, register_hoster
|
|
from app.scrapers.hosters._packer import unpack_packed_js
|
|
from app.scrapers.http import fetch
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_PATTERNS = (
|
|
re.compile(r'sources\s*:\s*\[\s*\{[^}]*?(?:file|src)\s*:\s*["\'](?P<url>[^"\']+)["\']'),
|
|
re.compile(r'(?:file|src)\s*:\s*["\'](?P<url>https?://[^"\']+?\.(?:m3u8|mp4)[^"\']*)["\']'),
|
|
re.compile(r'["\'](?P<url>https?://[^"\']*?\.(?:m3u8|mp4)(?:\?[^"\']*)?)["\']'),
|
|
)
|
|
|
|
|
|
@register_hoster
|
|
class UqloadExtractor(HosterExtractor):
|
|
name = "uqload"
|
|
domains = ("uqload.to", "uqload.co", "uqload.com", "uqload.io", "uqload.vc")
|
|
|
|
async def extract(self, embed_url: str) -> VideoLink:
|
|
html = await fetch(embed_url)
|
|
candidates: list[str] = []
|
|
for content in (html, unpack_packed_js(html) or ""):
|
|
for pattern in _PATTERNS:
|
|
for match in pattern.finditer(content):
|
|
candidates.append(match.group("url"))
|
|
video = [u for u in candidates if re.search(r"\.(mp4|m3u8)(\?|$)", u)]
|
|
url = next((u for u in video if ".mp4" in u), None) or (video[0] if video else None)
|
|
if not url:
|
|
raise ScrapeError(f"uqload : URL vidéo introuvable dans {embed_url}")
|
|
return VideoLink(
|
|
url=url,
|
|
hoster=self.name,
|
|
headers={"Referer": embed_url},
|
|
is_hls=".m3u8" in url,
|
|
)
|