KekikStream 2.2.3__py3-none-any.whl → 2.2.5__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/MolyStream.py +6 -5
- 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 +57 -28
- 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 +78 -53
- KekikStream/Plugins/JetFilmizle.py +78 -50
- KekikStream/Plugins/KultFilmler.py +64 -34
- KekikStream/Plugins/RoketDizi.py +43 -26
- KekikStream/Plugins/SelcukFlix.py +27 -14
- KekikStream/Plugins/SetFilmIzle.py +69 -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.2.3.dist-info → kekikstream-2.2.5.dist-info}/METADATA +2 -2
- {kekikstream-2.2.3.dist-info → kekikstream-2.2.5.dist-info}/RECORD +34 -34
- {kekikstream-2.2.3.dist-info → kekikstream-2.2.5.dist-info}/WHEEL +0 -0
- {kekikstream-2.2.3.dist-info → kekikstream-2.2.5.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.2.3.dist-info → kekikstream-2.2.5.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.2.3.dist-info → kekikstream-2.2.5.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,
|
|
@@ -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,7 @@
|
|
|
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
5
|
import re
|
|
6
6
|
|
|
7
7
|
class JetFilmizle(PluginBase):
|
|
@@ -40,17 +40,33 @@ class JetFilmizle(PluginBase):
|
|
|
40
40
|
|
|
41
41
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
42
42
|
istek = await self.httpx.get(f"{url}{page}", follow_redirects=True)
|
|
43
|
-
secici =
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
54
70
|
|
|
55
71
|
async def search(self, query: str) -> list[SearchResult]:
|
|
56
72
|
istek = await self.httpx.post(
|
|
@@ -58,55 +74,66 @@ class JetFilmizle(PluginBase):
|
|
|
58
74
|
data = {"s": query},
|
|
59
75
|
headers = {"Referer": f"{self.main_url}/"}
|
|
60
76
|
)
|
|
61
|
-
secici =
|
|
77
|
+
secici = HTMLParser(istek.text)
|
|
62
78
|
|
|
63
79
|
results = []
|
|
64
80
|
for article in secici.css("article.movie"):
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
|
68
94
|
|
|
69
95
|
if title and href:
|
|
70
|
-
results.append(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
)
|
|
76
|
-
)
|
|
96
|
+
results.append(SearchResult(
|
|
97
|
+
title = title,
|
|
98
|
+
url = self.fix_url(href),
|
|
99
|
+
poster = self.fix_url(poster) if poster else None,
|
|
100
|
+
))
|
|
77
101
|
|
|
78
102
|
return results
|
|
79
103
|
|
|
80
104
|
async def load_item(self, url: str) -> MovieInfo:
|
|
81
105
|
istek = await self.httpx.get(url)
|
|
82
|
-
secici =
|
|
106
|
+
secici = HTMLParser(istek.text)
|
|
107
|
+
html_text = istek.text
|
|
83
108
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
|
90
115
|
|
|
91
|
-
|
|
116
|
+
desc_el = secici.css_first("section.movie-exp p.aciklama")
|
|
117
|
+
description = desc_el.text(strip=True) if desc_el else None
|
|
92
118
|
|
|
93
|
-
|
|
94
|
-
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)]
|
|
95
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
|
|
96
123
|
|
|
97
|
-
# Year - div.yap içinde 4 haneli sayı ara
|
|
98
|
-
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)
|
|
99
125
|
year = None
|
|
100
|
-
|
|
101
|
-
|
|
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))
|
|
102
129
|
if year_match:
|
|
103
130
|
year = year_match.group(1)
|
|
104
131
|
|
|
105
|
-
actors
|
|
132
|
+
actors = [a.text(strip=True) for a in secici.css("div[itemprop='actor'] a span") if a.text(strip=True)]
|
|
106
133
|
|
|
107
134
|
return MovieInfo(
|
|
108
135
|
url = url,
|
|
109
|
-
poster = self.fix_url(poster),
|
|
136
|
+
poster = self.fix_url(poster) if poster else None,
|
|
110
137
|
title = title,
|
|
111
138
|
description = description,
|
|
112
139
|
tags = tags,
|
|
@@ -117,15 +144,15 @@ class JetFilmizle(PluginBase):
|
|
|
117
144
|
|
|
118
145
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
119
146
|
istek = await self.httpx.get(url)
|
|
120
|
-
secici =
|
|
147
|
+
secici = HTMLParser(istek.text)
|
|
121
148
|
|
|
122
149
|
results = []
|
|
123
150
|
|
|
124
151
|
# 1) Ana iframe'leri kontrol et
|
|
125
152
|
for iframe in secici.css("iframe"):
|
|
126
|
-
src = (iframe.
|
|
127
|
-
iframe.
|
|
128
|
-
iframe.
|
|
153
|
+
src = (iframe.attrs.get("src") or
|
|
154
|
+
iframe.attrs.get("data-src") or
|
|
155
|
+
iframe.attrs.get("data-lazy-src"))
|
|
129
156
|
|
|
130
157
|
if src and src != "about:blank":
|
|
131
158
|
iframe_url = self.fix_url(src)
|
|
@@ -136,9 +163,10 @@ class JetFilmizle(PluginBase):
|
|
|
136
163
|
# 2) Sayfa numaralarından linkleri topla (Fragman hariç)
|
|
137
164
|
page_links = []
|
|
138
165
|
for link in secici.css("a.post-page-numbers"):
|
|
139
|
-
|
|
166
|
+
span_el = link.css_first("span")
|
|
167
|
+
isim = span_el.text(strip=True) if span_el else ""
|
|
140
168
|
if isim != "Fragman":
|
|
141
|
-
href = link.
|
|
169
|
+
href = link.attrs.get("href")
|
|
142
170
|
if href:
|
|
143
171
|
page_links.append((self.fix_url(href), isim))
|
|
144
172
|
|
|
@@ -146,12 +174,12 @@ class JetFilmizle(PluginBase):
|
|
|
146
174
|
for page_url, isim in page_links:
|
|
147
175
|
try:
|
|
148
176
|
page_resp = await self.httpx.get(page_url)
|
|
149
|
-
page_sel =
|
|
177
|
+
page_sel = HTMLParser(page_resp.text)
|
|
150
178
|
|
|
151
179
|
for iframe in page_sel.css("div#movie iframe"):
|
|
152
|
-
src = (iframe.
|
|
153
|
-
iframe.
|
|
154
|
-
iframe.
|
|
180
|
+
src = (iframe.attrs.get("src") or
|
|
181
|
+
iframe.attrs.get("data-src") or
|
|
182
|
+
iframe.attrs.get("data-lazy-src"))
|
|
155
183
|
|
|
156
184
|
if src and src != "about:blank":
|
|
157
185
|
iframe_url = self.fix_url(src)
|