KekikStream 2.1.9__py3-none-any.whl → 2.2.7__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/Extractors/CloseLoad.py +7 -8
- KekikStream/Extractors/Filemoon.py +7 -6
- KekikStream/Extractors/JFVid.py +40 -0
- KekikStream/Extractors/MolyStream.py +6 -5
- KekikStream/Extractors/PlayerFilmIzle.py +6 -2
- KekikStream/Extractors/VidHide.py +0 -1
- KekikStream/Extractors/VidMoly.py +17 -9
- KekikStream/Plugins/BelgeselX.py +39 -20
- KekikStream/Plugins/DiziBox.py +115 -59
- KekikStream/Plugins/DiziPal.py +87 -40
- KekikStream/Plugins/DiziYou.py +105 -64
- KekikStream/Plugins/Dizilla.py +58 -29
- KekikStream/Plugins/FilmBip.py +60 -31
- KekikStream/Plugins/FilmMakinesi.py +75 -51
- KekikStream/Plugins/FilmModu.py +73 -36
- KekikStream/Plugins/FullHDFilm.py +82 -48
- KekikStream/Plugins/FullHDFilmizlesene.py +94 -39
- KekikStream/Plugins/HDFilmCehennemi.py +79 -54
- KekikStream/Plugins/JetFilmizle.py +98 -51
- KekikStream/Plugins/KultFilmler.py +64 -34
- KekikStream/Plugins/RoketDizi.py +43 -26
- KekikStream/Plugins/SelcukFlix.py +27 -14
- KekikStream/Plugins/SetFilmIzle.py +74 -43
- KekikStream/Plugins/SezonlukDizi.py +102 -46
- KekikStream/Plugins/Sinefy.py +130 -101
- KekikStream/Plugins/SinemaCX.py +82 -37
- KekikStream/Plugins/Sinezy.py +61 -47
- KekikStream/Plugins/SuperFilmGeldi.py +72 -36
- KekikStream/Plugins/UgurFilm.py +72 -34
- KekikStream/requirements.txt +1 -1
- {kekikstream-2.1.9.dist-info → kekikstream-2.2.7.dist-info}/METADATA +40 -32
- {kekikstream-2.1.9.dist-info → kekikstream-2.2.7.dist-info}/RECORD +36 -35
- {kekikstream-2.1.9.dist-info → kekikstream-2.2.7.dist-info}/WHEEL +0 -0
- {kekikstream-2.1.9.dist-info → kekikstream-2.2.7.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.1.9.dist-info → kekikstream-2.2.7.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.1.9.dist-info → kekikstream-2.2.7.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from
|
|
5
|
-
from Kekik.Sifreleme
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
|
|
4
|
+
from selectolax.parser import HTMLParser
|
|
5
|
+
from Kekik.Sifreleme import StringCodec
|
|
6
6
|
import json, re
|
|
7
7
|
|
|
8
8
|
class FullHDFilmizlesene(PluginBase):
|
|
@@ -42,55 +42,102 @@ class FullHDFilmizlesene(PluginBase):
|
|
|
42
42
|
|
|
43
43
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
44
44
|
istek = self.cloudscraper.get(f"{url}{page}")
|
|
45
|
-
secici =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
secici = HTMLParser(istek.text)
|
|
46
|
+
|
|
47
|
+
results = []
|
|
48
|
+
for veri in secici.css("li.film"):
|
|
49
|
+
title_el = veri.css_first("span.film-title")
|
|
50
|
+
link_el = veri.css_first("a")
|
|
51
|
+
img_el = veri.css_first("img")
|
|
52
|
+
|
|
53
|
+
title = title_el.text(strip=True) if title_el else None
|
|
54
|
+
href = link_el.attrs.get("href") if link_el else None
|
|
55
|
+
poster = img_el.attrs.get("data-src") if img_el else None
|
|
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
|
+
))
|
|
64
|
+
|
|
65
|
+
return results
|
|
56
66
|
|
|
57
67
|
async def search(self, query: str) -> list[SearchResult]:
|
|
58
68
|
istek = await self.httpx.get(f"{self.main_url}/arama/{query}")
|
|
59
|
-
secici =
|
|
69
|
+
secici = HTMLParser(istek.text)
|
|
60
70
|
|
|
61
71
|
results = []
|
|
62
72
|
for film in secici.css("li.film"):
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
73
|
+
title_el = film.css_first("span.film-title")
|
|
74
|
+
link_el = film.css_first("a")
|
|
75
|
+
img_el = film.css_first("img")
|
|
76
|
+
|
|
77
|
+
title = title_el.text(strip=True) if title_el else None
|
|
78
|
+
href = link_el.attrs.get("href") if link_el else None
|
|
79
|
+
poster = img_el.attrs.get("data-src") if img_el else None
|
|
66
80
|
|
|
67
81
|
if title and href:
|
|
68
|
-
results.append(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
)
|
|
74
|
-
)
|
|
82
|
+
results.append(SearchResult(
|
|
83
|
+
title = title,
|
|
84
|
+
url = self.fix_url(href),
|
|
85
|
+
poster = self.fix_url(poster) if poster else None,
|
|
86
|
+
))
|
|
75
87
|
|
|
76
88
|
return results
|
|
77
89
|
|
|
78
90
|
async def load_item(self, url: str) -> MovieInfo:
|
|
79
91
|
istek = await self.httpx.get(url)
|
|
80
|
-
secici =
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
secici = HTMLParser(istek.text)
|
|
93
|
+
html_text = istek.text
|
|
94
|
+
|
|
95
|
+
# Title: normalize-space yerine doğrudan class ile
|
|
96
|
+
title_el = secici.css_first("div.izle-titles")
|
|
97
|
+
title = title_el.text(strip=True) if title_el else ""
|
|
98
|
+
|
|
99
|
+
img_el = secici.css_first("div img[data-src]")
|
|
100
|
+
poster = img_el.attrs.get("data-src", "").strip() if img_el else ""
|
|
101
|
+
|
|
102
|
+
desc_el = secici.css_first("div.ozet-ic p")
|
|
103
|
+
description = desc_el.text(strip=True) if desc_el else ""
|
|
104
|
+
|
|
105
|
+
tags = [a.text(strip=True) for a in secici.css("a[rel='category tag']") if a.text(strip=True)]
|
|
106
|
+
|
|
107
|
+
# Rating: normalize-space yerine doğrudan class ile ve son kelimeyi al
|
|
108
|
+
rating_el = secici.css_first("div.puanx-puan")
|
|
109
|
+
rating = None
|
|
110
|
+
if rating_el:
|
|
111
|
+
rating_text = rating_el.text(strip=True)
|
|
112
|
+
if rating_text:
|
|
113
|
+
parts = rating_text.split()
|
|
114
|
+
rating = parts[-1] if parts else None
|
|
115
|
+
|
|
116
|
+
# Year: ilk yıl formatında değer
|
|
117
|
+
year_el = secici.css_first("div.dd a.category")
|
|
118
|
+
year = None
|
|
119
|
+
if year_el:
|
|
120
|
+
year_text = year_el.text(strip=True)
|
|
121
|
+
if year_text:
|
|
122
|
+
parts = year_text.split()
|
|
123
|
+
year = parts[0] if parts else None
|
|
124
|
+
|
|
125
|
+
# Actors: nth-child yerine tüm li'leri alıp 2. index
|
|
126
|
+
lis = secici.css("div.film-info ul li")
|
|
127
|
+
actors = []
|
|
128
|
+
if len(lis) >= 2:
|
|
129
|
+
actors = [a.text(strip=True) for a in lis[1].css("a > span") if a.text(strip=True)]
|
|
130
|
+
|
|
131
|
+
duration_el = secici.css_first("span.sure")
|
|
132
|
+
duration = "0"
|
|
133
|
+
if duration_el:
|
|
134
|
+
duration_text = duration_el.text(strip=True)
|
|
135
|
+
duration_parts = duration_text.split()
|
|
136
|
+
duration = duration_parts[0] if duration_parts else "0"
|
|
90
137
|
|
|
91
138
|
return MovieInfo(
|
|
92
139
|
url = url,
|
|
93
|
-
poster = self.fix_url(poster),
|
|
140
|
+
poster = self.fix_url(poster) if poster else None,
|
|
94
141
|
title = title,
|
|
95
142
|
description = description,
|
|
96
143
|
tags = tags,
|
|
@@ -102,10 +149,18 @@ class FullHDFilmizlesene(PluginBase):
|
|
|
102
149
|
|
|
103
150
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
104
151
|
istek = await self.httpx.get(url)
|
|
105
|
-
secici =
|
|
152
|
+
secici = HTMLParser(istek.text)
|
|
153
|
+
html_text = istek.text
|
|
154
|
+
|
|
155
|
+
# İlk script'i al (xpath (//script)[1] yerine)
|
|
156
|
+
scripts = secici.css("script")
|
|
157
|
+
script_content = scripts[0].text() if scripts else ""
|
|
158
|
+
|
|
159
|
+
scx_match = re.search(r"scx = (.*?);", script_content)
|
|
160
|
+
if not scx_match:
|
|
161
|
+
return []
|
|
106
162
|
|
|
107
|
-
|
|
108
|
-
scx_data = json.loads(re.findall(r"scx = (.*?);", script)[0])
|
|
163
|
+
scx_data = json.loads(scx_match.group(1))
|
|
109
164
|
scx_keys = list(scx_data.keys())
|
|
110
165
|
|
|
111
166
|
link_list = []
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from
|
|
5
|
-
from Kekik.Sifreleme
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle, ExtractResult
|
|
4
|
+
from selectolax.parser import HTMLParser
|
|
5
|
+
from Kekik.Sifreleme import Packer, StreamDecoder
|
|
6
6
|
import random, string, re
|
|
7
7
|
|
|
8
8
|
class HDFilmCehennemi(PluginBase):
|
|
@@ -31,17 +31,26 @@ class HDFilmCehennemi(PluginBase):
|
|
|
31
31
|
|
|
32
32
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
33
33
|
istek = await self.httpx.get(f"{url}", follow_redirects=True)
|
|
34
|
-
secici =
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
secici = HTMLParser(istek.text)
|
|
35
|
+
|
|
36
|
+
results = []
|
|
37
|
+
for veri in secici.css("div.section-content a.poster"):
|
|
38
|
+
title_el = veri.css_first("strong.poster-title")
|
|
39
|
+
img_el = veri.css_first("img")
|
|
40
|
+
|
|
41
|
+
title = title_el.text(strip=True) if title_el else None
|
|
42
|
+
href = veri.attrs.get("href")
|
|
43
|
+
poster = img_el.attrs.get("data-src") if img_el else None
|
|
44
|
+
|
|
45
|
+
if title and href:
|
|
46
|
+
results.append(MainPageResult(
|
|
47
|
+
category = category,
|
|
48
|
+
title = title,
|
|
49
|
+
url = self.fix_url(href),
|
|
50
|
+
poster = self.fix_url(poster) if poster else None,
|
|
51
|
+
))
|
|
52
|
+
|
|
53
|
+
return results
|
|
45
54
|
|
|
46
55
|
async def search(self, query: str) -> list[SearchResult]:
|
|
47
56
|
istek = await self.httpx.get(
|
|
@@ -54,57 +63,69 @@ class HDFilmCehennemi(PluginBase):
|
|
|
54
63
|
)
|
|
55
64
|
|
|
56
65
|
results = []
|
|
57
|
-
for veri in istek.json().get("results"):
|
|
58
|
-
secici =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
for veri in istek.json().get("results", []):
|
|
67
|
+
secici = HTMLParser(veri)
|
|
68
|
+
title_el = secici.css_first("h4.title")
|
|
69
|
+
link_el = secici.css_first("a")
|
|
70
|
+
img_el = secici.css_first("img")
|
|
71
|
+
|
|
72
|
+
title = title_el.text(strip=True) if title_el else None
|
|
73
|
+
href = link_el.attrs.get("href") if link_el else None
|
|
74
|
+
poster = (img_el.attrs.get("data-src") or img_el.attrs.get("src")) if img_el else None
|
|
62
75
|
|
|
63
76
|
if title and href:
|
|
64
|
-
results.append(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
)
|
|
70
|
-
)
|
|
77
|
+
results.append(SearchResult(
|
|
78
|
+
title = title,
|
|
79
|
+
url = self.fix_url(href),
|
|
80
|
+
poster = self.fix_url(poster) if poster else None,
|
|
81
|
+
))
|
|
71
82
|
|
|
72
83
|
return results
|
|
73
84
|
|
|
74
85
|
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
75
86
|
istek = await self.httpx.get(url, headers = {"Referer": f"{self.main_url}/"})
|
|
76
|
-
secici =
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
title
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
secici = HTMLParser(istek.text)
|
|
88
|
+
|
|
89
|
+
title_el = secici.css_first("h1.section-title")
|
|
90
|
+
title = title_el.text(strip=True) if title_el else ""
|
|
91
|
+
|
|
92
|
+
poster_el = secici.css_first("aside.post-info-poster img.lazyload")
|
|
93
|
+
poster = poster_el.attrs.get("data-src", "").strip() if poster_el else ""
|
|
94
|
+
|
|
95
|
+
desc_el = secici.css_first("article.post-info-content > p")
|
|
96
|
+
description = desc_el.text(strip=True) if desc_el else ""
|
|
97
|
+
|
|
98
|
+
tags = [a.text(strip=True) for a in secici.css("div.post-info-genres a") if a.text(strip=True)]
|
|
99
|
+
|
|
100
|
+
rating_el = secici.css_first("div.post-info-imdb-rating span")
|
|
101
|
+
rating = rating_el.text(strip=True) if rating_el else ""
|
|
102
|
+
|
|
103
|
+
year_el = secici.css_first("div.post-info-year-country a")
|
|
104
|
+
year = year_el.text(strip=True) if year_el else ""
|
|
105
|
+
|
|
106
|
+
actors = [a.text(strip=True) for a in secici.css("div.post-info-cast a > strong") if a.text(strip=True)]
|
|
107
|
+
|
|
108
|
+
duration_el = secici.css_first("div.post-info-duration")
|
|
109
|
+
duration_str = duration_el.text(strip=True) if duration_el else "0"
|
|
110
|
+
duration_str = duration_str.replace("dakika", "").strip()
|
|
92
111
|
|
|
93
112
|
try:
|
|
94
|
-
|
|
113
|
+
duration_match = re.search(r'\d+', duration_str)
|
|
114
|
+
duration_minutes = int(duration_match.group()) if duration_match else 0
|
|
95
115
|
except Exception:
|
|
96
116
|
duration_minutes = 0
|
|
97
117
|
|
|
98
118
|
# Dizi mi film mi kontrol et (Kotlin referansı: div.seasons kontrolü)
|
|
99
|
-
is_series = len(secici.css("div.seasons")
|
|
119
|
+
is_series = len(secici.css("div.seasons")) > 0
|
|
100
120
|
|
|
101
121
|
if is_series:
|
|
102
122
|
episodes = []
|
|
103
123
|
for ep in secici.css("div.seasons-tab-content a"):
|
|
104
|
-
|
|
105
|
-
|
|
124
|
+
ep_name_el = ep.css_first("h4")
|
|
125
|
+
ep_name = ep_name_el.text(strip=True) if ep_name_el else None
|
|
126
|
+
ep_href = ep.attrs.get("href")
|
|
127
|
+
|
|
106
128
|
if ep_name and ep_href:
|
|
107
|
-
ep_name = ep_name.strip()
|
|
108
129
|
# Regex ile sezon ve bölüm numarası çıkar
|
|
109
130
|
ep_match = re.search(r'(\d+)\.\s*Bölüm', ep_name)
|
|
110
131
|
sz_match = re.search(r'(\d+)\.\s*Sezon', ep_name)
|
|
@@ -120,7 +141,7 @@ class HDFilmCehennemi(PluginBase):
|
|
|
120
141
|
|
|
121
142
|
return SeriesInfo(
|
|
122
143
|
url = url,
|
|
123
|
-
poster = self.fix_url(poster),
|
|
144
|
+
poster = self.fix_url(poster) if poster else None,
|
|
124
145
|
title = self.clean_title(title),
|
|
125
146
|
description = description,
|
|
126
147
|
tags = tags,
|
|
@@ -132,7 +153,7 @@ class HDFilmCehennemi(PluginBase):
|
|
|
132
153
|
else:
|
|
133
154
|
return MovieInfo(
|
|
134
155
|
url = url,
|
|
135
|
-
poster = self.fix_url(poster),
|
|
156
|
+
poster = self.fix_url(poster) if poster else None,
|
|
136
157
|
title = self.clean_title(title),
|
|
137
158
|
description = description,
|
|
138
159
|
tags = tags,
|
|
@@ -207,7 +228,7 @@ class HDFilmCehennemi(PluginBase):
|
|
|
207
228
|
return ""
|
|
208
229
|
|
|
209
230
|
# 4) Özel decoder ile çöz
|
|
210
|
-
return StreamDecoder.
|
|
231
|
+
return StreamDecoder.extract_stream_url(unpacked)
|
|
211
232
|
|
|
212
233
|
async def invoke_local_source(self, iframe: str, source: str, url: str):
|
|
213
234
|
self.httpx.headers.update({
|
|
@@ -255,15 +276,19 @@ class HDFilmCehennemi(PluginBase):
|
|
|
255
276
|
|
|
256
277
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
257
278
|
istek = await self.httpx.get(url)
|
|
258
|
-
secici =
|
|
279
|
+
secici = HTMLParser(istek.text)
|
|
259
280
|
|
|
260
281
|
results = []
|
|
261
282
|
for alternatif in secici.css("div.alternative-links"):
|
|
262
|
-
lang_code = alternatif.
|
|
283
|
+
lang_code = alternatif.attrs.get("data-lang", "").upper()
|
|
263
284
|
|
|
264
285
|
for link in alternatif.css("button.alternative-link"):
|
|
265
|
-
|
|
266
|
-
|
|
286
|
+
source_text = link.text(strip=True).replace('(HDrip Xbet)', '').strip()
|
|
287
|
+
source = f"{source_text} {lang_code}"
|
|
288
|
+
video_id = link.attrs.get("data-video")
|
|
289
|
+
|
|
290
|
+
if not video_id:
|
|
291
|
+
continue
|
|
267
292
|
|
|
268
293
|
api_get = await self.httpx.get(
|
|
269
294
|
url = f"{self.main_url}/video/{video_id}/",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
|
|
4
|
+
from selectolax.parser import HTMLParser
|
|
5
|
+
import re
|
|
5
6
|
|
|
6
7
|
class JetFilmizle(PluginBase):
|
|
7
8
|
name = "JetFilmizle"
|
|
@@ -16,22 +17,56 @@ class JetFilmizle(PluginBase):
|
|
|
16
17
|
f"{main_url}/editorun-secimi/page/" : "Editörün Seçimi",
|
|
17
18
|
f"{main_url}/turk-film-izle/page/" : "Türk Filmleri",
|
|
18
19
|
f"{main_url}/cizgi-filmler-izle/page/" : "Çizgi Filmler",
|
|
19
|
-
f"{main_url}/kategoriler/yesilcam-filmleri-izlee/page/" : "Yeşilçam Filmleri"
|
|
20
|
+
f"{main_url}/kategoriler/yesilcam-filmleri-izlee/page/" : "Yeşilçam Filmleri",
|
|
21
|
+
f"{main_url}/film-turu/aile-filmleri-izle/page/" : "Aile Filmleri",
|
|
22
|
+
f"{main_url}/film-turu/aksiyon-filmleri/page/" : "Aksiyon Filmleri",
|
|
23
|
+
f"{main_url}/film-turu/animasyon-filmler-izle/page/" : "Animasyon Filmleri",
|
|
24
|
+
f"{main_url}/film-turu/bilim-kurgu-filmler/page/" : "Bilim Kurgu Filmleri",
|
|
25
|
+
f"{main_url}/film-turu/dram-filmleri-izle/page/" : "Dram Filmleri",
|
|
26
|
+
f"{main_url}/film-turu/fantastik-filmleri-izle/page/" : "Fantastik Filmler",
|
|
27
|
+
f"{main_url}/film-turu/gerilim-filmleri/page/" : "Gerilim Filmleri",
|
|
28
|
+
f"{main_url}/film-turu/gizem-filmleri/page/" : "Gizem Filmleri",
|
|
29
|
+
f"{main_url}/film-turu/komedi-film-full-izle/page/" : "Komedi Filmleri",
|
|
30
|
+
f"{main_url}/film-turu/korku-filmleri-izle/page/" : "Korku Filmleri",
|
|
31
|
+
f"{main_url}/film-turu/macera-filmleri/page/" : "Macera Filmleri",
|
|
32
|
+
f"{main_url}/film-turu/muzikal/page/" : "Müzikal Filmler",
|
|
33
|
+
f"{main_url}/film-turu/polisiye/page/" : "Polisiye Filmler",
|
|
34
|
+
f"{main_url}/film-turu/romantik-film-izle/page/" : "Romantik Filmler",
|
|
35
|
+
f"{main_url}/film-turu/savas-filmi-izle/page/" : "Savaş Filmleri",
|
|
36
|
+
f"{main_url}/film-turu/spor/page/" : "Spor Filmleri",
|
|
37
|
+
f"{main_url}/film-turu/suc-filmleri/page/" : "Suç Filmleri",
|
|
38
|
+
f"{main_url}/film-turu/tarihi-filmler/page/" : "Tarihi Filmleri",
|
|
20
39
|
}
|
|
21
40
|
|
|
22
41
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
23
42
|
istek = await self.httpx.get(f"{url}{page}", follow_redirects=True)
|
|
24
|
-
secici =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
secici = HTMLParser(istek.text)
|
|
44
|
+
|
|
45
|
+
results = []
|
|
46
|
+
for veri in secici.css("article.movie"):
|
|
47
|
+
# h2-h6 içindeki a linki
|
|
48
|
+
title_link = None
|
|
49
|
+
for h_tag in ["h2", "h3", "h4", "h5", "h6"]:
|
|
50
|
+
title_link = veri.css_first(f"{h_tag} a")
|
|
51
|
+
if title_link:
|
|
52
|
+
break
|
|
53
|
+
|
|
54
|
+
link_el = veri.css_first("a")
|
|
55
|
+
img_el = veri.css_first("img")
|
|
56
|
+
|
|
57
|
+
title = self.clean_title(title_link.text(strip=True)) if title_link else None
|
|
58
|
+
href = link_el.attrs.get("href") if link_el else None
|
|
59
|
+
poster = (img_el.attrs.get("data-src") or img_el.attrs.get("src")) if img_el else None
|
|
60
|
+
|
|
61
|
+
if title and href:
|
|
62
|
+
results.append(MainPageResult(
|
|
63
|
+
category = category,
|
|
64
|
+
title = title,
|
|
65
|
+
url = self.fix_url(href),
|
|
66
|
+
poster = self.fix_url(poster) if poster else None,
|
|
67
|
+
))
|
|
68
|
+
|
|
69
|
+
return results
|
|
35
70
|
|
|
36
71
|
async def search(self, query: str) -> list[SearchResult]:
|
|
37
72
|
istek = await self.httpx.post(
|
|
@@ -39,55 +74,66 @@ class JetFilmizle(PluginBase):
|
|
|
39
74
|
data = {"s": query},
|
|
40
75
|
headers = {"Referer": f"{self.main_url}/"}
|
|
41
76
|
)
|
|
42
|
-
secici =
|
|
77
|
+
secici = HTMLParser(istek.text)
|
|
43
78
|
|
|
44
79
|
results = []
|
|
45
80
|
for article in secici.css("article.movie"):
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
81
|
+
# h2-h6 içindeki a linki
|
|
82
|
+
title_link = None
|
|
83
|
+
for h_tag in ["h2", "h3", "h4", "h5", "h6"]:
|
|
84
|
+
title_link = article.css_first(f"{h_tag} a")
|
|
85
|
+
if title_link:
|
|
86
|
+
break
|
|
87
|
+
|
|
88
|
+
link_el = article.css_first("a")
|
|
89
|
+
img_el = article.css_first("img")
|
|
90
|
+
|
|
91
|
+
title = self.clean_title(title_link.text(strip=True)) if title_link else None
|
|
92
|
+
href = link_el.attrs.get("href") if link_el else None
|
|
93
|
+
poster = (img_el.attrs.get("data-src") or img_el.attrs.get("src")) if img_el else None
|
|
49
94
|
|
|
50
95
|
if title and href:
|
|
51
|
-
results.append(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
)
|
|
57
|
-
)
|
|
96
|
+
results.append(SearchResult(
|
|
97
|
+
title = title,
|
|
98
|
+
url = self.fix_url(href),
|
|
99
|
+
poster = self.fix_url(poster) if poster else None,
|
|
100
|
+
))
|
|
58
101
|
|
|
59
102
|
return results
|
|
60
103
|
|
|
61
104
|
async def load_item(self, url: str) -> MovieInfo:
|
|
62
105
|
istek = await self.httpx.get(url)
|
|
63
|
-
secici =
|
|
106
|
+
secici = HTMLParser(istek.text)
|
|
107
|
+
html_text = istek.text
|
|
64
108
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
109
|
+
title_el = secici.css_first("div.movie-exp-title")
|
|
110
|
+
title = self.clean_title(title_el.text(strip=True)) if title_el else None
|
|
111
|
+
|
|
112
|
+
img_el = secici.css_first("section.movie-exp img")
|
|
113
|
+
poster_raw = (img_el.attrs.get("data-src") or img_el.attrs.get("src")) if img_el else None
|
|
114
|
+
poster = poster_raw.strip() if poster_raw else None
|
|
71
115
|
|
|
72
|
-
|
|
116
|
+
desc_el = secici.css_first("section.movie-exp p.aciklama")
|
|
117
|
+
description = desc_el.text(strip=True) if desc_el else None
|
|
73
118
|
|
|
74
|
-
|
|
75
|
-
rating = rating_raw.strip() if rating_raw else None
|
|
119
|
+
tags = [a.text(strip=True) for a in secici.css("section.movie-exp div.catss a") if a.text(strip=True)]
|
|
76
120
|
|
|
121
|
+
rating_el = secici.css_first("section.movie-exp div.imdb_puan span")
|
|
122
|
+
rating = rating_el.text(strip=True) if rating_el else None
|
|
77
123
|
|
|
78
|
-
# Year - div.yap içinde 4 haneli sayı ara
|
|
79
|
-
year_div = secici.xpath("//div[@class='yap' and (contains(., 'Vizyon') or contains(., 'Yapım'))]/text()").get()
|
|
124
|
+
# Year - div.yap içinde 4 haneli sayı ara (xpath yerine regex)
|
|
80
125
|
year = None
|
|
81
|
-
|
|
82
|
-
|
|
126
|
+
yap_match = re.search(r'<div class="yap"[^>]*>([^<]*(?:Vizyon|Yapım)[^<]*)</div>', html_text, re.IGNORECASE)
|
|
127
|
+
if yap_match:
|
|
128
|
+
year_match = re.search(r'(\d{4})', yap_match.group(1))
|
|
83
129
|
if year_match:
|
|
84
130
|
year = year_match.group(1)
|
|
85
131
|
|
|
86
|
-
actors
|
|
132
|
+
actors = [a.text(strip=True) for a in secici.css("div[itemprop='actor'] a span") if a.text(strip=True)]
|
|
87
133
|
|
|
88
134
|
return MovieInfo(
|
|
89
135
|
url = url,
|
|
90
|
-
poster = self.fix_url(poster),
|
|
136
|
+
poster = self.fix_url(poster) if poster else None,
|
|
91
137
|
title = title,
|
|
92
138
|
description = description,
|
|
93
139
|
tags = tags,
|
|
@@ -98,15 +144,15 @@ class JetFilmizle(PluginBase):
|
|
|
98
144
|
|
|
99
145
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
100
146
|
istek = await self.httpx.get(url)
|
|
101
|
-
secici =
|
|
147
|
+
secici = HTMLParser(istek.text)
|
|
102
148
|
|
|
103
149
|
results = []
|
|
104
150
|
|
|
105
151
|
# 1) Ana iframe'leri kontrol et
|
|
106
152
|
for iframe in secici.css("iframe"):
|
|
107
|
-
src = (iframe.
|
|
108
|
-
iframe.
|
|
109
|
-
iframe.
|
|
153
|
+
src = (iframe.attrs.get("src") or
|
|
154
|
+
iframe.attrs.get("data-src") or
|
|
155
|
+
iframe.attrs.get("data-lazy-src"))
|
|
110
156
|
|
|
111
157
|
if src and src != "about:blank":
|
|
112
158
|
iframe_url = self.fix_url(src)
|
|
@@ -117,9 +163,10 @@ class JetFilmizle(PluginBase):
|
|
|
117
163
|
# 2) Sayfa numaralarından linkleri topla (Fragman hariç)
|
|
118
164
|
page_links = []
|
|
119
165
|
for link in secici.css("a.post-page-numbers"):
|
|
120
|
-
|
|
166
|
+
span_el = link.css_first("span")
|
|
167
|
+
isim = span_el.text(strip=True) if span_el else ""
|
|
121
168
|
if isim != "Fragman":
|
|
122
|
-
href = link.
|
|
169
|
+
href = link.attrs.get("href")
|
|
123
170
|
if href:
|
|
124
171
|
page_links.append((self.fix_url(href), isim))
|
|
125
172
|
|
|
@@ -127,12 +174,12 @@ class JetFilmizle(PluginBase):
|
|
|
127
174
|
for page_url, isim in page_links:
|
|
128
175
|
try:
|
|
129
176
|
page_resp = await self.httpx.get(page_url)
|
|
130
|
-
page_sel =
|
|
177
|
+
page_sel = HTMLParser(page_resp.text)
|
|
131
178
|
|
|
132
179
|
for iframe in page_sel.css("div#movie iframe"):
|
|
133
|
-
src = (iframe.
|
|
134
|
-
iframe.
|
|
135
|
-
iframe.
|
|
180
|
+
src = (iframe.attrs.get("src") or
|
|
181
|
+
iframe.attrs.get("data-src") or
|
|
182
|
+
iframe.attrs.get("data-lazy-src"))
|
|
136
183
|
|
|
137
184
|
if src and src != "about:blank":
|
|
138
185
|
iframe_url = self.fix_url(src)
|