KekikStream 2.2.2__py3-none-any.whl → 2.2.8__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.
Files changed (35) hide show
  1. KekikStream/Extractors/CloseLoad.py +47 -11
  2. KekikStream/Extractors/Filemoon.py +7 -6
  3. KekikStream/Extractors/MolyStream.py +6 -5
  4. KekikStream/Extractors/PlayerFilmIzle.py +6 -2
  5. KekikStream/Extractors/VidHide.py +0 -1
  6. KekikStream/Extractors/VidMoly.py +17 -9
  7. KekikStream/Plugins/BelgeselX.py +39 -20
  8. KekikStream/Plugins/DiziBox.py +115 -59
  9. KekikStream/Plugins/DiziPal.py +87 -40
  10. KekikStream/Plugins/DiziYou.py +105 -64
  11. KekikStream/Plugins/Dizilla.py +58 -29
  12. KekikStream/Plugins/FilmBip.py +60 -31
  13. KekikStream/Plugins/FilmMakinesi.py +75 -51
  14. KekikStream/Plugins/FilmModu.py +73 -36
  15. KekikStream/Plugins/FullHDFilm.py +82 -48
  16. KekikStream/Plugins/FullHDFilmizlesene.py +94 -39
  17. KekikStream/Plugins/HDFilmCehennemi.py +109 -88
  18. KekikStream/Plugins/JetFilmizle.py +78 -50
  19. KekikStream/Plugins/KultFilmler.py +64 -34
  20. KekikStream/Plugins/RoketDizi.py +43 -26
  21. KekikStream/Plugins/SelcukFlix.py +27 -14
  22. KekikStream/Plugins/SetFilmIzle.py +74 -43
  23. KekikStream/Plugins/SezonlukDizi.py +102 -46
  24. KekikStream/Plugins/Sinefy.py +130 -101
  25. KekikStream/Plugins/SinemaCX.py +82 -37
  26. KekikStream/Plugins/Sinezy.py +61 -47
  27. KekikStream/Plugins/SuperFilmGeldi.py +72 -36
  28. KekikStream/Plugins/UgurFilm.py +72 -34
  29. KekikStream/requirements.txt +1 -1
  30. {kekikstream-2.2.2.dist-info → kekikstream-2.2.8.dist-info}/METADATA +39 -32
  31. {kekikstream-2.2.2.dist-info → kekikstream-2.2.8.dist-info}/RECORD +35 -35
  32. {kekikstream-2.2.2.dist-info → kekikstream-2.2.8.dist-info}/WHEEL +0 -0
  33. {kekikstream-2.2.2.dist-info → kekikstream-2.2.8.dist-info}/entry_points.txt +0 -0
  34. {kekikstream-2.2.2.dist-info → kekikstream-2.2.8.dist-info}/licenses/LICENSE +0 -0
  35. {kekikstream-2.2.2.dist-info → kekikstream-2.2.8.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Subtitle, ExtractResult
4
- from parsel import Selector
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Subtitle, ExtractResult
4
+ from selectolax.parser import HTMLParser
5
5
  import re
6
6
 
7
7
  class SinemaCX(PluginBase):
@@ -39,57 +39,103 @@ class SinemaCX(PluginBase):
39
39
 
40
40
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
41
41
  istek = await self.httpx.get(url.replace("SAYFA", str(page)))
42
- secici = Selector(istek.text)
42
+ secici = HTMLParser(istek.text)
43
43
 
44
- return [
45
- MainPageResult(
44
+ results = []
45
+ for veri in secici.css("div.son div.frag-k, div.icerik div.frag-k"):
46
+ span_el = veri.css_first("div.yanac span")
47
+ if not span_el:
48
+ continue
49
+
50
+ title = span_el.text(strip=True)
51
+ if not title:
52
+ continue
53
+
54
+ link_el = veri.css_first("div.yanac a")
55
+ img_el = veri.css_first("a.resim img")
56
+
57
+ href = link_el.attrs.get("href") if link_el else None
58
+ poster = (img_el.attrs.get("data-src") or img_el.attrs.get("src")) if img_el else None
59
+
60
+ results.append(MainPageResult(
46
61
  category = category,
47
- title = veri.css("div.yanac span::text").get(),
48
- url = self.fix_url(veri.css("div.yanac a::attr(href)").get()),
49
- poster = self.fix_url(veri.css("a.resim img::attr(data-src)").get() or veri.css("a.resim img::attr(src)").get()),
50
- )
51
- for veri in secici.css("div.son div.frag-k, div.icerik div.frag-k")
52
- if veri.css("div.yanac span::text").get()
53
- ]
62
+ title = title,
63
+ url = self.fix_url(href) if href else "",
64
+ poster = self.fix_url(poster) if poster else None,
65
+ ))
66
+
67
+ return results
54
68
 
55
69
  async def search(self, query: str) -> list[SearchResult]:
56
70
  istek = await self.httpx.get(f"{self.main_url}/?s={query}")
57
- secici = Selector(istek.text)
58
-
59
- return [
60
- SearchResult(
61
- title = veri.css("div.yanac span::text").get(),
62
- url = self.fix_url(veri.css("div.yanac a::attr(href)").get()),
63
- poster = self.fix_url(veri.css("a.resim img::attr(data-src)").get() or veri.css("a.resim img::attr(src)").get()),
64
- )
65
- for veri in secici.css("div.icerik div.frag-k")
66
- if veri.css("div.yanac span::text").get()
67
- ]
71
+ secici = HTMLParser(istek.text)
72
+
73
+ results = []
74
+ for veri in secici.css("div.icerik div.frag-k"):
75
+ span_el = veri.css_first("div.yanac span")
76
+ if not span_el:
77
+ continue
78
+
79
+ title = span_el.text(strip=True)
80
+ if not title:
81
+ continue
82
+
83
+ link_el = veri.css_first("div.yanac a")
84
+ img_el = veri.css_first("a.resim img")
85
+
86
+ href = link_el.attrs.get("href") if link_el else None
87
+ poster = (img_el.attrs.get("data-src") or img_el.attrs.get("src")) if img_el else None
88
+
89
+ results.append(SearchResult(
90
+ title = title,
91
+ url = self.fix_url(href) if href else "",
92
+ poster = self.fix_url(poster) if poster else None,
93
+ ))
94
+
95
+ return results
68
96
 
69
97
  async def load_item(self, url: str) -> MovieInfo:
70
98
  istek = await self.httpx.get(url)
71
- secici = Selector(istek.text)
99
+ secici = HTMLParser(istek.text)
72
100
 
73
101
  duration_match = re.search(r"Süre:.*?(\d+)\s*Dakika", istek.text)
74
- description = secici.css("div.ackl div.scroll-liste::text").get()
102
+
103
+ desc_el = secici.css_first("div.ackl div.scroll-liste")
104
+ description = desc_el.text(strip=True) if desc_el else None
105
+
106
+ link_el = secici.css_first("link[rel='image_src']")
107
+ poster = link_el.attrs.get("href") if link_el else None
108
+
109
+ title_el = secici.css_first("div.f-bilgi h1")
110
+ title = title_el.text(strip=True) if title_el else None
111
+
112
+ tags = [a.text(strip=True) for a in secici.css("div.f-bilgi div.tur a") if a.text(strip=True)]
113
+
114
+ year_el = secici.css_first("div.f-bilgi ul.detay a[href*='yapim']")
115
+ year = year_el.text(strip=True) if year_el else None
116
+
117
+ actors = []
118
+ for li in secici.css("li.oync li.oyuncu-k"):
119
+ isim_el = li.css_first("span.isim")
120
+ if isim_el and isim_el.text(strip=True):
121
+ actors.append(isim_el.text(strip=True))
75
122
 
76
123
  return MovieInfo(
77
124
  url = url,
78
- poster = self.fix_url(secici.css("link[rel='image_src']::attr(href)").get()),
79
- title = secici.css("div.f-bilgi h1::text").get(),
80
- description = description.strip() if description else None,
81
- tags = [a.css("::text").get() for a in secici.css("div.f-bilgi div.tur a")],
82
- year = secici.css("div.f-bilgi ul.detay a[href*='yapim']::text").get(),
83
- actors = [li.css("span.isim::text").get() for li in secici.css("li.oync li.oyuncu-k")],
125
+ poster = self.fix_url(poster) if poster else None,
126
+ title = title,
127
+ description = description,
128
+ tags = tags,
129
+ year = year,
130
+ actors = actors,
84
131
  duration = int(duration_match[1]) if duration_match else None,
85
132
  )
86
133
 
87
134
  async def load_links(self, url: str) -> list[ExtractResult]:
88
135
  istek = await self.httpx.get(url)
89
- secici = Selector(istek.text)
136
+ secici = HTMLParser(istek.text)
90
137
 
91
- iframe_list = [iframe.css("::attr(data-vsrc)").get() for iframe in secici.css("iframe")]
92
- iframe_list = [i for i in iframe_list if i]
138
+ iframe_list = [iframe.attrs.get("data-vsrc") for iframe in secici.css("iframe") if iframe.attrs.get("data-vsrc")]
93
139
 
94
140
  # Sadece fragman varsa /2/ sayfasından dene
95
141
  has_only_trailer = all(
@@ -100,9 +146,8 @@ class SinemaCX(PluginBase):
100
146
  if has_only_trailer:
101
147
  alt_url = url.rstrip("/") + "/2/"
102
148
  alt_istek = await self.httpx.get(alt_url)
103
- alt_sec = Selector(alt_istek.text)
104
- iframe_list = [iframe.css("::attr(data-vsrc)").get() for iframe in alt_sec.css("iframe")]
105
- iframe_list = [i for i in iframe_list if i]
149
+ alt_sec = HTMLParser(alt_istek.text)
150
+ iframe_list = [iframe.attrs.get("data-vsrc") for iframe in alt_sec.css("iframe") if iframe.attrs.get("data-vsrc")]
106
151
 
107
152
  if not iframe_list:
108
153
  return []
@@ -1,7 +1,7 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
4
- from parsel import Selector
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
4
+ from selectolax.parser import HTMLParser
5
5
  import re, base64
6
6
 
7
7
  class Sinezy(PluginBase):
@@ -45,58 +45,72 @@ class Sinezy(PluginBase):
45
45
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
46
46
  full_url = f"{url}page/{page}/"
47
47
  resp = await self.httpx.get(full_url)
48
- sel = Selector(resp.text)
48
+ sel = HTMLParser(resp.text)
49
49
 
50
50
  results = []
51
51
  for item in sel.css("div.container div.content div.movie_box.move_k"):
52
- title = item.css("a::attr(title)").get()
53
- href = item.css("a::attr(href)").get()
54
- poster = item.css("img::attr(data-src)").get()
52
+ link_el = item.css_first("a")
53
+ img_el = item.css_first("img")
54
+
55
+ title = link_el.attrs.get("title") if link_el else None
56
+ href = link_el.attrs.get("href") if link_el else None
57
+ poster = img_el.attrs.get("data-src") if img_el else None
55
58
 
56
- if title and href:
57
- results.append(MainPageResult(
58
- category = category,
59
- title = title,
60
- url = self.fix_url(href),
61
- poster = self.fix_url(poster)
62
- ))
59
+ if title and href:
60
+ results.append(MainPageResult(
61
+ category = category,
62
+ title = title,
63
+ url = self.fix_url(href),
64
+ poster = self.fix_url(poster) if poster else None
65
+ ))
63
66
 
64
67
  return results
65
68
 
66
69
  async def search(self, query: str) -> list[SearchResult]:
67
70
  url = f"{self.main_url}/arama/?s={query}"
68
71
  resp = await self.httpx.get(url)
69
- sel = Selector(resp.text)
72
+ sel = HTMLParser(resp.text)
70
73
 
71
74
  results = []
72
75
  for item in sel.css("div.movie_box.move_k"):
73
- title = item.css("a::attr(title)").get()
74
- href = item.css("a::attr(href)").get()
75
- poster = item.css("img::attr(data-src)").get()
76
+ link_el = item.css_first("a")
77
+ img_el = item.css_first("img")
78
+
79
+ title = link_el.attrs.get("title") if link_el else None
80
+ href = link_el.attrs.get("href") if link_el else None
81
+ poster = img_el.attrs.get("data-src") if img_el else None
76
82
 
77
- if title and href:
78
- results.append(SearchResult(
79
- title = title,
80
- url = self.fix_url(href),
81
- poster = self.fix_url(poster)
82
- ))
83
+ if title and href:
84
+ results.append(SearchResult(
85
+ title = title,
86
+ url = self.fix_url(href),
87
+ poster = self.fix_url(poster) if poster else None
88
+ ))
83
89
 
84
90
  return results
85
91
 
86
92
  async def load_item(self, url: str) -> MovieInfo:
87
93
  resp = await self.httpx.get(url)
88
- sel = Selector(resp.text)
94
+ sel = HTMLParser(resp.text)
95
+
96
+ detail_el = sel.css_first("div.detail")
97
+ title = detail_el.attrs.get("title") if detail_el else None
98
+
99
+ poster_el = sel.css_first("div.move_k img")
100
+ poster = poster_el.attrs.get("data-src") if poster_el else None
101
+
102
+ desc_el = sel.css_first("div.desc.yeniscroll p")
103
+ description = desc_el.text(strip=True) if desc_el else None
89
104
 
90
- title = sel.css("div.detail::attr(title)").get()
91
- poster = sel.css("div.move_k img::attr(data-src)").get()
92
- description = sel.css("div.desc.yeniscroll p::text").get()
93
- rating = sel.css("span.info span.imdb::text").get()
105
+ rating_el = sel.css_first("span.info span.imdb")
106
+ rating = rating_el.text(strip=True) if rating_el else None
94
107
 
95
- tags = sel.css("div.detail span a::text").getall()
96
- actors = sel.css("span.oyn p::text").getall() # Might need splitting logic
108
+ tags = [a.text(strip=True) for a in sel.css("div.detail span a") if a.text(strip=True)]
109
+ actors = [p.text(strip=True) for p in sel.css("span.oyn p") if p.text(strip=True)]
97
110
 
98
111
  year = None
99
- info_text = sel.css("span.info::text").get()
112
+ info_el = sel.css_first("span.info")
113
+ info_text = info_el.text(strip=True) if info_el else ""
100
114
  if info_text:
101
115
  year_match = re.search(r'\b(19\d{2}|20\d{2})\b', info_text)
102
116
  if year_match:
@@ -104,7 +118,7 @@ class Sinezy(PluginBase):
104
118
 
105
119
  # Bulunamadıysa tüm sayfada ara
106
120
  if not year:
107
- all_text = " ".join(sel.css("::text").getall())
121
+ all_text = sel.body.text() if sel.body else ""
108
122
  year_match = re.search(r'\b(19\d{2}|20\d{2})\b', all_text)
109
123
  if year_match:
110
124
  year = year_match.group(1)
@@ -112,7 +126,7 @@ class Sinezy(PluginBase):
112
126
  return MovieInfo(
113
127
  title = title,
114
128
  url = url,
115
- poster = self.fix_url(poster),
129
+ poster = self.fix_url(poster) if poster else None,
116
130
  description = description,
117
131
  tags = tags,
118
132
  rating = rating,
@@ -125,19 +139,19 @@ class Sinezy(PluginBase):
125
139
 
126
140
  match = re.search(r"ilkpartkod\s*=\s*'([^']+)'", resp.text, re.IGNORECASE)
127
141
  if match:
128
- encoded = match.group(1)
129
- try:
130
- decoded = base64.b64decode(encoded).decode('utf-8')
131
- iframe_match = re.search(r'src="([^"]*)"', decoded)
132
-
133
- if iframe_match:
134
- iframe = iframe_match.group(1)
135
- iframe = self.fix_url(iframe)
136
-
137
- data = await self.extract(iframe)
138
- if data:
139
- return [data]
140
- except Exception:
141
- pass
142
+ encoded = match.group(1)
143
+ try:
144
+ decoded = base64.b64decode(encoded).decode('utf-8')
145
+ iframe_match = re.search(r'src="([^"]*)"', decoded)
146
+
147
+ if iframe_match:
148
+ iframe = iframe_match.group(1)
149
+ iframe = self.fix_url(iframe)
150
+
151
+ data = await self.extract(iframe)
152
+ if data:
153
+ return [data]
154
+ except Exception:
155
+ pass
142
156
 
143
157
  return []
@@ -1,7 +1,7 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
4
- from parsel import Selector
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 SuperFilmGeldi(PluginBase):
@@ -36,48 +36,83 @@ class SuperFilmGeldi(PluginBase):
36
36
 
37
37
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
38
38
  istek = await self.httpx.get(url.replace("SAYFA", str(page)))
39
- secici = Selector(istek.text)
39
+ secici = HTMLParser(istek.text)
40
40
 
41
- return [
42
- MainPageResult(
41
+ results = []
42
+ for veri in secici.css("div.movie-preview-content"):
43
+ link_el = veri.css_first("span.movie-title a")
44
+ if not link_el:
45
+ continue
46
+
47
+ title_text = link_el.text(strip=True)
48
+ if not title_text:
49
+ continue
50
+
51
+ img_el = veri.css_first("img")
52
+ href = link_el.attrs.get("href")
53
+ poster = img_el.attrs.get("src") if img_el else None
54
+
55
+ results.append(MainPageResult(
43
56
  category = category,
44
- title = self.clean_title(veri.css("span.movie-title a::text").get().split(" izle")[0]),
45
- url = self.fix_url(veri.css("span.movie-title a::attr(href)").get()),
46
- poster = self.fix_url(veri.css("img::attr(src)").get()),
47
- )
48
- for veri in secici.css("div.movie-preview-content")
49
- if veri.css("span.movie-title a::text").get()
50
- ]
57
+ title = self.clean_title(title_text.split(" izle")[0]),
58
+ url = self.fix_url(href) if href else "",
59
+ poster = self.fix_url(poster) if poster else None,
60
+ ))
61
+
62
+ return results
51
63
 
52
64
  async def search(self, query: str) -> list[SearchResult]:
53
65
  istek = await self.httpx.get(f"{self.main_url}?s={query}")
54
- secici = Selector(istek.text)
55
-
56
- return [
57
- SearchResult(
58
- title = self.clean_title(veri.css("span.movie-title a::text").get().split(" izle")[0]),
59
- url = self.fix_url(veri.css("span.movie-title a::attr(href)").get()),
60
- poster = self.fix_url(veri.css("img::attr(src)").get()),
61
- )
62
- for veri in secici.css("div.movie-preview-content")
63
- if veri.css("span.movie-title a::text").get()
64
- ]
66
+ secici = HTMLParser(istek.text)
67
+
68
+ results = []
69
+ for veri in secici.css("div.movie-preview-content"):
70
+ link_el = veri.css_first("span.movie-title a")
71
+ if not link_el:
72
+ continue
73
+
74
+ title_text = link_el.text(strip=True)
75
+ if not title_text:
76
+ continue
77
+
78
+ img_el = veri.css_first("img")
79
+ href = link_el.attrs.get("href")
80
+ poster = img_el.attrs.get("src") if img_el else None
81
+
82
+ results.append(SearchResult(
83
+ title = self.clean_title(title_text.split(" izle")[0]),
84
+ url = self.fix_url(href) if href else "",
85
+ poster = self.fix_url(poster) if poster else None,
86
+ ))
87
+
88
+ return results
65
89
 
66
90
  async def load_item(self, url: str) -> MovieInfo:
67
91
  istek = await self.httpx.get(url)
68
- secici = Selector(istek.text)
92
+ secici = HTMLParser(istek.text)
93
+
94
+ title_el = secici.css_first("div.title h1")
95
+ title = title_el.text(strip=True) if title_el else ""
96
+ title = self.clean_title(title.split(" izle")[0]) if title else ""
97
+
98
+ poster_el = secici.css_first("div.poster img")
99
+ poster = poster_el.attrs.get("src") if poster_el else None
69
100
 
70
- title = secici.css("div.title h1::text").get()
71
- title = self.clean_title(title.split(" izle")[0]) if title else ""
72
- poster = self.fix_url(secici.css("div.poster img::attr(src)").get())
73
- year = secici.css("div.release a::text").re_first(r"(\d{4})")
74
- description = secici.css("div.excerpt p::text").get()
75
- tags = secici.css("div.categories a::text").getall()
76
- actors = secici.css("div.actor a::text").getall()
101
+ # year: re_first kullanılamaz, re.search kullanıyoruz
102
+ year_el = secici.css_first("div.release a")
103
+ year_text = year_el.text(strip=True) if year_el else ""
104
+ year_match = re.search(r"(\d{4})", year_text)
105
+ year = year_match.group(1) if year_match else None
106
+
107
+ desc_el = secici.css_first("div.excerpt p")
108
+ description = desc_el.text(strip=True) if desc_el else None
109
+
110
+ tags = [a.text(strip=True) for a in secici.css("div.categories a") if a.text(strip=True)]
111
+ actors = [a.text(strip=True) for a in secici.css("div.actor a") if a.text(strip=True)]
77
112
 
78
113
  return MovieInfo(
79
114
  url = url,
80
- poster = poster,
115
+ poster = self.fix_url(poster) if poster else None,
81
116
  title = title,
82
117
  description = description,
83
118
  tags = tags,
@@ -86,12 +121,13 @@ class SuperFilmGeldi(PluginBase):
86
121
  )
87
122
 
88
123
  async def load_links(self, url: str) -> list[ExtractResult]:
89
- from KekikStream.Core import ExtractResult
90
-
91
124
  istek = await self.httpx.get(url)
92
- secici = Selector(istek.text)
125
+ secici = HTMLParser(istek.text)
126
+
127
+ iframe_el = secici.css_first("div#vast iframe")
128
+ iframe = iframe_el.attrs.get("src") if iframe_el else None
129
+ iframe = self.fix_url(iframe) if iframe else None
93
130
 
94
- iframe = self.fix_url(secici.css("div#vast iframe::attr(src)").get())
95
131
  if not iframe:
96
132
  return []
97
133
 
@@ -1,7 +1,8 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
4
- from parsel import Selector
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
4
+ from selectolax.parser import HTMLParser
5
+ import re
5
6
 
6
7
  class UgurFilm(PluginBase):
7
8
  name = "UgurFilm"
@@ -25,53 +26,86 @@ class UgurFilm(PluginBase):
25
26
 
26
27
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
27
28
  istek = await self.httpx.get(f"{url}{page}", follow_redirects=True)
28
- secici = Selector(istek.text)
29
+ secici = HTMLParser(istek.text)
29
30
 
30
- return [
31
- MainPageResult(
31
+ results = []
32
+ for veri in secici.css("div.icerik div"):
33
+ # Title is in the second span (a.baslik > span), not the first span (class="sol" which is empty)
34
+ title_el = veri.css_first("a.baslik span")
35
+ title = title_el.text(strip=True) if title_el else None
36
+ if not title:
37
+ continue
38
+
39
+ link_el = veri.css_first("a")
40
+ img_el = veri.css_first("img")
41
+
42
+ href = link_el.attrs.get("href") if link_el else None
43
+ poster = img_el.attrs.get("src") if img_el else None
44
+
45
+ results.append(MainPageResult(
32
46
  category = category,
33
- title = veri.css("span:nth-child(1)::text").get(),
34
- url = self.fix_url(veri.css("a::attr(href)").get()),
35
- poster = self.fix_url(veri.css("img::attr(src)").get()),
36
- )
37
- for veri in secici.css("div.icerik div") if veri.css("span:nth-child(1)::text").get()
38
- ]
47
+ title = title,
48
+ url = self.fix_url(href) if href else "",
49
+ poster = self.fix_url(poster) if poster else None,
50
+ ))
51
+
52
+ return results
39
53
 
40
54
  async def search(self, query: str) -> list[SearchResult]:
41
55
  istek = await self.httpx.get(f"{self.main_url}/?s={query}")
42
- secici = Selector(istek.text)
56
+ secici = HTMLParser(istek.text)
43
57
 
44
58
  results = []
45
59
  for film in secici.css("div.icerik div"):
46
- title = film.css("span:nth-child(1)::text").get()
47
- href = film.css("a::attr(href)").get()
48
- poster = film.css("img::attr(src)").get()
60
+ # Title is in a.baslik > span, not the first span
61
+ title_el = film.css_first("a.baslik span")
62
+ title = title_el.text(strip=True) if title_el else None
63
+
64
+ link_el = film.css_first("a")
65
+ img_el = film.css_first("img")
66
+
67
+ href = link_el.attrs.get("href") if link_el else None
68
+ poster = img_el.attrs.get("src") if img_el else None
49
69
 
50
70
  if title and href:
51
- results.append(
52
- SearchResult(
53
- title = title.strip(),
54
- url = self.fix_url(href.strip()),
55
- poster = self.fix_url(poster.strip()) if poster else None,
56
- )
57
- )
71
+ results.append(SearchResult(
72
+ title = title.strip(),
73
+ url = self.fix_url(href.strip()),
74
+ poster = self.fix_url(poster.strip()) if poster else None,
75
+ ))
58
76
 
59
77
  return results
60
78
 
61
79
  async def load_item(self, url: str) -> MovieInfo:
62
80
  istek = await self.httpx.get(url)
63
- secici = Selector(istek.text)
81
+ secici = HTMLParser(istek.text)
82
+
83
+ title_el = secici.css_first("div.bilgi h2")
84
+ title = title_el.text(strip=True) if title_el else ""
85
+
86
+ poster_el = secici.css_first("div.resim img")
87
+ poster = poster_el.attrs.get("src", "").strip() if poster_el else ""
88
+
89
+ desc_el = secici.css_first("div.slayt-aciklama")
90
+ description = desc_el.text(strip=True) if desc_el else ""
64
91
 
65
- title = secici.css("div.bilgi h2::text").get().strip()
66
- poster = secici.css("div.resim img::attr(src)").get().strip()
67
- description = secici.css("div.slayt-aciklama::text").get().strip()
68
- tags = secici.css("p.tur a[href*='/category/']::text").getall()
69
- year = secici.css("a[href*='/yil/']::text").re_first(r"\d+")
70
- actors = [actor.css("span::text").get() for actor in secici.css("li.oyuncu-k")]
92
+ tags = [a.text(strip=True) for a in secici.css("p.tur a[href*='/category/']") if a.text(strip=True)]
93
+
94
+ # re_first yerine re.search
95
+ year_el = secici.css_first("a[href*='/yil/']")
96
+ year_text = year_el.text(strip=True) if year_el else ""
97
+ year_match = re.search(r"\d+", year_text)
98
+ year = year_match.group() if year_match else None
99
+
100
+ actors = []
101
+ for actor in secici.css("li.oyuncu-k"):
102
+ span_el = actor.css_first("span")
103
+ if span_el and span_el.text(strip=True):
104
+ actors.append(span_el.text(strip=True))
71
105
 
72
106
  return MovieInfo(
73
107
  url = self.fix_url(url),
74
- poster = self.fix_url(poster),
108
+ poster = self.fix_url(poster) if poster else None,
75
109
  title = title,
76
110
  description = description,
77
111
  tags = tags,
@@ -81,14 +115,18 @@ class UgurFilm(PluginBase):
81
115
 
82
116
  async def load_links(self, url: str) -> list[ExtractResult]:
83
117
  istek = await self.httpx.get(url)
84
- secici = Selector(istek.text)
118
+ secici = HTMLParser(istek.text)
85
119
  results = []
86
120
 
87
- for part_link in secici.css("li.parttab a::attr(href)").getall():
121
+ part_links = [a.attrs.get("href") for a in secici.css("li.parttab a") if a.attrs.get("href")]
122
+
123
+ for part_link in part_links:
88
124
  sub_response = await self.httpx.get(part_link)
89
- sub_selector = Selector(sub_response.text)
125
+ sub_selector = HTMLParser(sub_response.text)
126
+
127
+ iframe_el = sub_selector.css_first("div#vast iframe")
128
+ iframe = iframe_el.attrs.get("src") if iframe_el else None
90
129
 
91
- iframe = sub_selector.css("div#vast iframe::attr(src)").get()
92
130
  if iframe and self.main_url in iframe:
93
131
  post_data = {
94
132
  "vid" : iframe.split("vid=")[-1],
@@ -3,7 +3,7 @@ wheel
3
3
  Kekik
4
4
  httpx
5
5
  cloudscraper
6
- parsel
6
+ selectolax
7
7
  pydantic
8
8
  InquirerPy
9
9
  yt-dlp