├── README.md
├── cron_releases.sh
├── digitalreleases.py
└── digitalreleases2.py
/README.md:
--------------------------------------------------------------------------------
1 | # torrentReleases
2 | Следим за качественными цифровыми релизами фильмов без суеты
3 |
4 | Полное описание с подробностями читайте по ссылке:
5 | https://habr.com/ru/post/443584/
6 |
--------------------------------------------------------------------------------
/cron_releases.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | for i in $(seq 1 5); do
4 | /opt/bin/python3 /opt/etc/movies/digitalreleases2.py > /opt/etc/movies/log.txt
5 | ret=$?
6 | if [ $ret -eq 0 ]; then
7 | logger -t "digitalreleases.py" "Загрузка завершена успешно."
8 | break
9 | else
10 | logger -t "digitalreleases.py" "Ошибка загрузки."
11 | fi
12 | done
--------------------------------------------------------------------------------
/digitalreleases.py:
--------------------------------------------------------------------------------
1 | ### DAYS — за сколько последних дней загружать цифровые релизы. По умолчанию 60.
2 | ### SOCKS_IP и SOCKS_PORT — IP-адрес и порт SOCKS Proxy. Если они указаны, то будет импортирована библиотека (PySocks), а в функции rutorLinks запросы будет обрабатываться через указанный прокси-сервер. В digitalReleases и filmDetail запросы всегда идут без прокси.
3 | ### SORT_TYPE — тип финальной сортировки. rating — сортировка по рейтингу, releaseDate — сортировка по дате цифрового релиза, torrentsDate — сортировка по дате появления торрента, comboDate — сортировка по комбинированное дате (наибольшая из releaseDate и torrentsDate).
4 | ### USE_MAGNET — использование Magnet-ссылок вместо ссылок на торрент-файлы.
5 |
6 |
7 | ### digitalReleases(days) возвращает массив со словарями {filmID, releaseDate}, цифровые релизы за количество дней days.
8 | ### filmDetail(filmID) возвращает словарь с информацией по фильму, соответствующему filmID.
9 | ### rutorLinks(filmID) возвращает словарь с раздачами, соответствующими filmID.
10 | ### saveHTML(movies, filePath) формирует HTML-файл по пути filePath из массива movies.
11 | ### main объединяет всё вместе digitalReleases > rutorLinks + filmDetail > saveHTML.
12 |
13 | DAYS = 60
14 | USE_MAGNET = False
15 | SORT_TYPE = "rating"
16 | SOCKS_IP = ""
17 | SOCKS_PORT = 0
18 | HTML_SAVE_PATH = "/opt/share/www/releases.html"
19 | #HTML_SAVE_PATH = r"C:\Users\Yuri\releases.html"
20 |
21 |
22 | KINOPOISK_UUID = "6730382b7a236cd964264b49413ed00f" ### Генерируется автоматически в main, но можно в случае необходимости использовать константные значения.
23 | KINOPOISK_CLIENTID = "56decdcf6d4ad1bcaa1b3856" ### Генерируется автоматически в main, но можно в случае необходимости использовать константные значения.
24 | KINOPOISK_API_SALT = "IDATevHDS7"
25 | KINOPOISK_BASE_URL = "https://ma.kinopoisk.ru"
26 | KINOPOISK_API_RELEAESES = "/k/v1/films/releases/digital?digitalReleaseMonth={}&limit=1000&offset=0&uuid={}"
27 | KINOPOISK_BASE_URL2 = "https://ma.kinopoisk.ru/ios/5.0.0/"
28 | KINOPOISK_API_FILMDETAIL = "getKPFilmDetailView?still_limit=9&filmID={}&uuid={}"
29 | POSTER_URL = "https://st.kp.yandex.net/images/{}{}width=360"
30 | RUTOR_BASE_URL = "http://rutor.info/search/0/0/010/0/film%20"
31 |
32 | import hashlib
33 | import datetime
34 | import urllib.request
35 | from urllib.parse import urljoin
36 | import time
37 | import gzip
38 | import json
39 | import html
40 | import re
41 | import operator
42 | import os
43 | import binascii
44 | if SOCKS_IP:
45 | import socks
46 | import socket
47 |
48 | def digitalReleases(days):
49 | rDict = {}
50 | result = []
51 |
52 | currentDateReal = datetime.date.today()
53 | currentDate = currentDateReal + datetime.timedelta(days=7)
54 |
55 | print("Текущая дата (с запасом 7 дней): " + currentDate.strftime("%d.%m.%Y"))
56 | downloadDates =[currentDate]
57 | targetDate = datetime.date.today() - datetime.timedelta(days=days)
58 | print("Целевая дата: " + targetDate.strftime("%d.%m.%Y"))
59 | iterationDate = datetime.date.today() + datetime.timedelta(days=7)
60 |
61 | while (targetDate.year != iterationDate.year) or (targetDate.month != iterationDate.month):
62 | iterationDate = iterationDate.replace(day=1) - datetime.timedelta(days=1)
63 | downloadDates.append(iterationDate)
64 |
65 | print("Количество месяцев для загрузки: " + str(len(downloadDates)))
66 |
67 | for downloadDate in downloadDates:
68 | print("Загрузка релизов за " + downloadDate.strftime("%m.%Y") + ".")
69 |
70 | requestMethod = KINOPOISK_API_RELEAESES.format(downloadDate.strftime("%m.%Y"), KINOPOISK_UUID)
71 | timestamp = str(int(round(time.time() * 1000)))
72 | hashString = requestMethod + timestamp + KINOPOISK_API_SALT
73 |
74 | request = urllib.request.Request(KINOPOISK_BASE_URL + requestMethod)
75 | request.add_header("Accept-encoding", "gzip")
76 | request.add_header("Accept", "application/json")
77 | request.add_header("User-Agent", "Android client (6.0.1 / api23), ru.kinopoisk/4.6.5 (86)")
78 | request.add_header("Image-Scale", "3")
79 | request.add_header("device", "android")
80 | request.add_header("ClientId", KINOPOISK_CLIENTID)
81 | request.add_header("countryID", "2")
82 | request.add_header("cityID", "1")
83 | request.add_header("Android-Api-Version", "23")
84 | request.add_header("clientDate", datetime.date.today().strftime("%H:%M %d.%m.%Y"))
85 | request.add_header("X-TIMESTAMP", timestamp)
86 | request.add_header("X-SIGNATURE", hashlib.md5(hashString.encode('utf-8')).hexdigest())
87 |
88 | try:
89 | response = urllib.request.urlopen(request)
90 | except Exception:
91 | print("Ошибка соединения при загрузке релизов за " + downloadDate.strftime("%m.%Y") + ". Даём второй шанс.")
92 | response = urllib.request.urlopen(request)
93 |
94 | if response.info().get('Content-Encoding') == 'gzip':
95 | gzipFile = gzip.GzipFile(fileobj=response)
96 | content = gzipFile.read().decode("utf-8")
97 | else:
98 | content = response.read().decode("utf-8")
99 |
100 | if content:
101 | tmpDict = json.loads(content)
102 | if not tmpDict:
103 | raise ValueError("Ошибка загрузки релизов за " + downloadDate.strftime("%m.%Y") + ". Ответ не соответствует JSON.")
104 | if tmpDict.get("success") != True:
105 | raise ValueError("Ошибка загрузки релизов за " + downloadDate.strftime("%m.%Y") + ". В ответе нет значения success или оно равно False.")
106 | items = tmpDict.get("data")
107 | if items == None or not isinstance(items, dict):
108 | raise ValueError("Ошибка загрузки релизов за " + downloadDate.strftime("%m.%Y") + ". Проблемы со значением data.")
109 | items = items.get("items")
110 | if items == None or not isinstance(items, list):
111 | raise ValueError("Ошибка загрузки релизов за " + downloadDate.strftime("%m.%Y") + ". Проблемы со значением items.")
112 |
113 | for item in items:
114 | if not isinstance(item, dict):
115 | raise ValueError("Ошибка загрузки релизов за " + downloadDate.strftime("%m.%Y") + ". Проблемы с одним из элементов items.")
116 | filmID = item.get("id")
117 | if not isinstance(filmID, int):
118 | raise ValueError("Ошибка загрузки релизов за " + downloadDate.strftime("%m.%Y") + ". Проблемы с id в одном из элементов items.")
119 | contextData = item.get("contextData")
120 | if not isinstance(contextData, dict):
121 | raise ValueError("Ошибка загрузки релизов за " + downloadDate.strftime("%m.%Y") + ". Проблемы с contextData в одном из элементов items.")
122 | releaseDateStr = contextData.get("releaseDate")
123 | if not isinstance(releaseDateStr, str):
124 | raise ValueError("Ошибка загрузки релизов за " + downloadDate.strftime("%m.%Y") + ". Проблемы с releaseDate в одном из элементов items.")
125 | releaseDate = datetime.datetime.strptime(releaseDateStr, "%Y-%m-%d").date()
126 |
127 | if (targetDate <= releaseDate) and (releaseDate <= currentDate):
128 | rDict[str(filmID)] = releaseDate
129 | else:
130 | raise ValueError("Ошибка загрузки релизов за " + downloadDate.strftime("%m.%Y") + ".")
131 |
132 | print("Загружены ID от {} релизов.".format(len(rDict)))
133 |
134 | for key, value in rDict.items():
135 | temp = {"filmID": key, "releaseDate":value}
136 | result.append(temp)
137 |
138 | return result
139 |
140 | def filmDetail(filmID):
141 | print("Загрузка данных для filmID " + filmID + ".")
142 |
143 | result = {}
144 |
145 | requestMethod = KINOPOISK_API_FILMDETAIL.format(filmID, KINOPOISK_UUID)
146 | timestamp = str(int(round(time.time() * 1000)))
147 | hashString = requestMethod + timestamp + KINOPOISK_API_SALT
148 |
149 | request = urllib.request.Request(KINOPOISK_BASE_URL2 + requestMethod)
150 | request.add_header("Accept-encoding", "gzip")
151 | request.add_header("Accept", "application/json")
152 | request.add_header("User-Agent", "Android client (6.0.1 / api23), ru.kinopoisk/4.6.5 (86)")
153 | request.add_header("Image-Scale", "3")
154 | request.add_header("device", "android")
155 | request.add_header("ClientId", KINOPOISK_CLIENTID)
156 | request.add_header("countryID", "2")
157 | request.add_header("cityID", "1")
158 | request.add_header("Android-Api-Version", "23")
159 | request.add_header("clientDate", datetime.date.today().strftime("%H:%M %d.%m.%Y"))
160 | request.add_header("X-TIMESTAMP", timestamp)
161 | request.add_header("X-SIGNATURE", hashlib.md5(hashString.encode('utf-8')).hexdigest())
162 |
163 | try:
164 | response = urllib.request.urlopen(request)
165 | except Exception:
166 | print("Ошибка соединения при загрузке данных для filmID " + filmID + ". Даём второй шанс.")
167 | response = urllib.request.urlopen(request)
168 |
169 | if response.info().get('Content-Encoding') == 'gzip':
170 | gzipFile = gzip.GzipFile(fileobj=response)
171 | content = gzipFile.read().decode("utf-8")
172 | else:
173 | content = response.read().decode("utf-8")
174 |
175 | if content:
176 | tmpDict = json.loads(content)
177 | #print(tmpDict)
178 |
179 | if not tmpDict:
180 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Ответ не соответствует JSON.")
181 | if tmpDict.get("resultCode") != 0:
182 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". В ответе нет значения resultCode или оно не равно 0.")
183 | itemData = tmpDict.get("data")
184 | if itemData == None or not isinstance(itemData, dict):
185 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением data.")
186 | nameRU = itemData.get("nameRU")
187 | if nameRU == None or not isinstance(nameRU, str):
188 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением nameRU.")
189 | nameEN = itemData.get("nameEN")
190 | if nameEN == None or not isinstance(nameEN, str):
191 | nameEN = ""
192 | year = itemData.get("year")
193 | if year == None or not isinstance(year, str):
194 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением year.")
195 | country = itemData.get("country")
196 | if country == None or not isinstance(country, str):
197 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением country.")
198 | genre = itemData.get("genre")
199 | if genre == None or not isinstance(genre, str):
200 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением genre.")
201 | description = itemData.get("description")
202 | if description == None or not isinstance(description, str):
203 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением description.")
204 | ratingAgeLimits = itemData.get("ratingAgeLimits")
205 | if ratingAgeLimits == None or not isinstance(ratingAgeLimits, str):
206 | ratingAgeLimits = ""
207 | posterURL = itemData.get("posterURL")
208 | if posterURL == None or not isinstance(posterURL, str):
209 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением posterURL.")
210 | if "?" in posterURL:
211 | posterURL = POSTER_URL.format(posterURL, "&")
212 | else:
213 | posterURL = POSTER_URL.format(posterURL, "?")
214 | filmLength = itemData.get("filmLength")
215 | if filmLength == None or not isinstance(filmLength, str):
216 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением filmLength.")
217 | ratingData = itemData.get("ratingData")
218 | if ratingData == None or not isinstance(ratingData, dict):
219 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением ratingData.")
220 | ratingKP = ratingData.get("rating")
221 | if ratingKP == None or not isinstance(ratingKP, str):
222 | ratingKP = ""
223 | ratingIMDb = ratingData.get("ratingIMDb")
224 | if ratingIMDb == None or not isinstance(ratingIMDb, str):
225 | ratingIMDb = ""
226 | webURL = itemData.get("webURL")
227 | if webURL == None or not isinstance(webURL, str):
228 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением webURL.")
229 |
230 |
231 | directors = []
232 | actors = []
233 |
234 | creators = itemData.get("creators")
235 | if creators == None or not isinstance(creators, list):
236 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением creators.")
237 | for personsGroup in creators:
238 | if not isinstance(personsGroup, list):
239 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением creators > personsGroup.")
240 | for person in personsGroup:
241 | if not isinstance(person, dict):
242 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением creators > personsGroup > person.")
243 | if person.get("professionKey") == "director":
244 | if person.get("nameRU"):
245 | directors.append(person.get("nameRU"))
246 | if person.get("professionKey") == "actor":
247 | if person.get("nameRU"):
248 | actors.append(person.get("nameRU"))
249 | else:
250 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ".")
251 |
252 | if ratingIMDb and ratingKP:
253 | rating = "{0:.1f}".format((float(ratingKP) + float(ratingIMDb)) / 2.0 + 0.001)
254 | elif ratingKP:
255 | rating = ratingKP
256 | elif ratingIMDb:
257 | rating = ratingIMDb
258 | else:
259 | rating = "0"
260 |
261 | directorsResult = ""
262 | if len(directors) > 0:
263 | for director in directors:
264 | directorsResult += director
265 | directorsResult += ", "
266 | if directorsResult.endswith(", "):
267 | directorsResult = directorsResult[:-2]
268 |
269 | actorsResult = ""
270 | if len(actors) > 0:
271 | for actor in actors:
272 | actorsResult += actor
273 | actorsResult += ", "
274 | if actorsResult.endswith(", "):
275 | actorsResult = actorsResult[:-2]
276 |
277 | result["filmID"] = filmID
278 | result["nameRU"] = nameRU
279 | result["nameOriginal"] = nameEN
280 | result["description"] = description
281 | result["year"] = year
282 | result["country"] = country
283 | result["genre"] = genre
284 | result["ratingAgeLimits"] = ratingAgeLimits
285 | result["posterURL"] = posterURL
286 | result["filmLength"] = filmLength
287 | result["ratingKP"] = ratingKP
288 | result["ratingIMDb"] = ratingIMDb
289 | result["rating"] = rating
290 | result["ratingFloat"] = float(rating)
291 | result["directors"] = directorsResult
292 | result["actors"] = actorsResult
293 | result["webURL"] = webURL
294 |
295 |
296 | #print(result)
297 |
298 | return result
299 |
300 | def rutorLinks(filmID):
301 | print("Загрузка торрент-ссылок для filmID " + filmID + ".")
302 |
303 | if SOCKS_IP:
304 | default_socket = socket.socket
305 | socks.set_default_proxy(socks.SOCKS5, SOCKS_IP, SOCKS_PORT)
306 | socket.socket = socks.socksocket
307 |
308 | request = urllib.request.Request(RUTOR_BASE_URL + filmID)
309 | request.add_header("Accept-encoding", "gzip")
310 | request.add_header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0")
311 |
312 | try:
313 | response = urllib.request.urlopen(request)
314 | except Exception:
315 | print("Ошибка соединения при загрузке торрент-ссылок для filmID " + filmID + ". Даём второй шанс.")
316 | response = urllib.request.urlopen(request)
317 | if response.info().get('Content-Encoding') == 'gzip':
318 | gzipFile = gzip.GzipFile(fileobj=response)
319 | content = gzipFile.read().decode("utf-8")
320 | else:
321 | content = response.read().decode("utf-8")
322 |
323 | if SOCKS_IP:
324 | socket.socket = default_socket
325 |
326 | strIndex = content.find("
")
327 | if strIndex != -1:
328 | content = content[strIndex:]
329 | else:
330 | raise IndexError("Ошибка загрузки торрент-ссылок для filmID " + filmID + ". Не найден блок с торрентами. Возможно, сайт rutor заблокирован.")
331 |
332 | strIndex = content.find("
")
333 | if strIndex != -1:
334 | content = content[:-(len(content) - strIndex)]
335 | else:
336 | raise IndexError("Ошибка загрузки торрент-ссылок для filmID " + filmID + ". Не найден блок с торрентами. Возможно, сайт rutor заблокирован.")
337 |
338 | patternLink = re.compile("")
339 | matches1 = re.findall(patternLink, content)
340 | patternName = re.compile("(.*?)")
341 | matches2 = re.findall(patternName, content)
342 | patternSeeders = re.compile("alt=\"S\" />(.*?)")
343 | matches3 = re.findall(patternSeeders, content)
344 | patternMagnet = re.compile("")
345 | matches4 = re.findall(patternMagnet, content)
346 | patternDate = re.compile("(.*?) | result["UHD BDRemux HDR"]["seeders"]:
393 | result["UHD BDRemux HDR"] = item #{"link": item["link"], "magnet": item["magnet"], "seeders": item["seeders"]}
394 | else:
395 | result["UHD BDRemux HDR"] = item
396 | #print("!UHD BDRemux HDR: " + tmpParts[0])
397 | else:
398 | if result.get("UHD BDRemux SDR") != None:
399 | if item["seeders"] > result["UHD BDRemux SDR"]["seeders"]:
400 | result["UHD BDRemux SDR"] = item
401 | else:
402 | result["UHD BDRemux SDR"] = item
403 | #print("!UHD BDRemux SDR: " + tmpParts[0])
404 | elif "BDREMUX" in realName:
405 | if result.get("BDRemux") != None:
406 | if item["seeders"] > result["BDRemux"]["seeders"]:
407 | result["BDRemux"] = item
408 | else:
409 | result["BDRemux"] = item
410 | #print("!BDRemux: " + tmpParts[0])
411 | elif "BDRIP-HEVC 1080" in realName:
412 | if result.get("BDRip-HEVC 1080p") != None:
413 | if item["seeders"] > result["BDRip-HEVC 1080p"]["seeders"]:
414 | result["BDRip-HEVC 1080p"] = item
415 | else:
416 | result["BDRip-HEVC 1080p"] = item
417 | #print("!BDRip-HEVC 1080p: " + tmpParts[0])
418 | elif "BDRIP 1080" in realName:
419 | if result.get("BDRip 1080p") != None:
420 | if item["seeders"] > result["BDRip 1080p"]["seeders"]:
421 | result["BDRip 1080p"] = item
422 | else:
423 | result["BDRip 1080p"] = item
424 | #print("!BDRip 1080p: " + tmpParts[0])
425 | elif "WEB-DL 2160" in realName:
426 | if "HDR" in tags:
427 | if result.get("WEB-DL 2160p HDR") != None:
428 | if item["seeders"] > result["WEB-DL 2160p HDR"]["seeders"]:
429 | result["WEB-DL 2160p HDR"] = item
430 | else:
431 | result["WEB-DL 2160p HDR"] = item
432 | #print("!WEB-DL 2160p HDR: " + tmpParts[0])
433 | else:
434 | if result.get("WEB-DL 2160p SDR") != None:
435 | if item["seeders"] > result["WEB-DL 2160p SDR"]["seeders"]:
436 | result["WEB-DL 2160p SDR"] = item
437 | else:
438 | result["WEB-DL 2160p SDR"] = item
439 | #print("!WEB-DL 2160p SDR: " + tmpParts[0])
440 | elif "WEB-DL 1080" in realName:
441 | if result.get("WEB-DL 1080p") != None:
442 | if item["seeders"] > result["WEB-DL 1080p"]["seeders"]:
443 | result["WEB-DL 1080p"] = item
444 | else:
445 | result["WEB-DL 1080p"] = item
446 | #print("!WEB-DL 1080p: " + tmpParts[0])
447 |
448 | if result.get("UHD BDRemux HDR") or result.get("UHD BDRemux SDR") or result.get("BDRip-HEVC 1080p") or result.get("BDRip 1080p"):
449 | result.pop("WEB-DL 2160p HDR", None)
450 | result.pop("WEB-DL 2160p SDR", None)
451 | result.pop("WEB-DL 1080p", None)
452 |
453 | finalResult = []
454 |
455 | if result.get("WEB-DL 1080p"):
456 | finalResult.append({"link": result["WEB-DL 1080p"]["link"], "magnet": result["WEB-DL 1080p"]["magnet"], "date": result["WEB-DL 1080p"]["date"], "type": "WEB-DL 1080p"})
457 | if result.get("WEB-DL 2160p HDR"):
458 | finalResult.append({"link": result["WEB-DL 2160p HDR"]["link"], "magnet": result["WEB-DL 2160p HDR"]["magnet"], "date": result["WEB-DL 2160p HDR"]["date"], "type": "WEB-DL 2160p HDR"})
459 | elif result.get("WEB-DL 2160p SDR"):
460 | finalResult.append({"link": result["WEB-DL 2160p SDR"]["link"], "magnet": result["WEB-DL 2160p SDR"]["magnet"], "date": result["WEB-DL 2160p SDR"]["date"], "type": "WEB-DL 2160p SDR"})
461 | if result.get("BDRip 1080p"):
462 | finalResult.append({"link": result["BDRip 1080p"]["link"], "magnet": result["BDRip 1080p"]["magnet"], "date": result["BDRip 1080p"]["date"], "type": "BDRip 1080p"})
463 | if result.get("BDRip-HEVC 1080p"):
464 | finalResult.append({"link": result["BDRip-HEVC 1080p"]["link"], "magnet": result["BDRip-HEVC 1080p"]["magnet"], "date": result["BDRip-HEVC 1080p"]["date"], "type": "BDRip-HEVC 1080p"})
465 | if result.get("BDRemux"):
466 | finalResult.append({"link": result["BDRemux"]["link"], "magnet": result["BDRemux"]["magnet"], "date": result["BDRemux"]["date"], "type": "BDRemux"})
467 | if result.get("UHD BDRemux HDR"):
468 | finalResult.append({"link": result["UHD BDRemux HDR"]["link"], "magnet": result["UHD BDRemux HDR"]["magnet"], "date": result["UHD BDRemux HDR"]["date"], "type": "UHD BDRemux HDR"})
469 | elif result.get("UHD BDRemux SDR"):
470 | finalResult.append({"link": result["UHD BDRemux SDR"]["link"], "magnet": result["UHD BDRemux SDR"]["magnet"], "date": result["UHD BDRemux SDR"]["date"], "type": "UHD BDRemux SDR"})
471 |
472 | #print(finalResult)
473 |
474 | return finalResult
475 |
476 | def saveHTML(movies, filePath):
477 | f = open(filePath,'w', encoding='utf-8')
478 | html = """
479 |
480 |
481 |
482 |
483 | Новые цифровые релизы
484 |
737 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 | """
818 | descriptionTemplate = """
819 |
820 | | {} |
821 |
822 |
823 | {}
824 |
825 | |
826 | """
827 | buttonsTemplate = """ """
828 | movieTemplate = """
829 |
830 |
834 |
835 |
836 | {}
837 | 
838 |
839 |
840 |
841 |
842 |
843 | {}
844 |
845 |
846 |
847 |
848 |
849 | {}
850 |
851 |
852 | """
853 | for movie in movies:
854 | #print(movie["nameRU"])
855 | #print(movie["torrentsDate"])
856 | #print(movie["releaseDate"])
857 |
858 | descriptionBlock = ""
859 | descriptionBlock += descriptionTemplate.format("год", movie["year"])
860 | descriptionBlock += descriptionTemplate.format("страна", movie["country"])
861 | descriptionBlock += descriptionTemplate.format("режиссёр", movie["directors"])
862 | descriptionBlock += descriptionTemplate.format("актёры", movie["actors"])
863 | descriptionBlock += descriptionTemplate.format("жанр", movie["genre"])
864 | if len(movie["ratingAgeLimits"]) > 0:
865 | if int(movie["ratingAgeLimits"]) <= 6:
866 | descriptionBlock += descriptionTemplate.format("возраст", "от 6 лет")
867 | elif int(movie["ratingAgeLimits"]) <= 12:
868 | descriptionBlock += descriptionTemplate.format("возраст", "от 12 лет")
869 | elif int(movie["ratingAgeLimits"]) <= 16:
870 | descriptionBlock += descriptionTemplate.format("возраст", "от 16 лет")
871 | elif int(movie["ratingAgeLimits"]) <= 18:
872 | descriptionBlock += descriptionTemplate.format("возраст", "от 18 лет")
873 | #descriptionBlock += descriptionTemplate.format("возраст", movie["ratingAgeLimits"] + " и старше")
874 | descriptionBlock += descriptionTemplate.format("продолжительность", movie["filmLength"])
875 | if len(movie["ratingKP"]) > 0:
876 | rKP = movie["ratingKP"]
877 | else:
878 | rKP = "отсутствует"
879 | descriptionBlock += descriptionTemplate.format("рейтинг КиноПоиск", " {}".format(movie["webURL"], rKP))
880 | if len(movie["ratingIMDb"]) > 0:
881 | descriptionBlock += descriptionTemplate.format("рейтинг IMDb", movie["ratingIMDb"])
882 | descriptionBlock += descriptionTemplate.format("цифровой релиз", movie["releaseDate"].strftime("%d.%m.%Y"))
883 |
884 | descriptionBlock += descriptionTemplate.format("торрент-релиз", " {}".format(RUTOR_BASE_URL + movie["filmID"], movie["torrentsDate"].strftime("%d.%m.%Y")))
885 | descriptionBlock += descriptionTemplate.format("описание", movie["description"])
886 |
887 |
888 | torrents = movie["torrents"]
889 | buttonsBlock = ""
890 | for torrent in torrents:
891 | if USE_MAGNET:
892 | buttonsBlock += buttonsTemplate.format(torrent["magnet"], torrent["type"])
893 | else:
894 | buttonsBlock += buttonsTemplate.format(torrent["link"], torrent["type"])
895 |
896 | displayOrigName = "display: none;"
897 | if len(movie["nameOriginal"]) > 0:
898 | displayOrigName = ""
899 |
900 | ratingColor = "#aaa"
901 | if movie["ratingFloat"] >= 7:
902 | ratingColor = "#3bb33b"
903 | elif movie["ratingFloat"] < 5.5:
904 | ratingColor = "#b43c3c"
905 |
906 | html += movieTemplate.format(movie["releaseDate"].strftime("%Y-%m-%d"), movie["torrentsDate"].strftime("%Y-%m-%d"), movie["rating"], movie["comboDate"].strftime("%Y-%m-%d"), movie["nameRU"], displayOrigName, movie["nameOriginal"], ratingColor, movie["rating"], movie["posterURL"], movie["nameRU"], descriptionBlock, buttonsBlock)
907 |
908 | html += """
909 |
910 |
911 | """
912 | f.write(html)
913 | f.close()
914 | return
915 |
916 | def main():
917 | KINOPOISK_UUID = binascii.b2a_hex(os.urandom(16))
918 | KINOPOISK_CLIENTID = binascii.b2a_hex(os.urandom(12))
919 |
920 | releases = digitalReleases(DAYS)
921 | movies = []
922 |
923 | for release in releases:
924 | torrents = rutorLinks(release["filmID"])
925 | if len(torrents) == 0:
926 | continue
927 |
928 | dates = []
929 | for torrent in torrents:
930 | dates.append(torrent["date"])
931 | dates.sort()
932 |
933 | detail = filmDetail(release["filmID"])
934 | detail["releaseDate"] = release["releaseDate"]
935 | detail["torrents"] = torrents
936 | detail["torrentsDate"] = dates[0]
937 | detail["comboDate"] = max(release["releaseDate"], dates[0])
938 | #print(detail["comboDate"])
939 | movies.append(detail)
940 |
941 | if (SORT_TYPE == "releaseDate"):
942 | movies.sort(key = operator.itemgetter("releaseDate"), reverse = True)
943 | elif (SORT_TYPE == "torrentsDate"):
944 | movies.sort(key = operator.itemgetter("torrentsDate"), reverse = True)
945 | elif (SORT_TYPE == "comboDate"):
946 | movies.sort(key = operator.itemgetter("comboDate"), reverse = True)
947 | else:
948 | movies.sort(key = operator.itemgetter("ratingFloat"), reverse = True)
949 |
950 | saveHTML(movies, HTML_SAVE_PATH)
951 |
952 | main()
--------------------------------------------------------------------------------
/digitalreleases2.py:
--------------------------------------------------------------------------------
1 | from bs4 import BeautifulSoup
2 | import hashlib
3 | import datetime
4 | import urllib.request
5 | from urllib.parse import urljoin
6 | from urllib.parse import quote
7 | import time
8 | import gzip
9 | import json
10 | import html
11 | import re
12 | import operator
13 | import os
14 | import binascii
15 | import urllib.parse
16 | import http.cookiejar
17 | import sys
18 |
19 | LOAD_DAYS = 60
20 | USE_MAGNET = True
21 | SORT_TYPE = "torrentsDate" #rating #torrentsDate
22 | MIN_VOTES_KP = 500
23 | MIN_VOTES_IMDB = 1500
24 | HTML_SAVE_PATH = "/opt/share/www/releases.html"
25 |
26 | SOCKS5_IP = ""
27 | SOCKS5_PORT = 9050
28 | if SOCKS5_IP:
29 | import socks
30 | from sockshandler import SocksiPyHandler
31 |
32 | CONNECTION_ATTEMPTS = 3
33 |
34 | RUTOR_BASE_URL = "http://rutor.info"
35 | #RUTOR_BASE_URL = "http://www.rutorc6mqdinc4cz.onion"
36 | RUTOR_MONTHS = {"Янв": 1, "Фев": 2, "Мар": 3, "Апр": 4, "Май": 5, "Июн": 6, "Июл": 7, "Авг": 8, "Сен": 9, "Окт": 10, "Ноя": 11, "Дек": 12}
37 | RUTOR_SEARCH_MAIN = "http://rutor.info/search/{}/{}/300/0/BDRemux|BDRip|(WEB%20DL)%201080p|2160p|1080%D1%80%7C2160%D1%80%7C1080i%20{}"
38 | #RUTOR_SEARCH_MAIN = "http://www.rutorc6mqdinc4cz.onion/search/{}/{}/300/0/BDRemux|BDRip|(WEB%20DL)%201080p|2160p|1080%D1%80%7C2160%D1%80%7C1080i%20{}"
39 |
40 | KINOPOISK_API_IOS_BASE_URL = "https://ma.kinopoisk.ru/ios/5.0.0/"
41 | KINOPOISK_API_V1_BASE_URL = "https://ma.kinopoisk.ru"
42 | KINOPOISK_API_IOS_FILMDETAIL = "getKPFilmDetailView?still_limit=9&filmID={}&uuid={}"
43 | KINOPOISK_API_SALT = "IDATevHDS7"
44 | KINOPOISK_CLIENTID = binascii.b2a_hex(os.urandom(12)).decode('ascii')
45 | KINOPOISK_UUID = binascii.b2a_hex(os.urandom(16)).decode('ascii')
46 | KINOPOISK_POSTER_URL = "https://st.kp.yandex.net/images/{}{}width=360"
47 |
48 | KINOZAL_SEARCH_BDREMUX = "http://kinozal.tv/browse.php?s=%5E{}&g=3&c=0&v=4&d=0&w=0&t=0&f=0"
49 | KINOZAL_SEARCH_BDRIP = "http://kinozal.tv/browse.php?s=%5E{}&g=3&c=0&v=3&d=0&w=0&t=0&f=0"
50 | KINOZAL_USERNAME = ""
51 | KINOZAL_PASSWORD = ""
52 |
53 | def main():
54 | print("Дата и время запуска программы: " + str(datetime.datetime.now()) + ".")
55 | print("Количество попыток при ошибках соединения: " + str(CONNECTION_ATTEMPTS) + ".")
56 |
57 | if SOCKS5_IP:
58 | print("Для rutor.info и kinozal.tv будет использоваться прокси-сервер SOCKS5: " + SOCKS5_IP + ":" + str(SOCKS5_PORT) + ".")
59 |
60 | print("Проверка доступности rutor.info...")
61 | try:
62 | content = loadRutorContent(RUTOR_SEARCH_MAIN.format(0, 0, ""), useProxy=True)
63 | count = rutorPagesCountForResults(content)
64 | except:
65 | print("Сайт rutor.info недоступен, или изменился его формат данных.")
66 | print("Работа программы принудительно завершена.")
67 | return 1
68 | else:
69 | print("Сайт rutor.info доступен.")
70 |
71 | print("Анализ раздач...")
72 | results = rutorResultsForDays(LOAD_DAYS)
73 | movies = convertRutorResults(results)
74 | movies.sort(key = operator.itemgetter(SORT_TYPE), reverse = True)
75 | saveHTML(movies, HTML_SAVE_PATH)
76 |
77 | if "HTML_SAVE_PATH_LINKS" in globals():
78 | saveHTML(movies, HTML_SAVE_PATH_LINKS, useMagnet=False)
79 |
80 | print("Работа программы завершена успешно.")
81 |
82 | return 0
83 |
84 | def rutorResultsForDays(days):
85 | targetDate = datetime.date.today() - datetime.timedelta(days=days)
86 | groups = [1, 5, 7, 10]
87 | tmpSet = set()
88 | tmpResults = {}
89 |
90 | for group in groups:
91 | try:
92 | print("Загрузка списка предварительно подходящих раздач...")
93 | content = loadRutorContent(RUTOR_SEARCH_MAIN.format(0, group, ""), useProxy=True)
94 | count = rutorPagesCountForResults(content)
95 | except:
96 | raise ConnectionError ("Ошибка. Не удалось загрузить страницу с результатами поиска или формат данных rutor.info изменился.")
97 |
98 | i = 0
99 | needMore = True
100 |
101 | while needMore:
102 | pageResults = rutorResultsOnPage(content)
103 | for result in pageResults:
104 | #if ("Патрик" in result["name"]):
105 | #print(result["name"])
106 | if result["date"] >= targetDate:
107 | #print(result["name"])
108 | #if not ("Шутки в сторону" in result["name"]):
109 | #continue
110 | element = parseRutorElement(result)
111 | if not element:
112 | continue
113 | if (element["compareName"] in tmpSet):
114 | continue
115 | print("Обработка раздачи: {} ({})...".format(element["nameRU"], element["year"]))
116 | try:
117 | elements = rutorSearchSimilarElements(element, group)
118 | elements = rutorFilmIDForElements(elements)
119 | #if len(newElements) == 0:
120 | #pass
121 | except:
122 | raise ConnectionError ("Ошибка. Не удалось загрузить данные похожих раздач или загрузить страницу с описанием.")
123 | tmpSet.add(element["compareName"])
124 | if len(elements) > 0:
125 | if (tmpResults.get(elements[0]["filmID"])):
126 | tmpResults[elements[0]["filmID"]].extend(elements)
127 | else:
128 | tmpResults[elements[0]["filmID"]] = elements
129 | else:
130 | needMore = False
131 | break
132 | i = i + 1
133 | if (i >= count):
134 | needMore = False
135 | if needMore:
136 | print("Загрузка списка предварительно подходящих раздач...")
137 | try:
138 | content = loadRutorContent(RUTOR_SEARCH_MAIN.format(i, group, ""), useProxy=True)
139 | except:
140 | raise ConnectionError ("Ошибка. Не удалось загрузить страницу с результатами поиска или формат данных rutor.info изменился.")
141 |
142 | return tmpResults
143 |
144 | def convertRutorResults(rutorResults):
145 | targetDate = datetime.date.today() - datetime.timedelta(days=LOAD_DAYS)
146 | #targetDate = datetime.date.today() - datetime.timedelta(days=65)
147 | minPremierDate = datetime.date.today() - datetime.timedelta(days=365)
148 |
149 | movies = []
150 |
151 | try:
152 | if KINOZAL_USERNAME:
153 | opener = kinozalAuth(KINOZAL_USERNAME, KINOZAL_PASSWORD)
154 | else:
155 | opener = None
156 | except:
157 | opener = None
158 |
159 | for key, values in rutorResults.items():
160 | BDDate = None
161 | BDDateLicense = None
162 | WBDate = None
163 | for value in values:
164 | if "BD" in value["type"]:
165 | if value["license"]:
166 | if not BDDateLicense:
167 | BDDateLicense = value["date"]
168 | else:
169 | BDDateLicense = min(BDDateLicense, value["date"])
170 | else:
171 | if not BDDate:
172 | BDDate = value["date"]
173 | else:
174 | BDDate = min(BDDate, value["date"])
175 | else:
176 | if not WBDate:
177 | WBDate = value["date"]
178 | else:
179 | WBDate = min(WBDate, value["date"])
180 | if BDDateLicense:
181 | if BDDateLicense < targetDate:
182 | continue
183 | elif BDDate:
184 | if BDDate < targetDate:
185 | continue
186 | else:
187 | if WBDate < targetDate:
188 | continue
189 |
190 | tr = {}
191 |
192 | for value in values:
193 | if value["type"] == "UHD BDRemux":
194 | if value["hdr"]:
195 | if tr.get("UHD BDRemux HDR") != None:
196 | if ((not tr["UHD BDRemux HDR"]["license"]) and value["license"]):
197 | tr["UHD BDRemux HDR"] = value
198 | elif (tr["UHD BDRemux HDR"]["license"] == False and value["license"] == False) or (tr["UHD BDRemux HDR"]["license"] == True and value["license"] == True):
199 | if value["seeders"] > tr["UHD BDRemux HDR"]["seeders"]:
200 | tr["UHD BDRemux HDR"] = value
201 | else:
202 | tr["UHD BDRemux HDR"] = value
203 | else:
204 | if tr.get("UHD BDRemux SDR") != None:
205 | if ((not tr["UHD BDRemux SDR"]["license"]) and value["license"]):
206 | tr["UHD BDRemux SDR"] = value
207 | elif (tr["UHD BDRemux SDR"]["license"] == False and value["license"] == False) or (tr["UHD BDRemux SDR"]["license"] == True and value["license"] == True):
208 | if value["seeders"] > tr["UHD BDRemux SDR"]["seeders"]:
209 | tr["UHD BDRemux SDR"] = value
210 | else:
211 | tr["UHD BDRemux SDR"] = value
212 | elif value["type"] == "BDRemux":
213 | if tr.get("BDRemux") != None:
214 | if ((not tr["BDRemux"]["license"]) and value["license"]):
215 | tr["BDRemux"] = value
216 | elif (tr["BDRemux"]["license"] == False and value["license"] == False) or (tr["BDRemux"]["license"] == True and value["license"] == True):
217 | if value["seeders"] > tr["BDRemux"]["seeders"]:
218 | tr["BDRemux"] = value
219 | else:
220 | tr["BDRemux"] = value
221 | elif value["type"] == "BDRip-HEVC":
222 | if tr.get("BDRip-HEVC 1080p") != None:
223 | if ((not tr["BDRip-HEVC 1080p"]["license"]) and value["license"]):
224 | tr["BDRip-HEVC 1080p"] = value
225 | elif (tr["BDRip-HEVC 1080p"]["license"] == False and value["license"] == False) or (tr["BDRip-HEVC 1080p"]["license"] == True and value["license"] == True):
226 | if value["seeders"] > tr["BDRip-HEVC 1080p"]["seeders"]:
227 | tr["BDRip-HEVC 1080p"] = value
228 | else:
229 | tr["BDRip-HEVC 1080p"] = value
230 | elif value["type"] == "BDRip":
231 | if tr.get("BDRip 1080p") != None:
232 | if ((not tr["BDRip 1080p"]["license"]) and value["license"]):
233 | tr["BDRip 1080p"] = value
234 | elif (tr["BDRip 1080p"]["license"] == False and value["license"] == False) or (tr["BDRip 1080p"]["license"] == True and value["license"] == True):
235 | if value["seeders"] > tr["BDRip 1080p"]["seeders"]:
236 | tr["BDRip 1080p"] = value
237 | else:
238 | tr["BDRip 1080p"] = value
239 | elif value["type"] == "WEB-DL":
240 | if value["resolution"] == "2160p":
241 | if value["hdr"]:
242 | if tr.get("WEB-DL 2160p HDR") != None:
243 | if ((not tr["WEB-DL 2160p HDR"]["license"]) and value["license"]):
244 | tr["WEB-DL 2160p HDR"] = value
245 | elif (tr["WEB-DL 2160p HDR"]["license"] == False and value["license"] == False) or (tr["WEB-DL 2160p HDR"]["license"] == True and value["license"] == True):
246 | if value["seeders"] > tr["WEB-DL 2160p HDR"]["seeders"]:
247 | tr["WEB-DL 2160p HDR"] = value
248 | else:
249 | tr["WEB-DL 2160p HDR"] = value
250 | else:
251 | if tr.get("WEB-DL 2160p SDR") != None:
252 | if ((not tr["WEB-DL 2160p SDR"]["license"]) and value["license"]):
253 | tr["WEB-DL 2160p SDR"] = value
254 | elif (tr["WEB-DL 2160p SDR"]["license"] == False and value["license"] == False) or (tr["WEB-DL 2160p SDR"]["license"] == True and value["license"] == True):
255 | if value["seeders"] > tr["WEB-DL 2160p SDR"]["seeders"]:
256 | tr["WEB-DL 2160p SDR"] = value
257 | else:
258 | tr["WEB-DL 2160p SDR"] = value
259 | else:
260 | if tr.get("WEB-DL 1080p") != None:
261 | if ((not tr["WEB-DL 1080p"]["license"]) and value["license"]):
262 | tr["WEB-DL 1080p"] = value
263 | elif (tr["WEB-DL 1080p"]["license"] == False and value["license"] == False) or (tr["WEB-DL 1080p"]["license"] == True and value["license"] == True):
264 | if value["seeders"] > tr["WEB-DL 1080p"]["seeders"]:
265 | tr["WEB-DL 1080p"] = value
266 | else:
267 | tr["WEB-DL 1080p"] = value
268 |
269 | if tr.get("UHD BDRemux HDR") or tr.get("UHD BDRemux SDR") or tr.get("BDRip-HEVC 1080p") or tr.get("BDRip 1080p") or tr.get("BDRemux"):
270 | tr.pop("WEB-DL 2160p HDR", None)
271 | tr.pop("WEB-DL 2160p SDR", None)
272 | tr.pop("WEB-DL 1080p", None)
273 |
274 | if tr.get("UHD BDRemux HDR"):
275 | tr.pop("UHD BDRemux SDR", None)
276 |
277 | print("Загрузка данных для фильма с ID " + values[0]["filmID"] + "...")
278 | try:
279 | detail = filmDetail(values[0]["filmID"])
280 | except:
281 | print("Загрузка не удалась. Пропуск фильма с ID " + values[0]["filmID"] + ".")
282 |
283 | print("Загружены данные для фильма: " + detail["nameRU"] + ".")
284 |
285 | if not detail.get("premierDate"):
286 | print("У фильма \"" + detail["nameRU"] + "\" нет даты премьеры. Пропуск фильма.")
287 | continue
288 | if detail["premierDate"] < minPremierDate:
289 | print("Фильм \"" + detail["nameRU"] + "\" слишком старый. Пропуск фильма.")
290 | continue
291 |
292 | finalResult = []
293 |
294 | if (tr.get("WEB-DL 1080p") or tr.get("WEB-DL 2160p HDR") or tr.get("WEB-DL 2160p SDR")) and opener:
295 | print("Пробуем найти отсутствующий BDRip 1080p на kinozal.tv...")
296 | kName = detail["nameRU"]
297 | kNameOriginal = detail["nameOriginal"]
298 | if not kNameOriginal:
299 | kNameOriginal = kName
300 | try:
301 | kRes = kinozalSearch({"nameRU" : kName, "nameOriginal":kNameOriginal, "year": detail["year"]}, opener, "BDRip 1080p")
302 | if kRes:
303 | print("Отсутствующий BDRip 1080p найден на kinozal.tv.")
304 | finalResult.append(kRes)
305 | tr.pop("WEB-DL 2160p HDR", None)
306 | tr.pop("WEB-DL 2160p SDR", None)
307 | tr.pop("WEB-DL 1080p", None)
308 | if kRes["license"]:
309 | BDDateLicense = kRes["date"]
310 | else:
311 | BDDate = kRes["date"]
312 | except:
313 | print("Какая-то ошибка при работе с kinozal.tv. Подробная информация о проблемах ещё не добавлена в функцию.")
314 | if tr.get("WEB-DL 1080p"):
315 | finalResult.append({"link": tr["WEB-DL 1080p"]["fileLink"], "magnet": tr["WEB-DL 1080p"]["magnetLink"], "date": tr["WEB-DL 1080p"]["date"], "type": "WEB-DL 1080p", "license": tr["WEB-DL 1080p"]["license"]})
316 | if tr.get("WEB-DL 2160p HDR"):
317 | finalResult.append({"link": tr["WEB-DL 2160p HDR"]["fileLink"], "magnet": tr["WEB-DL 2160p HDR"]["magnetLink"], "date": tr["WEB-DL 2160p HDR"]["date"], "type": "WEB-DL 2160p HDR", "license": tr["WEB-DL 2160p HDR"]["license"]})
318 | elif tr.get("WEB-DL 2160p SDR"):
319 | finalResult.append({"link": tr["WEB-DL 2160p SDR"]["fileLink"], "magnet": tr["WEB-DL 2160p SDR"]["magnetLink"], "date": tr["WEB-DL 2160p SDR"]["date"], "type": "WEB-DL 2160p SDR", "license": tr["WEB-DL 2160p SDR"]["license"]})
320 | if tr.get("BDRip 1080p"):
321 | finalResult.append({"link": tr["BDRip 1080p"]["fileLink"], "magnet": tr["BDRip 1080p"]["magnetLink"], "date": tr["BDRip 1080p"]["date"], "type": "BDRip 1080p", "license": tr["BDRip 1080p"]["license"]})
322 | elif (tr.get("BDRip-HEVC 1080p") or tr.get("BDRemux")) and opener:
323 | print("Пробуем найти отсутствующий BDRip 1080p на kinozal.tv...")
324 | kName = detail["nameRU"]
325 | kNameOriginal = detail["nameOriginal"]
326 | if not kNameOriginal:
327 | kNameOriginal = kName
328 | try:
329 | kRes = kinozalSearch({"nameRU" : kName, "nameOriginal":kNameOriginal, "year": detail["year"]}, opener, "BDRip 1080p")
330 | if kRes:
331 | print("Отсутствующий BDRip 1080p найден на kinozal.tv.")
332 | finalResult.append(kRes)
333 | except:
334 | print("Какая-то ошибка при работе с kinozal.tv. Подробная информация о проблемах ещё не добавлена в функцию.")
335 | if tr.get("BDRip-HEVC 1080p"):
336 |
337 | found = False
338 |
339 | try:
340 | if (not tr["BDRip-HEVC 1080p"]["license"]) and tr["BDRip 1080p"]["license"]:
341 | kName = detail["nameRU"]
342 | kNameOriginal = detail["nameOriginal"]
343 | if not kNameOriginal:
344 | kNameOriginal = kName
345 | kRes = kinozalSearch({"nameRU" : kName, "nameOriginal":kNameOriginal, "year": detail["year"]}, opener, "BDRip-HEVC 1080p", licenseOnly = True)
346 | if kRes:
347 | found = True
348 | finalResult.append(kRes)
349 | except:
350 | pass
351 |
352 | if not found:
353 | finalResult.append({"link": tr["BDRip-HEVC 1080p"]["fileLink"], "magnet": tr["BDRip-HEVC 1080p"]["magnetLink"], "date": tr["BDRip-HEVC 1080p"]["date"], "type": "BDRip-HEVC 1080p", "license": tr["BDRip-HEVC 1080p"]["license"]})
354 | elif (tr.get("BDRip 1080p") or tr.get("BDRemux")) and opener:
355 | print("Пробуем найти отсутствующий BDRip-HEVC 1080p на kinozal.tv...")
356 | kName = detail["nameRU"]
357 | kNameOriginal = detail["nameOriginal"]
358 | if not kNameOriginal:
359 | kNameOriginal = kName
360 | try:
361 | kRes = kinozalSearch({"nameRU" : kName, "nameOriginal":kNameOriginal, "year": detail["year"]}, opener, "BDRip-HEVC 1080p")
362 | if kRes:
363 | print("Отсутствующий BDRip-HEVC 1080p найден на kinozal.tv.")
364 | finalResult.append(kRes)
365 | except:
366 | print("Какая-то ошибка при работе с kinozal.tv. Подробная информация о проблемах ещё не добавлена в функцию.")
367 | if tr.get("BDRemux"):
368 | found = False
369 |
370 | try:
371 | if (not tr["BDRemux"]["license"]) and tr["BDRip 1080p"]["license"]:
372 | kName = detail["nameRU"]
373 | kNameOriginal = detail["nameOriginal"]
374 | if not kNameOriginal:
375 | kNameOriginal = kName
376 | kRes = kinozalSearch({"nameRU" : kName, "nameOriginal":kNameOriginal, "year": detail["year"]}, opener, "BDRemux", licenseOnly = True)
377 | if kRes:
378 | found = True
379 | finalResult.append(kRes)
380 | except:
381 | pass
382 |
383 | if not found:
384 | finalResult.append({"link": tr["BDRemux"]["fileLink"], "magnet": tr["BDRemux"]["magnetLink"], "date": tr["BDRemux"]["date"], "type": "BDRemux", "license": tr["BDRemux"]["license"]})
385 | elif (tr.get("BDRip-HEVC 1080p") or tr.get("BDRip 1080p")) and opener:
386 | print("Пробуем найти отсутствующий BDRemux на kinozal.tv...")
387 | kName = detail["nameRU"]
388 | kNameOriginal = detail["nameOriginal"]
389 | if not kNameOriginal:
390 | kNameOriginal = kName
391 | try:
392 | kRes = kinozalSearch({"nameRU" : kName, "nameOriginal":kNameOriginal, "year": detail["year"]}, opener, "BDRemux")
393 | if kRes:
394 | print("Отсутствующий BDRemux найден на kinozal.tv.")
395 | finalResult.append(kRes)
396 | except:
397 | print("Какая-то ошибка при работе с kinozal.tv. Подробная информация о проблемах ещё не добавлена в функцию.")
398 | if tr.get("UHD BDRemux HDR"):
399 | finalResult.append({"link": tr["UHD BDRemux HDR"]["fileLink"], "magnet": tr["UHD BDRemux HDR"]["magnetLink"], "date": tr["UHD BDRemux HDR"]["date"], "type": "UHD BDRemux HDR", "license": tr["UHD BDRemux HDR"]["license"]})
400 | elif tr.get("UHD BDRemux SDR"):
401 | finalResult.append({"link": tr["UHD BDRemux SDR"]["fileLink"], "magnet": tr["UHD BDRemux SDR"]["magnetLink"], "date": tr["UHD BDRemux SDR"]["date"], "type": "UHD BDRemux SDR", "license": tr["UHD BDRemux SDR"]["license"]})
402 |
403 | dates = []
404 | for torrent in finalResult:
405 | dates.append(torrent["date"])
406 | dates.sort()
407 |
408 | detail["torrents"] = finalResult
409 | detail["torrentsDate"] = dates[0]
410 | if BDDateLicense:
411 | detail["torrentsDate"] = BDDateLicense
412 | detail["torrentsDateType"] = "Blu-ray с официальным русским озвучиванием ★"
413 | elif BDDate:
414 | detail["torrentsDate"] = BDDate
415 | detail["torrentsDateType"] = "Blu-ray с официальным русским озвучиванием из VoD"
416 | else:
417 | detail["torrentsDate"] = WBDate
418 | detail["torrentsDateType"] = "VoD с официальным русским озвучиванием"
419 | movies.append(detail)
420 |
421 | return movies
422 |
423 | def loadRutorContent(URL, attempts=CONNECTION_ATTEMPTS, useProxy=False):
424 | headers = {}
425 | headers["Accept-encoding"] = "gzip"
426 | headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0"
427 |
428 | return loadURLContent(URL, headers=headers, attempts=attempts, useProxy=useProxy)
429 |
430 | def rutorPagesCountForResults(content):
431 | soup = BeautifulSoup(content, 'html.parser')
432 |
433 | if (soup == None):
434 | raise ValueError("Ошибка. Невозможно инициализировать HTML-парсер, что-то не так с контентом.")
435 |
436 | try:
437 | resultsGroup = soup.find("div", id="index")
438 | except:
439 | raise ValueError("Ошибка. Нет блока с торрентами.")
440 | if resultsGroup == None:
441 | raise ValueError("Ошибка. Нет блока с торрентами.")
442 |
443 | try:
444 | indexes = [text for text in resultsGroup.b.stripped_strings]
445 | except:
446 | raise ValueError("Ошибка. Нет блока со страницами результатов.")
447 | if len(indexes) == 0:
448 | raise ValueError("Ошибка. Нет блока со страницами результатов.")
449 |
450 | lastIndexStr = indexes[-1]
451 | if lastIndexStr.startswith("Страницы"):
452 | return 1
453 |
454 | lastIndex = int(lastIndexStr)
455 |
456 | if lastIndex <= 0:
457 | raise ValueError("Ошибка. Неверное значение индекса страницы.")
458 |
459 | return lastIndex
460 |
461 | def loadURLContent(url, headers={}, attempts=CONNECTION_ATTEMPTS, useProxy=False):
462 | if useProxy and SOCKS5_IP:
463 | proxyHandler = SocksiPyHandler(socks.PROXY_TYPE_SOCKS5, SOCKS5_IP, SOCKS5_PORT)
464 | opener = urllib.request.build_opener(proxyHandler)
465 | else:
466 | opener = urllib.request.build_opener()
467 |
468 | request = urllib.request.Request(url, headers=headers)
469 | response=None
470 | n = attempts
471 | while n > 0:
472 | try:
473 | response = opener.open(request)
474 | break
475 | except:
476 | n = n - 1
477 | if (n <= 0):
478 | raise ConnectionError("Ошибка соединения. Все попытки соединения израсходованы.")
479 |
480 | if response.info().get("Content-Encoding") == "gzip":
481 | gzipFile = gzip.GzipFile(fileobj=response)
482 | content = gzipFile.read().decode("utf-8")
483 | else:
484 | content = response.read().decode("utf-8")
485 |
486 | return content
487 |
488 | def kinopoiskRating(filmID, useProxy = False):
489 | result = {}
490 |
491 | headers = {}
492 | headers["Accept-encoding"] = "gzip"
493 | headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0"
494 |
495 | if useProxy and SOCKS5_IP:
496 | proxyHandler = SocksiPyHandler(socks.PROXY_TYPE_SOCKS5, SOCKS5_IP, SOCKS5_PORT)
497 | opener = urllib.request.build_opener(proxyHandler)
498 | else:
499 | opener = urllib.request.build_opener()
500 |
501 | request = urllib.request.Request("https://rating.kinopoisk.ru/{}.xml".format(filmID), headers=headers)
502 | response = opener.open(request)
503 | if response.info().get("Content-Encoding") == "gzip":
504 | gzipFile = gzip.GzipFile(fileobj=response)
505 | content = gzipFile.read().decode(response.info().get_content_charset())
506 | else:
507 | content = response.read().decode(response.info().get_content_charset())
508 |
509 | patternKP = re.compile("([0-9]*\.[0-9]*)")
510 | matches = re.findall(patternKP, content)
511 |
512 | if len(matches) == 1:
513 | result["rating"] = matches[0][1]
514 | result["ratingVoteCount"] = matches[0][0]
515 |
516 | patternIMDb = re.compile("([0-9]*\.[0-9]*)")
517 | matches = re.findall(patternIMDb, content)
518 |
519 | if len(matches) == 1:
520 | result["ratingIMDb"] = matches[0][1]
521 | result["ratingIMDbVoteCount"] = matches[0][0]
522 |
523 | return result
524 |
525 | def filmDetail(filmID):
526 | result = {}
527 | content = None
528 |
529 | try:
530 | content = loadKinopoiskContent(KINOPOISK_API_IOS_BASE_URL, KINOPOISK_API_IOS_FILMDETAIL.format(filmID, KINOPOISK_UUID))
531 | except:
532 | pass
533 |
534 | if content:
535 | tmpDict = json.loads(content)
536 |
537 | if tmpDict == None or not isinstance(tmpDict, dict):
538 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Ответ не соответствует JSON.")
539 | if tmpDict.get("resultCode") != 0:
540 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". В ответе нет значения resultCode или оно не равно 0.")
541 | itemData = tmpDict.get("data")
542 | if itemData == None or not isinstance(itemData, dict):
543 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением data.")
544 | nameRU = itemData.get("nameRU")
545 | if nameRU == None or not isinstance(nameRU, str):
546 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением nameRU.")
547 | nameEN = itemData.get("nameEN")
548 | if nameEN == None or not isinstance(nameEN, str):
549 | nameEN = ""
550 | year = itemData.get("year")
551 | if year == None or not isinstance(year, str):
552 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением year.")
553 | country = itemData.get("country")
554 | if country == None or not isinstance(country, str):
555 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением country.")
556 | genre = itemData.get("genre")
557 | if genre == None or not isinstance(genre, str):
558 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением genre.")
559 | description = itemData.get("description")
560 | if description == None or not isinstance(description, str):
561 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением description.")
562 | ratingAgeLimits = itemData.get("ratingAgeLimits")
563 | if ratingAgeLimits == None or not isinstance(ratingAgeLimits, str):
564 | ratingAgeLimits = ""
565 | ratingMPAA = itemData.get("ratingMPAA")
566 | if ratingMPAA == None or not isinstance(ratingMPAA, str):
567 | ratingMPAA = ""
568 | posterURL = itemData.get("posterURL")
569 | if posterURL == None or not isinstance(posterURL, str):
570 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением posterURL.")
571 | if "?" in posterURL:
572 | posterURL = KINOPOISK_POSTER_URL.format(posterURL, "&")
573 | else:
574 | posterURL = KINOPOISK_POSTER_URL.format(posterURL, "?")
575 | filmLength = itemData.get("filmLength")
576 | if filmLength == None or not isinstance(filmLength, str):
577 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением filmLength.")
578 | ratingData = itemData.get("ratingData")
579 | if ratingData == None or not isinstance(ratingData, dict):
580 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением ratingData.")
581 | ratingKP = ratingData.get("rating")
582 | if ratingKP == None or not isinstance(ratingKP, str):
583 | ratingKP = ""
584 | ratingKPCount = ratingData.get("ratingVoteCount")
585 | if ratingKPCount == None or not isinstance(ratingKPCount, str):
586 | ratingKPCount = "0"
587 | ratingKPCount = ratingKPCount.replace(" ", "")
588 | try:
589 | ratingKPCount = int(ratingKPCount)
590 | except:
591 | ratingKPCount = 0
592 | if ratingKPCount < MIN_VOTES_KP:
593 | ratingKP = ""
594 | ratingIMDb = ratingData.get("ratingIMDb")
595 | if ratingIMDb == None or not isinstance(ratingIMDb, str):
596 | ratingIMDb = ""
597 | ratingIMDbCount = ratingData.get("ratingIMDbVoteCount")
598 | if ratingIMDbCount == None or not isinstance(ratingIMDbCount, str):
599 | ratingIMDbCount = "0"
600 | ratingIMDbCount = ratingIMDbCount.replace(" ", "")
601 | try:
602 | ratingIMDbCount = int(ratingIMDbCount)
603 | except:
604 | ratingIMDbCount = 0
605 | if ratingIMDbCount < MIN_VOTES_IMDB:
606 | ratingIMDb = ""
607 | webURL = itemData.get("webURL")
608 | if webURL == None or not isinstance(webURL, str):
609 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением webURL.")
610 | rentData = itemData.get("rentData")
611 | if rentData == None or not isinstance(rentData, dict):
612 | rentData = {}
613 | premiereRU = rentData.get("premiereRU")
614 | if not isinstance(premiereRU, str):
615 | premiereRU = None
616 | premiereWorld = rentData.get("premiereWorld")
617 | if not isinstance(premiereWorld, str):
618 | premiereWorld = None
619 | premiereDigital = rentData.get("premiereDigital")
620 | if not isinstance(premiereDigital, str):
621 | premiereDigital = None
622 | premierDate = None
623 | premierType = None
624 | if (not premierDate) and premiereRU:
625 | premierDate = datetime.datetime.strptime(premiereRU, "%d.%m.%Y").date()
626 | premierType = "ru"
627 | if (not premierDate) and premiereWorld:
628 | premierDate = datetime.datetime.strptime(premiereWorld, "%d.%m.%Y").date()
629 | premierType = "world"
630 | if (not premierDate) and premiereDigital:
631 | premierDate = datetime.datetime.strptime(premiereDigital, "%d.%m.%Y").date()
632 | premierType = "digital"
633 | videoURL = itemData.get("videoURL")
634 | if videoURL == None or not isinstance(videoURL, dict):
635 | videoURL == ""
636 | else:
637 | hdLink = videoURL.get("hd")
638 | if hdLink == None or not isinstance(hdLink, str):
639 | videoURL == ""
640 | else:
641 | videoURL = hdLink
642 |
643 | directors = []
644 | actors = []
645 |
646 | creators = itemData.get("creators")
647 | if creators == None or not isinstance(creators, list):
648 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением creators.")
649 | for personsGroup in creators:
650 | if not isinstance(personsGroup, list):
651 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением creators > personsGroup.")
652 | for person in personsGroup:
653 | if not isinstance(person, dict):
654 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ". Проблемы со значением creators > personsGroup > person.")
655 | if person.get("professionKey") == "director":
656 | if person.get("nameRU"):
657 | directors.append(person.get("nameRU"))
658 | if person.get("professionKey") == "actor":
659 | if person.get("nameRU"):
660 | actors.append(person.get("nameRU"))
661 | else:
662 | raise ValueError("Ошибка загрузки данных для filmID " + filmID + ".")
663 |
664 | freshRating = {}
665 | try:
666 | freshRating = kinopoiskRating(filmID)
667 | except:
668 | pass
669 |
670 | if freshRating.get("rating") and freshRating.get("ratingVoteCount"):
671 | ratingKP = freshRating.get("rating")
672 | ratingKPCount = freshRating.get("ratingVoteCount")
673 | try:
674 | ratingKP = "{0:.1f}".format(float(ratingKP))
675 | ratingKPCount = int(ratingKPCount)
676 | except:
677 | ratingKPCount = 0
678 | if ratingKPCount < MIN_VOTES_KP:
679 | ratingKP = ""
680 |
681 | if freshRating.get("ratingIMDb") and freshRating.get("ratingIMDbVoteCount"):
682 | ratingIMDb = freshRating.get("ratingIMDb")
683 | ratingIMDbCount = freshRating.get("ratingIMDbVoteCount")
684 | try:
685 | ratingIMDb = "{0:.1f}".format(float(ratingIMDb))
686 | ratingIMDbCount = int(ratingIMDbCount)
687 | except:
688 | ratingIMDbCount = 0
689 | if ratingIMDbCount < MIN_VOTES_IMDB:
690 | ratingIMDb = ""
691 |
692 | if ratingIMDb and ratingKP:
693 | rating = "{0:.1f}".format((float(ratingKP) + float(ratingIMDb)) / 2.0 + 0.001)
694 | elif ratingKP:
695 | rating = ratingKP
696 | elif ratingIMDb:
697 | rating = ratingIMDb
698 | else:
699 | rating = "0"
700 |
701 | directorsResult = ""
702 | if len(directors) > 0:
703 | for director in directors:
704 | directorsResult += director
705 | directorsResult += ", "
706 | if directorsResult.endswith(", "):
707 | directorsResult = directorsResult[:-2]
708 |
709 | actorsResult = ""
710 | if len(actors) > 0:
711 | for actor in actors:
712 | actorsResult += actor
713 | actorsResult += ", "
714 | if actorsResult.endswith(", "):
715 | actorsResult = actorsResult[:-2]
716 |
717 | result["filmID"] = filmID
718 | result["nameRU"] = nameRU
719 | result["nameOriginal"] = nameEN
720 | result["description"] = description
721 | result["year"] = year
722 | result["country"] = country
723 | result["genre"] = genre
724 | result["ratingAgeLimits"] = ratingAgeLimits
725 | result["ratingMPAA"] = ratingMPAA
726 | result["posterURL"] = posterURL
727 | result["filmLength"] = filmLength
728 | result["ratingKP"] = ratingKP
729 | result["ratingKPCount"] = ratingKPCount
730 | result["ratingIMDb"] = ratingIMDb
731 | result["ratingIMDbCount"] = ratingIMDbCount
732 | result["rating"] = rating
733 | result["ratingFloat"] = float(rating)
734 | result["directors"] = directorsResult
735 | result["actors"] = actorsResult
736 | result["webURL"] = webURL
737 | result["trailerURL"] = videoURL
738 | if premierDate:
739 | result["premierDate"] = premierDate
740 | result["premierType"] = premierType
741 |
742 | return result
743 |
744 | def convertToAlfaNum(str):
745 | tmpStr = str.upper()
746 | tmpList = []
747 | for c in tmpStr:
748 | if c.isalnum():
749 | tmpList.append(c)
750 | else:
751 | tmpList.append(" ")
752 |
753 | return " ".join("".join(tmpList).split())
754 |
755 | def replaceSimilarChars(str):
756 | tmpStr = str.upper()
757 | tmpStr = tmpStr.replace("A", "А")
758 | tmpStr = tmpStr.replace("B", "В")
759 | tmpStr = tmpStr.replace("C", "С")
760 | tmpStr = tmpStr.replace("E", "Е")
761 | tmpStr = tmpStr.replace("H", "Н")
762 | tmpStr = tmpStr.replace("K", "К")
763 | tmpStr = tmpStr.replace("M", "М")
764 | tmpStr = tmpStr.replace("O", "О")
765 | tmpStr = tmpStr.replace("P", "Р")
766 | tmpStr = tmpStr.replace("T", "Т")
767 | tmpStr = tmpStr.replace("X", "Х")
768 | tmpStr = tmpStr.replace("Y", "У")
769 | tmpStr = tmpStr.replace("Ё", "Е")
770 |
771 | return tmpStr
772 |
773 | def parseRutorElement(dict):
774 | tmpParts = dict["name"].split("|")
775 |
776 | fullName = tmpParts[0].strip().upper()
777 | tags = set()
778 | tagsStr = ""
779 |
780 | if len(tmpParts) > 1:
781 | for i in range(1, len(tmpParts)):
782 | moreParts = tmpParts[i].split(",")
783 | for tmpPart in moreParts:
784 | tags.add(tmpPart.strip().upper())
785 | tagsStr = tagsStr + tmpPart.strip().upper() + " "
786 |
787 | if ("LINE" in tags) or ("UKR" in tags) or ("3D-VIDEO" in tags) or ("60 FPS" in tags) or (("1080" in fullName) and ("HDR" in tags)) or ("UHD BDRIP" in fullName) or ("[" in fullName) or ("]" in fullName):
788 | return None
789 |
790 | patternYear = re.compile("\((\d{4})\)")
791 | match = re.search(patternYear, tmpParts[0])
792 |
793 | if not match:
794 | return None
795 |
796 | year = match[1]
797 | targetYear = (datetime.date.today() - datetime.timedelta(days=365)).year
798 | if int(year) < targetYear:
799 | return None
800 |
801 | namesPart = (tmpParts[0][:match.start()]).strip()
802 | typePart = (tmpParts[0][match.end():]).strip().upper()
803 | names = namesPart.split("/")
804 | RU = True if len(names) == 1 else False
805 | nameRU = names[0].strip()
806 | names.pop(0)
807 | if len(names) > 0:
808 | nameOriginal = names[-1]
809 | else:
810 | nameOriginal = nameRU
811 |
812 | if not RU:
813 | if not (("ЛИЦЕНЗИЯ" in tags) or ("ITUNES" in tags) or ("D" in tags) or ("D1" in tags) or ("D2" in tags) or ("НЕВАФИЛЬМ" in tags) or ("ПИФАГОР" in tags) or ("AMEDIA" in tags) or ("МОСФИЛЬМ-МАСТЕР" in tags) or ("СВ-ДУБЛЬ" in tags) or ("КИРИЛЛИЦА" in tags) or ("АРК-ТВ" in tagsStr) or ("APK-ТВ" in tagsStr) or ("APK-TB" in tagsStr)):
814 | return None
815 |
816 | license = True if ("ЛИЦЕНЗИЯ" in tags) else False
817 |
818 | if "UHD BDREMUX" in typePart:
819 | type = "UHD BDRemux"
820 | elif "BDREMUX" in typePart:
821 | type = "BDRemux"
822 | elif "BDRIP-HEVC" in typePart:
823 | type = "BDRip-HEVC"
824 | elif "BDRIP" in typePart:
825 | type = "BDRip"
826 | elif "WEB-DL " in typePart:
827 | type = "WEB-DL"
828 | elif "WEB-DL-HEVC" in typePart:
829 | #type = "WEB-DL-HEVC"
830 | type = "WEB-DL"
831 | else:
832 | return None
833 |
834 | hdr = False
835 |
836 | if "2160" in typePart:
837 | resolution = "2160p"
838 | hdr = True if ("HDR" in tags) else False
839 | elif "1080I" in typePart:
840 | resolution = "1080i"
841 | elif ("1080P" in typePart) or ("1080Р" in typePart):
842 | resolution = "1080p"
843 | else:
844 | return None
845 |
846 | IMAX = True if (("IMAX" in tags) or ("IMAX EDITION" in tags)) else False
847 | OpenMatte = True if ("OPEN MATTE" in tags) else False
848 |
849 | if RU:
850 | compareName = replaceSimilarChars(convertToAlfaNum(nameRU)) + " " + year
851 | searchPattern = "(^" + convertToAlfaNum(nameRU) + " " + year + ")|(^" + compareName + ")"
852 | else:
853 | compareName = replaceSimilarChars(convertToAlfaNum(nameRU)) + " " + convertToAlfaNum(nameOriginal) + " " + year
854 | searchPattern = "(^" + convertToAlfaNum(nameRU) + " " + convertToAlfaNum(nameOriginal) + " " + year + ")|(^" + compareName + ")"
855 | if len(searchPattern) > 130:
856 | searchPattern = "(^" + convertToAlfaNum(nameRU) + " " + convertToAlfaNum(nameOriginal) + " " + year + ")"
857 | searchPattern = searchPattern.replace("AND", "and")
858 | searchPattern = searchPattern.replace("OR", "or")
859 |
860 | result = {"date": dict["date"], "torrentName": dict["name"], "fileLink": dict["fileLink"], "magnetLink": dict["magnetLink"], "descriptionLink": dict["descriptionLink"], "size": dict["size"], "seeders": dict["seeders"], "leechers": dict["leechers"], "nameOriginal": nameOriginal, "nameRU": nameRU, "compareName": compareName, "searchPattern": searchPattern, "year": year, "type": type, "resolution": resolution, "hdr": hdr, "IMAX": IMAX, "OpenMatte": OpenMatte, "license": license}
861 |
862 | return result
863 |
864 | def rutorSearchSimilarElements(element, group):
865 | results = []
866 | #print(RUTOR_SEARCH_MAIN.format(0, group, quote(element["searchPattern"])))
867 | content = loadRutorContent(RUTOR_SEARCH_MAIN.format(0, group, quote(element["searchPattern"])), useProxy=True)
868 | try:
869 | pageResults = rutorResultsOnPage(content)
870 | except:
871 | #print(RUTOR_SEARCH_MAIN.format(0, group, quote(element["searchPattern"])))
872 | return results
873 |
874 | for result in pageResults:
875 | tmpElement = parseRutorElement(result)
876 | if not tmpElement:
877 | continue
878 | if tmpElement["compareName"] == element["compareName"]:
879 | results.append(tmpElement)
880 |
881 | return results
882 |
883 | def rutorResultsOnPage(content):
884 | soup = BeautifulSoup(content, 'html.parser')
885 |
886 | if (soup == None):
887 | raise ValueError("{} {}".format(datetime.datetime.now(), "Невозможно инициализировать HTML-парсер, что-то не так с контентом."))
888 |
889 | result = []
890 |
891 | try:
892 | resultsGroup = soup.find("div", id="index")
893 | except Exception as e:
894 | raise ValueError("{} {}".format(datetime.datetime.now(), "Нет блока с торрентами."))
895 | if resultsGroup == None:
896 | raise ValueError("{} {}".format(datetime.datetime.now(), "Нет блока с торрентами."))
897 |
898 | elements = resultsGroup.find_all("tr", class_=["gai", "tum"])
899 |
900 | if len(elements) == 0:
901 | return result
902 |
903 | for element in elements:
904 | allTDinElement = element.find_all("td", recursive=False)
905 |
906 | if len(allTDinElement) == 4:
907 | dateElement = allTDinElement[0]
908 | mainElement = allTDinElement[1]
909 | sizeElement = allTDinElement[2]
910 | peersElement = allTDinElement[3]
911 | elif len(allTDinElement) == 5:
912 | dateElement = allTDinElement[0]
913 | mainElement = allTDinElement[1]
914 | sizeElement = allTDinElement[3]
915 | peersElement = allTDinElement[4]
916 | else:
917 | raise ValueError("{} {}".format(datetime.datetime.now(), "Неверный формат блока торрента."))
918 |
919 | try:
920 | components = dateElement.string.split(u"\xa0")
921 | torrentDate = datetime.date((int(components[2]) + 2000) if int(components[2]) < 2000 else int(components[2]), RUTOR_MONTHS[components[1]], int(components[0]))
922 | except Exception as e:
923 | raise ValueError("{} {}".format(datetime.datetime.now(), "Неверный формат блока даты."))
924 |
925 | try:
926 | seeders = int(peersElement.find("span", class_="green").get_text(strip=True))
927 | leechers = int(peersElement.find("span", class_="red").get_text(strip=True))
928 | except Exception as e:
929 | raise ValueError("{} {}".format(datetime.datetime.now(), "Неверный формат блока пиров."))
930 |
931 | try:
932 | sizeStr = sizeElement.get_text(strip=True)
933 |
934 | if sizeStr.endswith("GB"):
935 | multiplier = 1024 * 1024 * 1024
936 | elif sizeStr.endswith("MB"):
937 | multiplier = 1024 * 1024
938 | elif sizeStr.endswith("KB"):
939 | multiplier = 1024
940 | else:
941 | multiplier = 1
942 |
943 | components = sizeStr.split(u"\xa0")
944 | torrentSize = int(float(components[0]) * multiplier)
945 | except Exception as e:
946 | raise ValueError("{} {}".format(datetime.datetime.now(), "Неверный формат блока размера."))
947 | continue
948 |
949 | try:
950 | mainElements = mainElement.find_all("a")
951 | torrentFileLink = mainElements[0].get("href").strip()
952 | if not torrentFileLink.startswith("http"):
953 | torrentFileLink = urljoin("http://d.rutor.info", torrentFileLink)
954 | magnetLink = mainElements[1].get("href").strip()
955 |
956 | if not magnetLink.startswith("magnet"):
957 | raise ValueError("Magnet")
958 |
959 | torrentLink = quote(mainElements[2].get("href").strip())
960 | if not torrentLink.startswith("http"):
961 | torrentLink = urljoin(RUTOR_BASE_URL, torrentLink)
962 |
963 | torrentName = mainElements[2].get_text(strip=True)
964 | except Exception as e:
965 | raise ValueError("{} {}".format(datetime.datetime.now(), "Неверный формат основного блока в блоке торрента."))
966 |
967 | result.append({"date": torrentDate, "name": torrentName, "fileLink": torrentFileLink, "magnetLink": magnetLink, "descriptionLink": torrentLink, "size": torrentSize, "seeders": seeders, "leechers": leechers})
968 |
969 | return result
970 |
971 | def rutorFilmIDForElements(elements, deep = True):
972 | kID = None
973 | for element in elements:
974 | content = loadRutorContent(element["descriptionLink"], useProxy=True)
975 |
976 | patternLink = re.compile("\"http://www.kinopoisk.ru/film/(.*?)/\"")
977 | matches = re.findall(patternLink, content)
978 | if len(matches) == 1:
979 | kID = matches[0]
980 | break
981 | elif len(matches) > 1:
982 | return []
983 |
984 | if not kID:
985 | patternLink = re.compile("\"http://www.kinopoisk.ru/level/1/film/(.*?)/\"")
986 | matches = re.findall(patternLink, content)
987 | if len(matches) == 1:
988 | kID = matches[0]
989 | break
990 | elif len(matches) > 1:
991 | return []
992 |
993 | if kID:
994 | for element in elements:
995 | element["filmID"] = kID
996 | return elements
997 | else:
998 | if not deep:
999 | return []
1000 |
1001 | try:
1002 | for element in elements:
1003 | content = loadRutorContent(element["descriptionLink"], useProxy=True)
1004 | pageResults = rutorResultsOnPage(content)
1005 | newElements = rutorFilmIDForElements(pageResults, deep = False)
1006 | if len(newElements) > 0:
1007 | kID = newElements[0]["filmID"]
1008 | break
1009 | except:
1010 | return []
1011 |
1012 | if kID:
1013 | for element in elements:
1014 | element["filmID"] = kID
1015 | return elements
1016 | else:
1017 | return []
1018 |
1019 | return elements
1020 |
1021 | def loadKinopoiskContent(baseURL, requestMethod, CLIENTID=KINOPOISK_CLIENTID, API_SALT=KINOPOISK_API_SALT, attempts=CONNECTION_ATTEMPTS, useProxy=False):
1022 | timestamp = str(int(round(time.time() * 1000)))
1023 | hashString = requestMethod + timestamp + API_SALT
1024 |
1025 | headers = {}
1026 | headers["Accept-encoding"] = "gzip"
1027 | headers["Accept"] = "application/json"
1028 | headers["User-Agent"] = "Android client (6.0.1 / api23), ru.kinopoisk/4.6.5 (86)"
1029 | headers["Image-Scale"] = "3"
1030 | headers["device"] = "android"
1031 | headers["ClientId"] = CLIENTID
1032 | headers["countryID"] = "2"
1033 | headers["cityID"] = "1"
1034 | headers["Android-Api-Version"] = "23"
1035 | headers["clientDate"] = datetime.date.today().strftime("%H:%M %d.%m.%Y")
1036 | headers["device"] = "android"
1037 | headers["X-TIMESTAMP"] = timestamp
1038 | headers["X-SIGNATURE"] = hashlib.md5(hashString.encode('utf-8')).hexdigest()
1039 |
1040 | return loadURLContent(baseURL + requestMethod, headers=headers, attempts=attempts, useProxy=useProxy)
1041 |
1042 | def kinozalAuth(username, password, useProxy = True):
1043 | headers = {}
1044 | headers["Accept-encoding"] = "gzip"
1045 | headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0"
1046 |
1047 | cookiejar = http.cookiejar.CookieJar()
1048 |
1049 | if useProxy and SOCKS5_IP:
1050 | proxyHandler = SocksiPyHandler(socks.PROXY_TYPE_SOCKS5, SOCKS5_IP, SOCKS5_PORT)
1051 | opener = urllib.request.build_opener(proxyHandler)
1052 | opener.add_handler(urllib.request.HTTPCookieProcessor(cookiejar))
1053 | else:
1054 | opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookiejar))
1055 |
1056 | values = {"username":username, "password":password}
1057 | data = urllib.parse.urlencode(values).encode()
1058 |
1059 | request = urllib.request.Request("http://kinozal.tv/takelogin.php", data=data, headers=headers)
1060 | try:
1061 | response = opener.open(request)
1062 | except:
1063 | response = opener.open(request)
1064 |
1065 | cookieSet = set()
1066 |
1067 | for cookie in cookiejar:
1068 | cookieSet.add(cookie.name)
1069 |
1070 | if ("pass" in cookieSet) and ("uid" in cookieSet):
1071 | return opener
1072 |
1073 | return None
1074 |
1075 | def kinozalSearch(filmDetail, opener, type, licenseOnly = False):
1076 | targetDate = datetime.date.today() - datetime.timedelta(days=LOAD_DAYS)
1077 | headers = {}
1078 | headers["Accept-encoding"] = "gzip"
1079 | headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0"
1080 |
1081 | result = {}
1082 | DBResults = []
1083 | PMResults = []
1084 |
1085 | if type == "BDRip 1080p" or type == "BDRip-HEVC 1080p":
1086 | request = urllib.request.Request(KINOZAL_SEARCH_BDRIP.format(quote(filmDetail["nameRU"])), headers=headers)
1087 | elif type == "BDRemux":
1088 | request = urllib.request.Request(KINOZAL_SEARCH_BDREMUX.format(quote(filmDetail["nameRU"])), headers=headers)
1089 | else:
1090 | return None
1091 |
1092 | try:
1093 | response = opener.open(request)
1094 | except:
1095 | response = opener.open(request)
1096 |
1097 | if response.info().get("Content-Encoding") == "gzip":
1098 | gzipFile = gzip.GzipFile(fileobj=response)
1099 | content = gzipFile.read().decode(response.info().get_content_charset())
1100 | else:
1101 | content = response.read().decode(response.info().get_content_charset())
1102 |
1103 | content = content.replace("\n", "")
1104 | soup = BeautifulSoup(content, 'html.parser')
1105 |
1106 | elements = soup.find_all("td", class_=["nam"])
1107 |
1108 | if len(elements) == 0:
1109 | return None
1110 |
1111 | for element in elements:
1112 | contents = element.contents
1113 | if len(contents) != 7:
1114 | continue
1115 |
1116 | fullName = contents[0].get_text(strip=True)
1117 | torrentLink = contents[0].get("href").strip()
1118 | seeders = int(contents[3].get_text(strip=True))
1119 | leechers = int(contents[4].get_text(strip=True))
1120 | dateStr = contents[5].get_text(strip=True)
1121 |
1122 | if "сегодня" in dateStr:
1123 | torrentDate = datetime.date.today()
1124 | elif "вчера" in dateStr:
1125 | torrentDate = datetime.date.today() - datetime.timedelta(days=1)
1126 | else:
1127 | patternDate = re.compile("\d{2}.\d{2}.\d{4}")
1128 | matches = re.findall(patternDate, dateStr)
1129 | if len(matches) != 1:
1130 | continue
1131 | torrentDate = datetime.datetime.strptime(matches[0], "%d.%m.%Y").date()
1132 |
1133 | if torrentDate <= targetDate:
1134 | continue
1135 |
1136 | patternID = re.compile("id=(\d+)")
1137 | matches = re.findall(patternID, torrentLink)
1138 | if len(matches) != 1:
1139 | continue
1140 | kinozalID = matches[0]
1141 |
1142 | patternYear = re.compile("/ \d{4} /")
1143 | match = re.search(patternYear, fullName)
1144 |
1145 | if not match:
1146 | continue
1147 |
1148 |
1149 | namesPart = (fullName[:match.end()]).strip().upper().replace("Ё", "Е")
1150 | typePart = (fullName[match.end():]).strip().upper()
1151 |
1152 | year = int(filmDetail["year"])
1153 | nameRU = filmDetail["nameRU"].upper().replace("Ё", "Е")
1154 | nameOriginal = filmDetail["nameOriginal"].upper().replace("Ё", "Е")
1155 |
1156 | if type == "BDRip 1080p":
1157 | if not ((nameRU in namesPart) and (nameOriginal in namesPart) and ((str(year) in namesPart) or (str(year - 1) in namesPart) or (str(year + 1) in namesPart)) and ("BDRIP" in typePart) and ("1080P" in typePart)):
1158 | continue
1159 | if ("HEVC" in typePart):
1160 | continue
1161 | elif type == "BDRemux":
1162 | if not ((nameRU in namesPart) and (nameOriginal in namesPart) and ((str(year) in namesPart) or (str(year - 1) in namesPart) or (str(year + 1) in namesPart)) and ("REMUX" in typePart) and (("1080P" in typePart) or ("1080I" in typePart))):
1163 | continue
1164 | elif type == "BDRip-HEVC 1080p":
1165 | if not ((nameRU in namesPart) and (nameOriginal in namesPart) and ((str(year) in namesPart) or (str(year - 1) in namesPart) or (str(year + 1) in namesPart)) and ("BDRIP" in typePart) and ("HEVC" in typePart) and ("1080P" in typePart)):
1166 | continue
1167 | else:
1168 | return None
1169 |
1170 | if ("3D" in typePart) or ("TS" in typePart) or ("LINE" in typePart):
1171 | continue
1172 |
1173 | request = urllib.request.Request("http://kinozal.tv/details.php?id={}".format(kinozalID), headers=headers)
1174 |
1175 | try:
1176 | response = opener.open(request)
1177 | except:
1178 | response = opener.open(request)
1179 |
1180 | if response.info().get("Content-Encoding") == "gzip":
1181 | gzipFile = gzip.GzipFile(fileobj=response)
1182 | content = gzipFile.read().decode(response.info().get_content_charset())
1183 | else:
1184 | content = response.read().decode(response.info().get_content_charset())
1185 | patternTabID = re.compile("Релиз".format(kinozalID))
1186 | matches = re.findall(patternTabID, content)
1187 | if len(matches) != 1:
1188 | continue
1189 |
1190 | request = urllib.request.Request("http://kinozal.tv/get_srv_details.php?id={}&pagesd={}".format(kinozalID, matches[0]), headers=headers)
1191 | try:
1192 | response = opener.open(request)
1193 | except:
1194 | response = opener.open(request)
1195 | if response.info().get("Content-Encoding") == "gzip":
1196 | gzipFile = gzip.GzipFile(fileobj=response)
1197 | content = gzipFile.read().decode(response.info().get_content_charset())
1198 | else:
1199 | content = response.read().decode(response.info().get_content_charset())
1200 |
1201 | content = content.upper()
1202 | pmAudioOK = False
1203 |
1204 | if ("ЛИЦЕНЗИЯ" in content) or ("ITUNES" in content) or ("НЕВАФИЛЬМ" in content) or ("ПИФАГОР" in content) or ("AMEDIA" in content) or ("МОСФИЛЬМ-МАСТЕР" in content) or ("СВ-ДУБЛЬ" in content) or ("АРК-ТВ" in content) or ("APK-ТВ" in content) or ("APK-TB" in content) or ("КИРИЛЛИЦА" in content):
1205 | pmAudioOK = True
1206 |
1207 | license = False
1208 | if ("ЛИЦЕНЗИЯ" in content):
1209 | license = True
1210 |
1211 | if ("RUS TRANSFER" in typePart) or ("РУ" in typePart):
1212 | license = True
1213 |
1214 | if ("ДБ" in typePart) or ("РУ" in typePart):
1215 | if licenseOnly:
1216 | if license:
1217 | DBResults.append({"fullName": fullName, "kinozalID": kinozalID, "torrentDate": torrentDate, "seeders":seeders, "leechers": leechers, "license": license})
1218 | else:
1219 | #print(content)
1220 | #print(license)
1221 | DBResults.append({"fullName": fullName, "kinozalID": kinozalID, "torrentDate": torrentDate, "seeders":seeders, "leechers": leechers, "license": license})
1222 |
1223 | if ("ПМ" in typePart) and pmAudioOK and not (("ДБ" in typePart) or ("РУ" in typePart)):
1224 | if licenseOnly:
1225 | if license:
1226 | PMResults.append({"fullName": fullName, "kinozalID": kinozalID, "torrentDate": torrentDate, "seeders":seeders, "leechers": leechers, "license": license})
1227 | else:
1228 | PMResults.append({"fullName": fullName, "kinozalID": kinozalID, "torrentDate": torrentDate, "seeders":seeders, "leechers": leechers, "license": license})
1229 |
1230 | if len(DBResults) > 0:
1231 | DBResults.sort(key = operator.itemgetter("license", "seeders"), reverse = True)
1232 | if DBResults[0]["seeders"] == 0:
1233 | #return None
1234 | DBResults.sort(key = operator.itemgetter("license", "torrentDate"), reverse = True)
1235 | request = urllib.request.Request("http://kinozal.tv/get_srv_details.php?id={}&action=2".format(DBResults[0]["kinozalID"]), headers=headers)
1236 | try:
1237 | response = opener.open(request)
1238 | except:
1239 | response = opener.open(request)
1240 | if response.info().get("Content-Encoding") == "gzip":
1241 | gzipFile = gzip.GzipFile(fileobj=response)
1242 | content = gzipFile.read().decode(response.info().get_content_charset())
1243 | else:
1244 | content = response.read().decode(response.info().get_content_charset())
1245 |
1246 | patternHash = re.compile("[A-F0-9]{40}")
1247 | match = re.search(patternHash, content)
1248 |
1249 | if not match:
1250 | return None
1251 |
1252 | return {"link": "http://dl.kinozal.tv/download.php?id={}".format(DBResults[0]["kinozalID"]), "magnet": "magnet:?xt=urn:btih:{}&dn=kinozal.tv".format(match[0]), "date": DBResults[0]["torrentDate"], "type": type, "license": DBResults[0]["license"]}
1253 | elif len(PMResults) > 0:
1254 | PMResults.sort(key = operator.itemgetter("license", "seeders"), reverse = True)
1255 | if PMResults[0]["seeders"] == 0:
1256 | #return None
1257 | PMResults.sort(key = operator.itemgetter("license", "torrentDate"), reverse = True)
1258 | request = urllib.request.Request("http://kinozal.tv/get_srv_details.php?id={}&action=2".format(PMResults[0]["kinozalID"]), headers=headers)
1259 | try:
1260 | response = opener.open(request)
1261 | except:
1262 | response = opener.open(request)
1263 | if response.info().get("Content-Encoding") == "gzip":
1264 | gzipFile = gzip.GzipFile(fileobj=response)
1265 | content = gzipFile.read().decode(response.info().get_content_charset())
1266 | else:
1267 | content = response.read().decode(response.info().get_content_charset())
1268 |
1269 | patternHash = re.compile("[A-F0-9]{40}")
1270 | match = re.search(patternHash, content)
1271 |
1272 | if not match:
1273 | return None
1274 |
1275 | return {"link": "http://dl.kinozal.tv/download.php?id={}".format(PMResults[0]["kinozalID"]), "magnet": "magnet:?xt=urn:btih:{}&dn=kinozal.tv".format(match[0]), "date": PMResults[0]["torrentDate"], "type": type, "license": PMResults[0]["license"]}
1276 | return None
1277 |
1278 | def saveHTML(movies, filePath, useMagnet=USE_MAGNET):
1279 | f = open(filePath,'w', encoding='utf-8')
1280 | html = """
1281 |
1282 |
1283 |
1284 |
1285 |
1286 | Новые цифровые релизы
1287 |
1584 |
1634 |
1635 |
1636 |
1637 |
1638 |
1639 |
1640 |
1641 | """
1642 | descriptionTemplate = """
1643 |
1644 | | {} |
1645 |
1646 |
1647 | {}
1648 |
1649 | |
1650 | """
1651 | buttonsTemplate = """ """
1652 | buttonsTemplateS = """ """
1653 | movieTemplate = """
1654 |
1655 |
1659 |
1660 |
1661 | {}
1662 | 
1663 |
1664 |
1665 |
1666 |
1667 |
1668 |
1669 |
1670 |
1671 | {}
1672 |
1673 |
1674 | {}
1675 |
1676 |
1677 |
1678 | {}
1679 |
1680 |
1681 | """
1682 | for movie in movies:
1683 |
1684 | descriptionBlock = ""
1685 | descriptionBlock += descriptionTemplate.format("год", movie["year"])
1686 | descriptionBlock += descriptionTemplate.format("страна", movie["country"])
1687 | descriptionBlock += descriptionTemplate.format("режиссёр", movie["directors"])
1688 | descriptionBlock += descriptionTemplate.format("актёры", movie["actors"])
1689 | descriptionBlock += descriptionTemplate.format("жанр", movie["genre"])
1690 | if len(movie["ratingAgeLimits"]) > 0:
1691 | try:
1692 | if int(movie["ratingAgeLimits"]) < 6:
1693 | descriptionBlock += descriptionTemplate.format("возраст", "любой")
1694 | elif int(movie["ratingAgeLimits"]) < 12:
1695 | descriptionBlock += descriptionTemplate.format("возраст", "от 6 лет")
1696 | elif int(movie["ratingAgeLimits"]) < 16:
1697 | descriptionBlock += descriptionTemplate.format("возраст", "от 12 лет")
1698 | elif int(movie["ratingAgeLimits"]) < 18:
1699 | descriptionBlock += descriptionTemplate.format("возраст", "от 16 лет")
1700 | else:
1701 | descriptionBlock += descriptionTemplate.format("возраст", "от 18 лет")
1702 | except:
1703 | pass
1704 | elif len(movie["ratingMPAA"]) > 0:
1705 | if movie["ratingMPAA"] == "G":
1706 | descriptionBlock += descriptionTemplate.format("возраст", "любой")
1707 | elif movie["ratingMPAA"] == "PG":
1708 | descriptionBlock += descriptionTemplate.format("возраст", "от 6 лет")
1709 | elif movie["ratingMPAA"] == "PG-13":
1710 | descriptionBlock += descriptionTemplate.format("возраст", "от 12 лет")
1711 | elif movie["ratingMPAA"] == "R":
1712 | descriptionBlock += descriptionTemplate.format("возраст", "от 16 лет")
1713 | else:
1714 | descriptionBlock += descriptionTemplate.format("возраст", "от 18 лет")
1715 | descriptionBlock += descriptionTemplate.format("продолжительность", movie["filmLength"])
1716 |
1717 | if len(movie["ratingKP"]) > 0:
1718 | rKP = movie["ratingKP"]
1719 | else:
1720 | if movie["ratingKPCount"] == 0:
1721 | rKP = "нет"
1722 | elif movie["ratingKPCount"] < MIN_VOTES_KP:
1723 | rKP = "мало голосов"
1724 | else:
1725 | rKP = "нет"
1726 |
1727 | descriptionBlock += descriptionTemplate.format("рейтинг КиноПоиск", " {}".format(movie["webURL"], rKP))
1728 |
1729 | if len(movie["ratingIMDb"]) > 0:
1730 | rIMDb = movie["ratingIMDb"]
1731 | else:
1732 | if movie["ratingIMDbCount"] == 0:
1733 | rIMDb = "нет"
1734 | elif movie["ratingIMDbCount"] < MIN_VOTES_IMDB:
1735 | rIMDb = "мало голосов"
1736 | else:
1737 | rIMDb = "нет"
1738 |
1739 | descriptionBlock += descriptionTemplate.format("рейтинг IMDb", rIMDb)
1740 |
1741 | # if len(movie["ratingIMDb"]) > 0:
1742 | # descriptionBlock += descriptionTemplate.format("рейтинг IMDb", movie["ratingIMDb"])
1743 | # else:
1744 | # descriptionBlock += descriptionTemplate.format("рейтинг IMDb", "нет (возможно, мало голосов)")
1745 |
1746 | prHeader = "премьера"
1747 | if movie["premierType"] == "digital":
1748 | prHeader = "цифровая премьера"
1749 | elif movie["premierType"] == "ru":
1750 | prHeader = "премьера в России"
1751 | descriptionBlock += descriptionTemplate.format(prHeader, movie["premierDate"].strftime("%d.%m.%Y"))
1752 | #descriptionBlock += descriptionTemplate.format("торрент-релиз", " {} ({})".format("http://rutor.info/search/0/0/010/0/film%20" + movie["filmID"], movie["torrentsDate"].strftime("%d.%m.%Y"), movie["torrentsDateType"]))
1753 | descriptionBlock += descriptionTemplate.format("торрент-релиз", "{}".format(movie["torrentsDate"].strftime("%d.%m.%Y")))
1754 | #descriptionBlock += descriptionTemplate.format("описание", movie["description"])
1755 | descriptionBlock += descriptionTemplate.format("тип торрент-релиза", movie["torrentsDateType"])
1756 |
1757 |
1758 | torrents = movie["torrents"]
1759 | buttonsBlock = ""
1760 | for torrent in torrents:
1761 | if torrent["license"]:
1762 | if useMagnet:
1763 | buttonsBlock += buttonsTemplateS.format(torrent["magnet"], torrent["type"])
1764 | else:
1765 | buttonsBlock += buttonsTemplateS.format(torrent["link"], torrent["type"])
1766 | else:
1767 | if useMagnet:
1768 | buttonsBlock += buttonsTemplate.format(torrent["magnet"], torrent["type"])
1769 | else:
1770 | buttonsBlock += buttonsTemplate.format(torrent["link"], torrent["type"])
1771 |
1772 | displayOrigName = "display: none;"
1773 | if len(movie["nameOriginal"]) > 0:
1774 | displayOrigName = ""
1775 |
1776 | ratingStyle = "background-color: #aaa;"
1777 | if movie["ratingFloat"] >= 7:
1778 | ratingStyle = "background-color: #3bb33b;"
1779 | elif movie["ratingFloat"] < 5.5:
1780 | ratingStyle = "background-color: #b43c3c;"
1781 |
1782 | rating = movie["rating"]
1783 | if movie["ratingFloat"] < 1:
1784 | ratingStyle = "display: none;"
1785 | rating = "—"
1786 |
1787 | html += movieTemplate.format(movie["torrentsDate"].strftime("%Y-%m-%d"), movie["torrentsDate"].strftime("%Y-%m-%d"), movie["rating"], movie["torrentsDate"].strftime("%Y-%m-%d"), movie["nameRU"], displayOrigName, movie["nameOriginal"], ratingStyle, rating, movie["posterURL"], movie["nameRU"], "https://www.kinopoisk.ru/film/{}/video/".format(movie["filmID"]), descriptionBlock, movie["description"], buttonsBlock)
1788 |
1789 | #html += movieTemplate.format(movie["torrentsDate"].strftime("%Y-%m-%d"), movie["torrentsDate"].strftime("%Y-%m-%d"), movie["rating"], movie["torrentsDate"].strftime("%Y-%m-%d"), movie["nameRU"], displayOrigName, movie["nameOriginal"], ratingStyle, rating, movie["posterURL"], movie["nameRU"], movie["trailerURL"], descriptionBlock, movie["description"], buttonsBlock)
1790 | html += """
1791 |
1792 |
1793 | """
1794 | f.write(html)
1795 | f.close()
1796 | return
1797 |
1798 | try:
1799 | exitCode = main()
1800 | except:
1801 | exitCode = 1
1802 |
1803 | sys.exit(exitCode)
--------------------------------------------------------------------------------
|