- hqfap + 4k69: both ingested fresh but playback is dead (hqfap serves a fixed ~3MB "server down" stub for every scene; 4k69 resolves no playable URL). Removed from ALL_BROWSE_SCRAPERS so no new dead sources get ingested; existing live playback_sources marked dead in prod (scenes drop out of has_playback / Sites). Extractors kept in registry for easy re-enable if the hosts recover. - latestpornvideo: was a performer-search scraper, so it never picked up the site's "latest" feed — users saw a stale set. Converted to a browse scraper reading /page/N/ (studio+date from title/thumb, category tags; performers via canonical merge). Moved DIRECT → BROWSE list. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
250 lines
17 KiB
Python
250 lines
17 KiB
Python
"""Direct tube scrapers.
|
|
|
|
Każdy scraper hit'uje tube bezpośrednio HTTPm — różne tube'y to różne rate limit
|
|
budgets, więc mogą iść równolegle. Wszystkie feedują sceny do tej samej
|
|
`Source(name=SCRAPER_SOURCE_NAME)` z external_id `f"{sitetag}:{url}"`. Resolver
|
|
mergeuje idempotentnie po tym kluczu.
|
|
|
|
Nazwa źródła: do 2026-06-07 brzmiała `"pornapp"` — myląca pozostałość po usuniętym
|
|
zewnętrznym porn-app API (sugerowała zależność od obcego serwisu, której NIE MA —
|
|
to nasze własne direct-scrapery tubów). Przemianowana na `"tube-scraper"`; wiersz
|
|
`sources` zaktualizowany w DB (UPDATE name) więc cała historia ingest_runs została.
|
|
|
|
Search-based ścieżka (per performer name); category browse'ng przez `categoriesUrl`.
|
|
|
|
UWAGA — speculative scrapers: większość aggregator + special tubes (xmoviesforyou,
|
|
watchporn, siska, porn4days, porndish, xxxfreewatch, latestleaks, mypornerleak,
|
|
porndittcom, perverzija, fpoxxx, ...) ma URL templates + regex'y oparte na typowych
|
|
WordPress conventions. Wymagają post-deploy verification — gdy któryś nie zwraca
|
|
wyników, sprawdź real search HTML + popraw template/regex w odpowiednim pliku.
|
|
"""
|
|
# Umbrella Source.name dla wszystkich direct-scraperów (deep-crawl, browse-latest,
|
|
# performer-driven). Rename z legacy "pornapp" 2026-06-07 (mylące — nie ma zależności
|
|
# od zewnętrznego porn-app API).
|
|
SCRAPER_SOURCE_NAME = "tube-scraper"
|
|
|
|
from app.connectors.direct_scrapers._browse_base import BaseBrowseScraper
|
|
from app.connectors.direct_scrapers.base import BaseDirectTubeScraper
|
|
from app.connectors.direct_scrapers.eporner import EpornerScraper
|
|
from app.connectors.direct_scrapers.fpoxxx import FpoxxxScraper
|
|
from app.connectors.direct_scrapers.hdporn92 import HDPorn92Scraper # noqa: F401 — kept for backref; disabled
|
|
from app.connectors.direct_scrapers.hqporner import HQPornerScraper
|
|
from app.connectors.direct_scrapers.latestleaks import LatestLeaksScraper
|
|
from app.connectors.direct_scrapers.latestpornvideo import LatestPornVideoScraper
|
|
from app.connectors.direct_scrapers.mypornerleak import MyPornerLeakScraper
|
|
from app.connectors.direct_scrapers.perverzija import PerverzijaScraper
|
|
from app.connectors.direct_scrapers.porn4days import Porn4DaysScraper
|
|
from app.connectors.direct_scrapers.pornditt import PornDittScraper
|
|
from app.connectors.direct_scrapers.porndish import PornDishScraper
|
|
from app.connectors.direct_scrapers.pornhat import PornHatScraper # noqa: F401 — kept for backref; ingest disabled
|
|
from app.connectors.direct_scrapers.pornhub import PornHubScraper
|
|
from app.connectors.direct_scrapers.porntrex import PornTrexScraper
|
|
from app.connectors.direct_scrapers.redtube import RedTubeScraper
|
|
from app.connectors.direct_scrapers.siska import SiskaScraper
|
|
from app.connectors.direct_scrapers.sxyland import SxyLandScraper
|
|
from app.connectors.direct_scrapers.sxyprn import SxyPrnScraper
|
|
from app.connectors.direct_scrapers.watchporn import WatchPornScraper
|
|
from app.connectors.direct_scrapers.xhamster import XHamsterScraper
|
|
from app.connectors.direct_scrapers.xmoviesforyou import XMoviesForYouScraper
|
|
from app.connectors.direct_scrapers.xnxx import XnxxScraper
|
|
from app.connectors.direct_scrapers.xvideos import XVideosScraper
|
|
from app.connectors.direct_scrapers.xxxfreewatch import XxxFreeWatchScraper # noqa: F401 — kept for backref; delisted
|
|
from app.connectors.direct_scrapers.youporn import YouPornScraper
|
|
from app.connectors.direct_scrapers.zerodayxx import ZeroDayXXScraper
|
|
|
|
ALL_DIRECT_SCRAPERS: list[type[BaseDirectTubeScraper]] = [
|
|
# Existing 4 (verified, in production)
|
|
HQPornerScraper,
|
|
# HDPorn92Scraper — wyłączony 2026-05-18. Scene pages to SEO shell: ZERO player iframe
|
|
# (tylko happyleafmotion ads), JS hijackuje wszystkie kliki → `go.rmishe.com/smartpop/...`
|
|
# popunder redirect. Mobile WebView page-as-hoster pokazuje ad redirect zamiast video.
|
|
# 33,598 playback_sources mass-marked dead, 27,374 solo-orphan scenes deleted.
|
|
SxyLandScraper,
|
|
# ZeroDayXXScraper — wyłączony 2026-05-12 (source quality report): 25,596 scen, 0.1% canonical
|
|
# match. Slug-concat tytuły (`bella reese big butt ready to be filled with cum analized`) bez
|
|
# `[Studio]` lub `Studio - Perf - Title` prefixu (parse rate 3%) → resolver nie ma żadnego
|
|
# signalu do matchu. Wraps watchporn ale dziedziczy stripped metadata. Solo orphany usunięte
|
|
# (~21k scen) — plik scrapera + extractor zostają (istniejące playback_sources nadal się
|
|
# resolvują).
|
|
# Mainstream (URL templates well-known)
|
|
# PornHubScraper — wyłączony 2026-05-12 (analiza źródeł): 23,750 scen scrapnietych,
|
|
# tylko 105 (0.4%) match z TPDB/StashDB. PH hostuje głównie własne shortened
|
|
# clipy + amateur upload — nigdy nie zmatchują studio canonical content. Plik
|
|
# zostaje (extractor `pornhubcom` używa go w playback resolve dla istniejących
|
|
# playback_sources).
|
|
# RedTubeScraper — wyłączony 2026-05-12 (analiza źródeł): 20,127 scen, 82 match
|
|
# (0.4%). Same powody co PH (skrócone clipy + amateur upload).
|
|
XVideosScraper,
|
|
XnxxScraper,
|
|
XHamsterScraper,
|
|
YouPornScraper,
|
|
PornTrexScraper,
|
|
EpornerScraper,
|
|
# Aggregators (WordPress-like ?s= search; speculative — verify post-deploy)
|
|
# XMoviesForYouScraper — wyłączony 2026-05-12 (post audit fix). 100% scen serwuje
|
|
# streamtape (DEAD_HOSTER_RE — malware drive-by .reg) + opcjonalnie playmogo/mixdrop.
|
|
# Mixdrop zrebrandował na m1xdrop.bz, yt-dlp out-of-date, packer/JS extract = fail.
|
|
# Playmogo = DoodStream CAPTCHA. Porn-app sam olewa xmoviesforyou (brak handlera w
|
|
# jadx). 1,321 solo-orphan scen.
|
|
# WatchPornScraper — wyłączony 2026-05-12 (user bug-report). Wszystkie iframes to
|
|
# DoodStream variants (playmogo/d0000d/dooood/mivalyo) z CAPTCHA gate. WebView na
|
|
# mobile = black screen (player JS nie inicjalizuje się przez Turnstile). 16%
|
|
# scen solo (no backup tube), 84% multi-source — user może użyć innego tube. yt-dlp
|
|
# nie wspiera DoodStream ("Piracy"), własny resolver TBD jeśli warto.
|
|
# SiskaScraper — przeniesiony do ALL_BROWSE_SCRAPERS (browse-konwersja 2026-06-20,
|
|
# bo search siski zepsuty site-side — `?s=` ignoruje query). Patrz siska.py.
|
|
# Porn4DaysScraper — wyłączony 2026-05-12 (post audit fix). 100% scen na streamtape
|
|
# only (DEAD_HOSTER_RE blacklist - malware drive-by .reg downloads). SERVER1_URL =
|
|
# streamtape, brak SERVER2/SERVER3 backup. Porn-app sam olewa porn4days. 10,346
|
|
# solo-orphan scen.
|
|
PornDishScraper,
|
|
# XxxFreeWatchScraper — wyłączony 2026-05-18. 790 scen, 0% canonical match, 100% solo-orphan.
|
|
# Cloudflare 403 z VPS IP, mobile WebView teoretycznie działa ale 0/790 scen miało jakikolwiek
|
|
# match do TPDB/StashDB. Pure orphan factory. Solo scenes deleted, scraper disabled.
|
|
# LatestPornVideoScraper — przeniesiony do ALL_BROWSE_SCRAPERS (browse-konwersja 2026-06-22,
|
|
# user 1da0375e: search-driven nie brał feedu "latest" → stary zestaw w apce).
|
|
# LatestLeaksScraper — wyłączony 2026-05-12 (source quality report): 16,438 scen, 0.0%
|
|
# canonical match. Slug-concat tytuły, brak studio/duration/date signali. Solo orphany
|
|
# usunięte (~15k scen).
|
|
MyPornerLeakScraper,
|
|
# Added 2026-05-12 (theporndude survey): jeden z 14 free tubes na liście który
|
|
# zwraca consistent search results. KVS engine, slug-aware scene URLs. Mostly
|
|
# orphan ingest (auto-screenshots, no canonical phash match — sprawdzone), ale
|
|
# może łapać sceny popularnych performerów których jeszcze nie mamy w TPDB.
|
|
# PornHatScraper — wyłączony 2026-05-18. 9,799 scen, 0.2% canonical match, 100% solo-orphan.
|
|
# Pure orphan factory — auto-screenshot thumbs nie matchują phash do canonical, slug tytuły
|
|
# nie matchują rapidfuzz, brak duration/date signals. KEEP `pornhatcom` extractor i istniejące
|
|
# playback_sources żywe — mobile może je odtwarzać; disable tylko future ingest.
|
|
# PornDittScraper — wyłączony 2026-05-12 (bug-report 64356e9b). Każdy link
|
|
# produkował nową Scene row zamiast matchować do istniejącej kanonicznej
|
|
# (TPDB/StashDB) bo pornditt ma weak signal: title + cz. performera, brak
|
|
# fingerprintu/duration/date → composite_score zawsze poniżej auto_merge
|
|
# threshold (0.92). Plik scrapera + extractor zostają (istniejące playback_sources
|
|
# nadal się resolvują, _REGISTRY w app/extractors/__init__.py odpala
|
|
# `porndittcom` → _embed_iframe.extract). Re-enable wymaga albo
|
|
# "alternative-source mode" w resolverze (match-only, never create new),
|
|
# albo bogatszej extracji metadanych (duration + fingerprint).
|
|
# Special
|
|
SxyPrnScraper,
|
|
PerverzijaScraper,
|
|
FpoxxxScraper,
|
|
]
|
|
|
|
# Browse-mode scrapers — iterują `latest-vids` listing zamiast search-by-performer.
|
|
# Phash thumbnail fingerprint (waga 0.40 w composite scoring) auto-mergeuje do
|
|
# canonical (TPDB/StashDB) gdy tube hot-linkuje studio thumbnail. Schedulowane
|
|
# raz dziennie, pages 1-5. Patrz `_browse_base.BaseBrowseScraper` +
|
|
# `app/scheduler/browse_latest.py`.
|
|
#
|
|
# **Pilot results (2026-05-12):**
|
|
# - ShyfapScraper: 0/23 match (0%) — robi własne thumbnails ≠ canonical
|
|
# (phash Hamming 12-16). Plus rebranduje tytuły. **Wyłączony.**
|
|
# - FreshpornoScraper: 39/59 match (66%) — hot-linkuje studio thumbnaile
|
|
# (phash Hamming 0). Oryginalne tytuły + channels=studio 1:1. **Aktywny.**
|
|
from app.connectors.direct_scrapers.freshporno import FreshpornoScraper # noqa: E402
|
|
from app.connectors.direct_scrapers.porn00 import Porn00Scraper # noqa: E402
|
|
from app.connectors.direct_scrapers.porndoe import PornDoeScraper # noqa: E402
|
|
from app.connectors.direct_scrapers.pornxp import PornXPScraper # noqa: E402
|
|
from app.connectors.direct_scrapers.shyfap import ShyfapScraper # noqa: E402, F401
|
|
from app.connectors.direct_scrapers.yesporn import YesPornVipScraper # noqa: E402
|
|
from app.connectors.direct_scrapers.fullmovies import FullmoviesScraper # noqa: E402
|
|
from app.connectors.direct_scrapers.hdporngg import HDPornGGScraper # noqa: E402
|
|
from app.connectors.direct_scrapers.fourk69 import FourK69Scraper # noqa: E402,F401 — disabled 2026-06-22 (broken playback), kept for backref/re-enable
|
|
from app.connectors.direct_scrapers.hqfap import HQFapScraper # noqa: E402,F401 — disabled 2026-06-22 (broken playback), kept for backref/re-enable
|
|
from app.connectors.direct_scrapers.neporn import NepornScraper # noqa: E402
|
|
from app.connectors.direct_scrapers.superporn import SuperpornScraper # noqa: E402
|
|
from app.connectors.direct_scrapers.eporner_api import EpornerApiScraper # noqa: E402
|
|
from app.connectors.direct_scrapers.xvideos_browse import XVideosBrowseScraper # noqa: E402
|
|
|
|
ALL_BROWSE_SCRAPERS: list[type[BaseBrowseScraper]] = [
|
|
FreshpornoScraper,
|
|
# LatestPornVideoScraper — browse od 2026-06-22 (user 1da0375e: search-driven
|
|
# nie brał feedu "latest"). Listing card: tytuł (z embedded "<Studio> YY MM DD"),
|
|
# thumb (studio+date w nazwie), category-* jako tag. Performerów listing nie ma
|
|
# czysto (brak `actors-*`) → puste, dorabia canonical-merge. Playback: luluvid
|
|
# iframe → extractor latestpornvideocom (_embed_iframe) → telefon resolwuje.
|
|
LatestPornVideoScraper,
|
|
# SiskaScraper — re-enabled 2026-06-20 jako browse (user fa4083a2). Search siski
|
|
# zepsuty site-side (`?s=` ignoruje query), więc latest-browse z `/page/<n>/`.
|
|
# Komplet metadanych z kafelka listingu (tytuł/duration/thumb/performer/studio/
|
|
# kategoria). Playback: playmogo + luluvid → telefon resolwuje phone-side.
|
|
SiskaScraper,
|
|
# PornXPScraper — pilot 2026-05-17 (20 scen): studio 100%, performer 95%,
|
|
# release_date 100%, duration 100%, stream_url 100%, phash 100%. Najlepsze
|
|
# sygnały spośród browse-mode scraperów. Stream direct mp4 (sv.porn-xp.com)
|
|
# 360/720 quality. Release year z `Released: <year>` na detail.
|
|
PornXPScraper,
|
|
# Porn00Scraper — pilot 2026-05-17 (16 scen): brak studio (0%) + brak release
|
|
# date (0%) ALE performer 100%, duration 100%, stream_url 100% (KVS video_alt_url
|
|
# 720p). Tytuł zachowuje studio prefix ("Studio Title - Scene Name") → title
|
|
# fuzzy match (rapidfuzz token_set_ratio) może załapać canonical. Monitorować.
|
|
Porn00Scraper,
|
|
# PornDoeScraper — dołączony 2026-05-21 (theporndude audit). Każda scena ma
|
|
# kompletny JSON-LD VideoObject: title + uploadDate + duration + named studio
|
|
# (producer/publisher) + named performers (actor[]) + thumbnail. Najbogatsze
|
|
# strukturalne metadane spośród browse scraperów — composite fuzzy match ma
|
|
# komplet sygnałów. Phash hit-rate niski (własne crop-thumbnaile), studio +
|
|
# performer + date + duration nadrabiają.
|
|
PornDoeScraper,
|
|
# YesPornVipScraper — dołączony 2026-05-27 (user audit). JSON-LD VideoObject
|
|
# + `<meta property="video:duration|release_date|tag">` per scena (Goon ma
|
|
# duration w sekundach gotowe + ISO 8601 release_date z timezone). Studio +
|
|
# performerzy z `btn gold` linków (`/channels/<slug>/` + `/models/<slug>/`).
|
|
# 941k organic monthly (SE Ranking, comparable z porndoe 731k / porntrex 790k).
|
|
# Scraper-of-paysites (DogFart / HardX / TeamSkeet / Vixen) — wysokie expected
|
|
# canonical match dla studio scenes. Korekta: theporndude scorecard rank 26
|
|
# ('yespornvip.com', score -0.5, auth wall) dotyczył **innej domeny** — pdude.link
|
|
# redirect do porndudecams affiliate. Prawdziwa kanoniczna domena to TLD `.vip`.
|
|
YesPornVipScraper,
|
|
# FullmoviesScraper + HDPornGGScraper — dołączone 2026-06-01. KVS engine (sponsor_groups
|
|
# stack, `/videos/<slug>/` + `/latest-updates/`). Studio teraz z PREFIKSU tytułu
|
|
# ("Studio - Scene") — sidebar `/networks/` listował WSZYSTKIE sieci, więc pierwszy match
|
|
# zawsze Brazzers (mis-attribution, dlatego nigdy nie były włączone). Niosą paysite studio
|
|
# content (TeamSkeet/Dad Crush/Brazzers/...) z title+performer+duration → composite fuzzy.
|
|
# Nawet bez canonical match: grywalny content z inferred tagami (mission: daily tagged ingest).
|
|
FullmoviesScraper,
|
|
HDPornGGScraper,
|
|
# EpornerApiScraper — dołączony 2026-06-03 (Faza 2b alternatywa). eporner detail to
|
|
# JS-heavy KVS bez SSR metadanych (jak porntrex/hqporner — odrzucone), ALE eporner ma
|
|
# publiczne JSON API (api/v2/video/search): 1 call = 100 filmów z title+length_sec+
|
|
# keywords+added+thumb. ~100k filmów, deep-crawl przez crawl_page() (API, bez detail-fetch).
|
|
EpornerApiScraper,
|
|
# XVideosBrowseScraper — dołączony 2026-06-03. SSR JSON-LD (duration/title/uploadDate)
|
|
# + page-parse /models/ (performerzy) + /tags/. Sample: median ~10.5min, 93% ≥3min.
|
|
# Mega-katalog ~13M → deep_crawl._PAGE_CAP["xvideoscom"]=1800 (~50k najnowszych), nie
|
|
# full-crawl. (youporn pominięty — JSON-LD bez actor/keywords, scene-perf/tagi = nav A-Z.)
|
|
XVideosBrowseScraper,
|
|
# HQFapScraper / FourK69Scraper — WYŁĄCZONE 2026-06-22 (user request, na razie).
|
|
# Oba na PlayTube CMS, ingestowały świeżo i wyglądały żywo, ALE playback w obu padł:
|
|
# - hqfap: hosting migrował na `/upload/videos/video_down.mp4` = STAŁY ~3MB stub
|
|
# "server down" dla KAŻDEJ sceny (extractor go odrzuca → None),
|
|
# - 4k69: get_file nie zwraca już grywalnego URL (extractor resolves nothing → None).
|
|
# Scena bez grywalnego źródła = śmieciowy wpis, więc nie ingestujemy nowych. Istniejące
|
|
# live playback_sources oznaczone dead na prodzie (znikają z /sources + has_playback).
|
|
# Reversible: odkomentuj + odżyw sources gdy hosting wróci. Extractory zostają w
|
|
# _REGISTRY (hqfapcom/4k69com) — gotowe gdyby content wrócił.
|
|
# HQFapScraper,
|
|
# FourK69Scraper,
|
|
# NepornScraper — dołączony 2026-06-10 (user request). KVS engine (jak freshporno/
|
|
# porn00), /latest-updates/N/. JSON-LD (title+desc+uploadDate+thumb) + video:duration
|
|
# meta + /models/ performerzy + /categories/ tagi. Brak studio (tytuł bywa
|
|
# "- HardX Update - ..." — fuzzy match po tytule). Resolve server-side _kvs,
|
|
# finalny remote_control.php portable cross-IP.
|
|
NepornScraper,
|
|
# SuperpornScraper — dołączony 2026-06-10 (user request). superporn blokuje VPS IP
|
|
# twardym CF 403 (każda impersonacja TLS), więc ingest HTML idzie przez Bright Data
|
|
# ISP proxy (BRIGHTDATA_PROXY_URL, ryczałt nie per-GB). Pierwszy scraper z proxy — `_proxy` w
|
|
# _browse_base. JSON-LD (title+desc+uploadDate+thumb+duration) + chipy pornstar/
|
|
# kategorie. Playback IP-bound → WebView (extractor superporncom → _vps_blocked_fallback).
|
|
# Bez proxy: scraper no-op (pusty iterator).
|
|
SuperpornScraper,
|
|
# porntrex/hqporner/youporn — NIE: KVS/JS bez SSR duration → niewidoczne orphany (2026-06-03).
|
|
# ShyfapScraper — wyłączony 2026-05-12 (pilot fail, 0% match — orphan factory).
|
|
]
|
|
|
|
__all__ = [
|
|
"BaseDirectTubeScraper",
|
|
"BaseBrowseScraper",
|
|
"ALL_DIRECT_SCRAPERS",
|
|
"ALL_BROWSE_SCRAPERS",
|
|
]
|