KekikStream 2.3.9__py3-none-any.whl → 2.5.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- KekikStream/Core/Extractor/ExtractorBase.py +3 -2
- KekikStream/Core/Extractor/ExtractorLoader.py +8 -14
- KekikStream/Core/HTMLHelper.py +120 -49
- KekikStream/Core/Plugin/PluginBase.py +35 -12
- KekikStream/Core/Plugin/PluginLoader.py +12 -14
- KekikStream/Core/Plugin/PluginManager.py +2 -2
- KekikStream/Core/Plugin/PluginModels.py +0 -3
- KekikStream/Extractors/Abstream.py +27 -0
- KekikStream/Extractors/CloseLoad.py +30 -54
- KekikStream/Extractors/ContentX.py +27 -72
- KekikStream/Extractors/DonilasPlay.py +33 -77
- KekikStream/Extractors/DzenRu.py +10 -24
- KekikStream/Extractors/ExPlay.py +20 -38
- KekikStream/Extractors/Filemoon.py +21 -46
- KekikStream/Extractors/HDMomPlayer.py +30 -0
- KekikStream/Extractors/HDPlayerSystem.py +13 -31
- KekikStream/Extractors/HotStream.py +27 -0
- KekikStream/Extractors/JFVid.py +3 -24
- KekikStream/Extractors/JetTv.py +21 -34
- KekikStream/Extractors/JetV.py +55 -0
- KekikStream/Extractors/MailRu.py +11 -29
- KekikStream/Extractors/MixPlayHD.py +15 -28
- KekikStream/Extractors/MixTiger.py +17 -40
- KekikStream/Extractors/MolyStream.py +17 -21
- KekikStream/Extractors/Odnoklassniki.py +40 -104
- KekikStream/Extractors/PeaceMakerst.py +18 -45
- KekikStream/Extractors/PixelDrain.py +8 -16
- KekikStream/Extractors/PlayerFilmIzle.py +22 -41
- KekikStream/Extractors/RapidVid.py +21 -35
- KekikStream/Extractors/SetPlay.py +18 -43
- KekikStream/Extractors/SibNet.py +7 -17
- KekikStream/Extractors/Sobreatsesuyp.py +23 -45
- KekikStream/Extractors/TRsTX.py +23 -53
- KekikStream/Extractors/TurboImgz.py +7 -14
- KekikStream/Extractors/VCTPlay.py +10 -28
- KekikStream/Extractors/Veev.py +145 -0
- KekikStream/Extractors/VidBiz.py +62 -0
- KekikStream/Extractors/VidHide.py +58 -30
- KekikStream/Extractors/VidMoly.py +65 -99
- KekikStream/Extractors/VidMoxy.py +16 -27
- KekikStream/Extractors/VidPapi.py +24 -54
- KekikStream/Extractors/VideoSeyred.py +19 -40
- KekikStream/Extractors/Videostr.py +58 -0
- KekikStream/Extractors/Vidoza.py +18 -0
- KekikStream/Extractors/Vtbe.py +38 -0
- KekikStream/Extractors/YTDLP.py +2 -2
- KekikStream/Extractors/YildizKisaFilm.py +13 -31
- KekikStream/Extractors/Zeus.py +61 -0
- KekikStream/Plugins/BelgeselX.py +97 -77
- KekikStream/Plugins/DiziBox.py +28 -45
- KekikStream/Plugins/DiziMom.py +179 -0
- KekikStream/Plugins/DiziPal.py +95 -161
- KekikStream/Plugins/DiziYou.py +51 -147
- KekikStream/Plugins/Dizilla.py +40 -61
- KekikStream/Plugins/FilmBip.py +90 -39
- KekikStream/Plugins/FilmEkseni.py +199 -0
- KekikStream/Plugins/FilmMakinesi.py +72 -73
- KekikStream/Plugins/FilmModu.py +25 -35
- KekikStream/Plugins/Filmatek.py +184 -0
- KekikStream/Plugins/FilmciBaba.py +155 -0
- KekikStream/Plugins/FullHDFilmizlesene.py +16 -37
- KekikStream/Plugins/HDFilm.py +243 -0
- KekikStream/Plugins/HDFilmCehennemi.py +242 -189
- KekikStream/Plugins/JetFilmizle.py +101 -69
- KekikStream/Plugins/KultFilmler.py +138 -104
- KekikStream/Plugins/RecTV.py +52 -73
- KekikStream/Plugins/RoketDizi.py +18 -27
- KekikStream/Plugins/SelcukFlix.py +30 -48
- KekikStream/Plugins/SetFilmIzle.py +76 -104
- KekikStream/Plugins/SezonlukDizi.py +90 -94
- KekikStream/Plugins/Sinefy.py +195 -167
- KekikStream/Plugins/SinemaCX.py +148 -78
- KekikStream/Plugins/Sinezy.py +29 -31
- KekikStream/Plugins/SuperFilmGeldi.py +12 -17
- KekikStream/Plugins/UgurFilm.py +85 -38
- KekikStream/Plugins/Watch32.py +160 -0
- KekikStream/Plugins/YabanciDizi.py +176 -211
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/METADATA +1 -1
- kekikstream-2.5.4.dist-info/RECORD +99 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/WHEEL +1 -1
- KekikStream/Plugins/FullHDFilm.py +0 -249
- kekikstream-2.3.9.dist-info/RECORD +0 -84
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
4
|
+
|
|
5
|
+
class DiziMom(PluginBase):
|
|
6
|
+
name = "DiziMom"
|
|
7
|
+
language = "tr"
|
|
8
|
+
main_url = "https://www.dizimom.one"
|
|
9
|
+
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
10
|
+
description = "Binlerce yerli yabancı dizi arşivi, tüm sezonlar, kesintisiz bölümler. Sadece dizi izle, Dizimom heryerde seninle!"
|
|
11
|
+
|
|
12
|
+
main_page = {
|
|
13
|
+
f"{main_url}/tum-bolumler/page" : "Son Bölümler",
|
|
14
|
+
f"{main_url}/yerli-dizi-izle/page" : "Yerli Diziler",
|
|
15
|
+
f"{main_url}/yabanci-dizi-izle/page" : "Yabancı Diziler",
|
|
16
|
+
f"{main_url}/tv-programlari-izle/page" : "TV Programları",
|
|
17
|
+
f"{main_url}/netflix-dizileri-izle/page" : "Netflix Dizileri",
|
|
18
|
+
f"{main_url}/turkce-dublaj-diziler-hd/page" : "Dublajlı Diziler",
|
|
19
|
+
f"{main_url}/yerli-dizi-izle/page" : "Yerli Diziler",
|
|
20
|
+
f"{main_url}/anime-izle/page" : "Animeler",
|
|
21
|
+
f"{main_url}/yabanci-dizi-izle/page" : "Yabancı Diziler",
|
|
22
|
+
f"{main_url}/kore-dizileri-izle-hd/page" : "Kore Dizileri",
|
|
23
|
+
f"{main_url}/full-hd-hint-dizileri-izle/page" : "Hint Dizileri",
|
|
24
|
+
f"{main_url}/pakistan-dizileri-izle/page" : "Pakistan Dizileri",
|
|
25
|
+
f"{main_url}/tv-programlari-izle/page" : "Tv Programları",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
29
|
+
istek = await self.httpx.get(f"{url}/{page}/")
|
|
30
|
+
secici = HTMLHelper(istek.text)
|
|
31
|
+
|
|
32
|
+
results = []
|
|
33
|
+
# Eğer "tum-bolumler" ise Episode kutularını, değilse Dizi kutularını tara
|
|
34
|
+
if "/tum-bolumler/" in url:
|
|
35
|
+
for item in secici.select("div.episode-box"):
|
|
36
|
+
title = secici.select_text("div.episode-name a", item)
|
|
37
|
+
href = secici.select_attr("div.episode-name a", "href", item)
|
|
38
|
+
img = secici.select_poster("div.cat-img img", item)
|
|
39
|
+
if title and href:
|
|
40
|
+
results.append(MainPageResult(
|
|
41
|
+
category = category,
|
|
42
|
+
title = title.split(" izle")[0],
|
|
43
|
+
url = self.fix_url(href),
|
|
44
|
+
poster = self.fix_url(img)
|
|
45
|
+
))
|
|
46
|
+
else:
|
|
47
|
+
for item in secici.select("div.single-item"):
|
|
48
|
+
title = secici.select_text("div.categorytitle a", item)
|
|
49
|
+
href = secici.select_attr("div.categorytitle a", "href", item)
|
|
50
|
+
img = secici.select_poster("div.cat-img img", item)
|
|
51
|
+
if title and href:
|
|
52
|
+
results.append(MainPageResult(
|
|
53
|
+
category = category,
|
|
54
|
+
title = title.split(" izle")[0],
|
|
55
|
+
url = self.fix_url(href),
|
|
56
|
+
poster = self.fix_url(img)
|
|
57
|
+
))
|
|
58
|
+
|
|
59
|
+
return results
|
|
60
|
+
|
|
61
|
+
async def search(self, query: str) -> list[SearchResult]:
|
|
62
|
+
istek = await self.httpx.get(f"{self.main_url}/?s={query}")
|
|
63
|
+
secici = HTMLHelper(istek.text)
|
|
64
|
+
items = secici.select("div.single-item")
|
|
65
|
+
|
|
66
|
+
return [
|
|
67
|
+
SearchResult(
|
|
68
|
+
title = secici.select_text("div.categorytitle a", item).split(" izle")[0],
|
|
69
|
+
url = self.fix_url(secici.select_attr("div.categorytitle a", "href", item)),
|
|
70
|
+
poster = self.fix_url(secici.select_attr("div.cat-img img", "src", item))
|
|
71
|
+
)
|
|
72
|
+
for item in items
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
async def load_item(self, url: str) -> SeriesInfo:
|
|
76
|
+
istek = await self.httpx.get(url)
|
|
77
|
+
secici = HTMLHelper(istek.text)
|
|
78
|
+
|
|
79
|
+
title = self.clean_title(secici.select_text("div.title h1"))
|
|
80
|
+
poster = secici.select_poster("div.category_image img")
|
|
81
|
+
description = secici.select_direct_text("div.category_desc")
|
|
82
|
+
tags = secici.select_texts("div.genres a")
|
|
83
|
+
rating = secici.regex_first(r"(?s)IMDB\s*:\s*(?:</span>)?\s*([\d\.]+)", secici.html)
|
|
84
|
+
year = secici.extract_year("div.category_text")
|
|
85
|
+
actors = secici.meta_list("Oyuncular", container_selector="div#icerikcat2")
|
|
86
|
+
|
|
87
|
+
episodes = []
|
|
88
|
+
for item in secici.select("div.bolumust"):
|
|
89
|
+
name = secici.select_text("div.baslik", item)
|
|
90
|
+
href = secici.select_attr("a", "href", item)
|
|
91
|
+
if name and href:
|
|
92
|
+
s, e = secici.extract_season_episode(name)
|
|
93
|
+
episodes.append(Episode(
|
|
94
|
+
season = s or 1,
|
|
95
|
+
episode = e or 1,
|
|
96
|
+
title = self.clean_title(name.replace(title, "").strip()),
|
|
97
|
+
url = self.fix_url(href)
|
|
98
|
+
))
|
|
99
|
+
|
|
100
|
+
return SeriesInfo(
|
|
101
|
+
url = url,
|
|
102
|
+
poster = self.fix_url(poster),
|
|
103
|
+
title = title,
|
|
104
|
+
description = description,
|
|
105
|
+
tags = tags,
|
|
106
|
+
rating = rating,
|
|
107
|
+
year = year,
|
|
108
|
+
actors = actors,
|
|
109
|
+
episodes = episodes
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
113
|
+
await self.httpx.post(
|
|
114
|
+
url = f"{self.main_url}/wp-login.php",
|
|
115
|
+
headers = {
|
|
116
|
+
"User-Agent" : "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
|
|
117
|
+
"sec-ch-ua" : 'Not/A)Brand";v="8", "Chromium";v="137", "Google Chrome";v="137"',
|
|
118
|
+
"sec-ch-ua-mobile" : "?1",
|
|
119
|
+
"sec-ch-ua-platform" : "Android"
|
|
120
|
+
},
|
|
121
|
+
data = {
|
|
122
|
+
"log" : "keyiflerolsun",
|
|
123
|
+
"pwd" : "12345",
|
|
124
|
+
"rememberme" : "forever",
|
|
125
|
+
"redirect_to" : self.main_url
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
istek = await self.httpx.get(url)
|
|
130
|
+
secici = HTMLHelper(istek.text)
|
|
131
|
+
|
|
132
|
+
iframe_data = []
|
|
133
|
+
|
|
134
|
+
# Aktif kaynağın (main iframe) adını bul
|
|
135
|
+
current_name = secici.select_text("div.sources span.current_dil") or ""
|
|
136
|
+
main_iframe = secici.select_attr("iframe[src]", "src")
|
|
137
|
+
|
|
138
|
+
# Bazen iframe doğrudan video p içinde olabilir
|
|
139
|
+
if not main_iframe:
|
|
140
|
+
main_iframe = secici.select_attr("div.video p iframe", "src")
|
|
141
|
+
|
|
142
|
+
if main_iframe:
|
|
143
|
+
iframe_data.append((main_iframe, current_name))
|
|
144
|
+
|
|
145
|
+
# Diğer kaynakları (Partlar) gez
|
|
146
|
+
sources = secici.select("div.sources a.post-page-numbers")
|
|
147
|
+
for source in sources:
|
|
148
|
+
href = secici.select_attr(None, "href", source)
|
|
149
|
+
name = secici.select_text("span.dil", source)
|
|
150
|
+
if href:
|
|
151
|
+
# Part sayfasına git
|
|
152
|
+
sub_istek = await self.httpx.get(href)
|
|
153
|
+
sub_helper = HTMLHelper(sub_istek.text)
|
|
154
|
+
sub_iframe = sub_helper.select_attr("div.video p iframe", "src") or sub_helper.select_attr("iframe[src]", "src")
|
|
155
|
+
|
|
156
|
+
if sub_iframe:
|
|
157
|
+
iframe_data.append((sub_iframe, name or f"{len(iframe_data)+1}.Kısım"))
|
|
158
|
+
|
|
159
|
+
results = []
|
|
160
|
+
for iframe_url, source_name in iframe_data:
|
|
161
|
+
# URL düzeltme
|
|
162
|
+
iframe_url = self.fix_url(iframe_url)
|
|
163
|
+
|
|
164
|
+
# Prefix olarak kaynak adını kullan (1.Kısım | HDMomPlayer)
|
|
165
|
+
extract_result = await self.extract(iframe_url, prefix=source_name)
|
|
166
|
+
|
|
167
|
+
if extract_result:
|
|
168
|
+
if isinstance(extract_result, list):
|
|
169
|
+
results.extend(extract_result)
|
|
170
|
+
else:
|
|
171
|
+
results.append(extract_result)
|
|
172
|
+
else:
|
|
173
|
+
results.append(ExtractResult(
|
|
174
|
+
url = iframe_url,
|
|
175
|
+
name = f"{source_name} | External",
|
|
176
|
+
referer = self.main_url
|
|
177
|
+
))
|
|
178
|
+
|
|
179
|
+
return results
|
KekikStream/Plugins/DiziPal.py
CHANGED
|
@@ -1,223 +1,157 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle, ExtractResult, HTMLHelper
|
|
4
4
|
|
|
5
5
|
class DiziPal(PluginBase):
|
|
6
6
|
name = "DiziPal"
|
|
7
7
|
language = "tr"
|
|
8
|
-
main_url = "https://
|
|
8
|
+
main_url = "https://dizipal.uk"
|
|
9
9
|
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
10
10
|
description = "dizipal güncel, dizipal yeni ve gerçek adresi. dizipal en yeni dizi ve filmleri güvenli ve hızlı şekilde sunar."
|
|
11
11
|
|
|
12
12
|
main_page = {
|
|
13
|
-
f"{main_url}/
|
|
14
|
-
f"{main_url}/
|
|
15
|
-
f"{main_url}/
|
|
16
|
-
f"{main_url}/
|
|
17
|
-
f"{main_url}/
|
|
18
|
-
f"{main_url}/
|
|
19
|
-
f"{main_url}/
|
|
20
|
-
f"{main_url}/
|
|
21
|
-
f"{main_url}/
|
|
22
|
-
f"{main_url}/
|
|
23
|
-
f"{main_url}/
|
|
13
|
+
f"{main_url}/kategori/aile/page/" : "Aile",
|
|
14
|
+
f"{main_url}/kategori/aksiyon/page/" : "Aksiyon",
|
|
15
|
+
f"{main_url}/kategori/animasyon/page/" : "Animasyon",
|
|
16
|
+
f"{main_url}/kategori/belgesel/page/" : "Belgesel",
|
|
17
|
+
f"{main_url}/kategori/bilim-kurgu/page/" : "Bilim Kurgu",
|
|
18
|
+
f"{main_url}/kategori/dram/page/" : "Dram",
|
|
19
|
+
f"{main_url}/kategori/fantastik/page/" : "Fantastik",
|
|
20
|
+
f"{main_url}/kategori/gerilim/page/" : "Gerilim",
|
|
21
|
+
f"{main_url}/kategori/gizem/page/" : "Gizem",
|
|
22
|
+
f"{main_url}/kategori/komedi/page/" : "Komedi",
|
|
23
|
+
f"{main_url}/kategori/korku/page/" : "Korku",
|
|
24
|
+
f"{main_url}/kategori/macera/page/" : "Macera",
|
|
25
|
+
f"{main_url}/kategori/muzik/page/" : "Müzik",
|
|
26
|
+
f"{main_url}/kategori/romantik/page/" : "Romantik",
|
|
27
|
+
f"{main_url}/kategori/savas/page/" : "Savaş",
|
|
28
|
+
f"{main_url}/kategori/suc/page/" : "Suç",
|
|
29
|
+
f"{main_url}/kategori/tarih/page/" : "Tarih",
|
|
30
|
+
f"{main_url}/kategori/vahsi-bati/page/" : "Vahşi Batı",
|
|
31
|
+
f"{main_url}/kategori/yerli/page/" : "Yerli",
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
27
|
-
istek = await self.httpx.get(url)
|
|
35
|
+
istek = await self.httpx.get(f"{url}{page}/")
|
|
28
36
|
secici = HTMLHelper(istek.text)
|
|
29
37
|
|
|
30
38
|
results = []
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
dizi_url = href.split("/sezon")[0] if "/sezon" in href else href
|
|
44
|
-
|
|
45
|
-
results.append(MainPageResult(
|
|
46
|
-
category = category,
|
|
47
|
-
title = title,
|
|
48
|
-
url = self.fix_url(dizi_url),
|
|
49
|
-
poster = self.fix_url(poster) if poster else None,
|
|
50
|
-
))
|
|
51
|
-
else:
|
|
52
|
-
for veri in secici.select("article.type2 ul li"):
|
|
53
|
-
title = secici.select_text("span.title", veri)
|
|
54
|
-
href = secici.select_attr("a", "href", veri)
|
|
55
|
-
poster = secici.select_attr("img", "src", veri)
|
|
56
|
-
|
|
57
|
-
if title and href:
|
|
58
|
-
results.append(MainPageResult(
|
|
59
|
-
category = category,
|
|
60
|
-
title = title,
|
|
61
|
-
url = self.fix_url(href),
|
|
62
|
-
poster = self.fix_url(poster) if poster else None,
|
|
63
|
-
))
|
|
39
|
+
for veri in secici.select("div.grid div.post-item"):
|
|
40
|
+
title = secici.select_attr("a", "title", veri)
|
|
41
|
+
href = secici.select_attr("a", "href", veri)
|
|
42
|
+
poster = secici.select_poster("div.poster img", veri)
|
|
43
|
+
|
|
44
|
+
if title and href:
|
|
45
|
+
results.append(MainPageResult(
|
|
46
|
+
category = category,
|
|
47
|
+
title = title,
|
|
48
|
+
url = self.fix_url(href),
|
|
49
|
+
poster = self.fix_url(poster),
|
|
50
|
+
))
|
|
64
51
|
|
|
65
52
|
return results
|
|
66
53
|
|
|
67
54
|
async def search(self, query: str) -> list[SearchResult]:
|
|
68
|
-
self.httpx.
|
|
69
|
-
|
|
70
|
-
"X-Requested-With" : "XMLHttpRequest"
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
istek = await self.httpx.post(
|
|
74
|
-
url = f"{self.main_url}/api/search-autocomplete",
|
|
75
|
-
data = {"query": query}
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
try:
|
|
79
|
-
data = istek.json()
|
|
80
|
-
except Exception:
|
|
81
|
-
return []
|
|
55
|
+
istek = await self.httpx.get(f"{self.main_url}/?s={query}")
|
|
56
|
+
secici = HTMLHelper(istek.text)
|
|
82
57
|
|
|
83
58
|
results = []
|
|
59
|
+
for veri in secici.select("div.grid div.post-item"):
|
|
60
|
+
title = secici.select_attr("a", "title", veri)
|
|
61
|
+
href = secici.select_attr("a", "href", veri)
|
|
62
|
+
poster = secici.select_poster("div.poster img", veri)
|
|
84
63
|
|
|
85
|
-
|
|
86
|
-
items = data.values() if isinstance(data, dict) else data
|
|
87
|
-
|
|
88
|
-
for item in items:
|
|
89
|
-
if not isinstance(item, dict):
|
|
90
|
-
continue
|
|
91
|
-
|
|
92
|
-
title = item.get("title")
|
|
93
|
-
url = item.get("url")
|
|
94
|
-
poster = item.get("poster")
|
|
95
|
-
|
|
96
|
-
if title and url:
|
|
64
|
+
if title and href:
|
|
97
65
|
results.append(SearchResult(
|
|
98
66
|
title = title,
|
|
99
|
-
url =
|
|
100
|
-
poster = self.fix_url(poster)
|
|
67
|
+
url = self.fix_url(href),
|
|
68
|
+
poster = self.fix_url(poster),
|
|
101
69
|
))
|
|
102
70
|
|
|
103
71
|
return results
|
|
104
72
|
|
|
105
|
-
def _find_sibling_text(self, secici: HTMLHelper, label_text: str) -> str | None:
|
|
106
|
-
"""Bir label'ın kardeş div'inden text çıkarır (xpath yerine)"""
|
|
107
|
-
for div in secici.select("div"):
|
|
108
|
-
if secici.select_text(element=div) == label_text:
|
|
109
|
-
# Sonraki kardeş elementi bul
|
|
110
|
-
next_sibling = div.next
|
|
111
|
-
while next_sibling:
|
|
112
|
-
if hasattr(next_sibling, 'text') and next_sibling.text(strip=True):
|
|
113
|
-
return next_sibling.text(strip=True)
|
|
114
|
-
next_sibling = next_sibling.next if hasattr(next_sibling, 'next') else None
|
|
115
|
-
return None
|
|
116
|
-
|
|
117
73
|
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
118
|
-
# Reset headers to get HTML response
|
|
119
|
-
self.httpx.headers.update({
|
|
120
|
-
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
|
121
|
-
})
|
|
122
|
-
self.httpx.headers.pop("X-Requested-With", None)
|
|
123
|
-
|
|
124
74
|
istek = await self.httpx.get(url)
|
|
125
75
|
secici = HTMLHelper(istek.text)
|
|
126
|
-
html_text = istek.text
|
|
127
76
|
|
|
128
|
-
poster
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
info = {}
|
|
132
|
-
for li in secici.select("li"):
|
|
133
|
-
key = secici.select_text("div.key", li)
|
|
134
|
-
val = secici.select_text("div.value", li)
|
|
135
|
-
if key and val:
|
|
136
|
-
info[key.strip(":")] = val.strip()
|
|
137
|
-
|
|
138
|
-
year = info.get("Yapım Yılı")
|
|
139
|
-
rating = info.get("IMDB Puanı")
|
|
77
|
+
poster = self.fix_url(secici.select_attr("meta[property='og:image']", "content"))
|
|
78
|
+
description = secici.select_attr("meta[property='og:description']", "content")
|
|
79
|
+
title = secici.select_text("h1")
|
|
140
80
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
81
|
+
year = secici.meta_value("Yapım Yılı")
|
|
82
|
+
rating = secici.meta_value("IMDB Puanı")
|
|
83
|
+
duration_raw = secici.meta_value("Süre")
|
|
84
|
+
if duration_raw:
|
|
85
|
+
parts = duration_raw.split()
|
|
86
|
+
saat = 0
|
|
87
|
+
dakika = 0
|
|
88
|
+
|
|
89
|
+
for p in parts:
|
|
90
|
+
if "s" in p:
|
|
91
|
+
saat = int(p.replace("s", ""))
|
|
92
|
+
elif "dk" in p:
|
|
93
|
+
dakika = int(p.replace("dk", ""))
|
|
94
|
+
|
|
95
|
+
duration = saat * 60 + dakika
|
|
96
|
+
else:
|
|
97
|
+
duration = None
|
|
148
98
|
|
|
149
|
-
|
|
150
|
-
|
|
99
|
+
tags = secici.meta_list("Tür")
|
|
100
|
+
actors = secici.meta_list("Oyuncular")
|
|
101
|
+
if not actors:
|
|
102
|
+
actors = secici.select_attrs("div.swiper-slide a", "title")
|
|
151
103
|
|
|
152
104
|
if "/dizi/" in url:
|
|
153
|
-
title = secici.select_text("div.cover h5")
|
|
154
|
-
|
|
155
105
|
episodes = []
|
|
156
106
|
for ep in secici.select("div.episode-item"):
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
107
|
+
name = secici.select_text("h4 a", ep)
|
|
108
|
+
href = secici.select_attr("a", "href", ep)
|
|
109
|
+
link_title = secici.select_attr("a", "title", ep)
|
|
110
|
+
|
|
111
|
+
h4_texts = secici.select_texts("h4", ep)
|
|
112
|
+
text = h4_texts[1] if len(h4_texts) > 1 else (h4_texts[0] if h4_texts else "")
|
|
161
113
|
|
|
162
|
-
|
|
163
|
-
ep_episode = None
|
|
164
|
-
if len(ep_parts) >= 4:
|
|
165
|
-
try:
|
|
166
|
-
ep_season = int(ep_parts[0].replace(".", ""))
|
|
167
|
-
ep_episode = int(ep_parts[2].replace(".", ""))
|
|
168
|
-
except ValueError:
|
|
169
|
-
pass
|
|
114
|
+
full_text = f"{text} {link_title}" if link_title else text
|
|
170
115
|
|
|
171
|
-
if
|
|
116
|
+
if name and href:
|
|
117
|
+
s, e = secici.extract_season_episode(full_text or "")
|
|
172
118
|
episodes.append(Episode(
|
|
173
|
-
season =
|
|
174
|
-
episode =
|
|
175
|
-
title =
|
|
176
|
-
url = self.fix_url(
|
|
119
|
+
season = s,
|
|
120
|
+
episode = e,
|
|
121
|
+
title = name,
|
|
122
|
+
url = self.fix_url(href)
|
|
177
123
|
))
|
|
178
124
|
|
|
179
125
|
return SeriesInfo(
|
|
180
126
|
url = url,
|
|
181
|
-
poster = poster,
|
|
127
|
+
poster = poster.replace("https://test4test.online", self.main_url),
|
|
182
128
|
title = title,
|
|
183
129
|
description = description,
|
|
184
130
|
tags = tags,
|
|
185
131
|
rating = rating,
|
|
186
132
|
year = year,
|
|
187
133
|
duration = duration,
|
|
188
|
-
episodes = episodes
|
|
189
|
-
actors = actors
|
|
134
|
+
episodes = episodes,
|
|
135
|
+
actors = actors
|
|
190
136
|
)
|
|
191
|
-
else:
|
|
192
|
-
# Film için title - g-title div'lerinin 2. olanı
|
|
193
|
-
g_titles = secici.select("div.g-title div")
|
|
194
|
-
title = secici.select_text(element=g_titles[1]) if len(g_titles) >= 2 else None
|
|
195
137
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
138
|
+
return MovieInfo(
|
|
139
|
+
url = url,
|
|
140
|
+
poster = poster.replace("https://test4test.online", self.main_url),
|
|
141
|
+
title = title,
|
|
142
|
+
description = description,
|
|
143
|
+
tags = tags,
|
|
144
|
+
rating = rating,
|
|
145
|
+
year = year,
|
|
146
|
+
duration = duration,
|
|
147
|
+
actors = actors
|
|
148
|
+
)
|
|
207
149
|
|
|
208
150
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
209
|
-
# Reset headers to get HTML response
|
|
210
|
-
self.httpx.headers.update({
|
|
211
|
-
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
|
212
|
-
})
|
|
213
|
-
self.httpx.headers.pop("X-Requested-With", None)
|
|
214
|
-
|
|
215
151
|
istek = await self.httpx.get(url)
|
|
216
152
|
secici = HTMLHelper(istek.text)
|
|
217
153
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
iframe = secici.select_attr(".series-player-container iframe", "src") or secici.select_attr("div#vast_new iframe", "src")
|
|
154
|
+
iframe = secici.select_attr("div.video-player-area iframe", "src") or secici.select_attr("div.responsive-player iframe", "src")
|
|
221
155
|
if not iframe:
|
|
222
156
|
return []
|
|
223
157
|
|