Last active
February 18, 2021 18:36
-
-
Save danilvalov/720966d26e99f06aed41 to your computer and use it in GitHub Desktop.
FlexGet Kinopoisk plugin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
templates: | |
movies: | |
set: | |
path: /tmp/mnt/94E8B2B1E8B290CA/Torrents/download/DLNA/Movies | |
transmission: | |
host: ************ | |
port: **** | |
username: ************* | |
password: ************* | |
email: | |
from: **********@**********.ru | |
to: **********@**********.ru | |
title: FlexGet Notification | |
smtp_host: ************* | |
smtp_port: 25 | |
smtp_username: ************* | |
smtp_password: '*************' | |
tasks: | |
nnm-club: | |
rss: | |
url: http://nnm-club.me/forum/rss2.php?f=218&t=1&uk=************* | |
other_fields: [description] | |
ascii: yes | |
accept_all: yes | |
manipulate: | |
- title: | |
replace: | |
regexp: '[^\x00-\x80]+' | |
format: '' | |
- kinopoisk_id: | |
from: description | |
replace: | |
regexp: '(.|\n)*kinopoisk.ru/rating/([0-9]+)(.|\n)*' | |
format: '\2' | |
kinopoisk: | |
min_score: 7.0 | |
min_votes: 1000 | |
template: | |
- movies |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import unicode_literals, division, absolute_import | |
import urllib2, xmltodict | |
import logging | |
from flexget import plugin | |
from flexget.event import event | |
from flexget.plugins.filter.seen import FilterSeen | |
log = logging.getLogger('kinopoisk') | |
class FilterKinopoisk(FilterSeen): | |
""" | |
Kinopoisk filter | |
Using: | |
Add option to config.yml: | |
kinopoisk: | |
min_score: 7.0 # ignore movies with score below 7.0, default: 0 | |
min_votes: 1000 # ignore movies with votes below 1000, default: 0 | |
matching: 'strict' # ignore entries without kinopoisk_id, values: 'strict' or 'loose', default: 'strict' | |
scope: 'local' # use global or local storage, values: 'global' or 'local', default: 'global' | |
Please, replace values of '7.0' and '1000' to your | |
""" | |
schema = { | |
'oneOf': [ | |
{ | |
'type': 'object', | |
'properties': { | |
'min_score': {'type': 'number'}, | |
'min_votes': {'type': 'integer'}, | |
'matching': {'type': 'string', 'enum': ['strict', 'loose']}, | |
'scope': {'type': 'string', 'enum': ['global', 'local']} | |
} | |
} | |
] | |
} | |
def __init__(self): | |
# remember and filter by these fields | |
self.fields = ['kinopoisk_id'] | |
self.keyword = 'kinopoisk' | |
def is_number(self, s): | |
try: | |
float(s) | |
return True | |
except ValueError: | |
return False | |
@plugin.priority(0) # Make filter run after other filters, but before exists_movies | |
def on_task_filter(self, task, config): | |
if config is False: | |
return | |
# Reject all entries without kinopoisk id | |
if config.get('matching') != 'loose': | |
for entry in task.entries: | |
if 'kinopoisk_id' not in entry or not self.is_number(entry['kinopoisk_id']): | |
log.info('Rejecting %s because of missing movie kinopoisk id' % entry['title']) | |
entry.reject('Missing movie kinopoisk id') | |
# call super | |
super(FilterKinopoisk, self).on_task_filter(task, config.get('scope', True)) | |
# check that two copies of a movie have not been accepted this run | |
kinopoisk_ids = set() | |
for entry in task.accepted: | |
if not self.is_number(entry['kinopoisk_id']): | |
entry.reject('Kinopoisk ID not found') | |
continue | |
if entry['kinopoisk_id'] in kinopoisk_ids and self.is_number(entry['kinopoisk_id']): | |
entry.reject('Already accepted once in task') | |
continue | |
else: | |
kinopoisk_ids.add(entry['kinopoisk_id']) | |
try: | |
page = urllib2.urlopen('http://rating.kinopoisk.ru/' + entry['kinopoisk_id'] + '.xml') | |
except urllib2.HTTPError: | |
entry.reject('Rating is not found') | |
continue | |
doc = page.read() | |
page.close() | |
data = xmltodict.parse(doc) | |
score = float(data['rating']['kp_rating']['#text']) | |
votes = float(data['rating']['kp_rating']['@num_vote']) | |
if 'min_score' in config: | |
if score <= 0: | |
entry.reject('Score is zero') | |
continue | |
if score < config['min_score']: | |
entry.reject('Score (%s) below minimum (%s)' % (score, config['min_score'])) | |
continue | |
if 'min_votes' in config: | |
if votes < config['min_votes']: | |
entry.reject('Votes (%s) below minimum (%s)' % (votes, config['min_votes'])) | |
continue | |
log.debug('Accepting %s' % (entry['title'])) | |
@event('plugin.register') | |
def register_plugin(): | |
plugin.register(FilterKinopoisk, 'kinopoisk', api_ver=2) |
@githubroman
The following regexp finds kinopoisk ids in kinopoisk urls on any page:
https://gist.github.com/danilvalov/720966d26e99f06aed41#file-config-yml-L34
For example:
you have the following description:
<description><a href="https://nnmclub.to/forum/viewtopic.php?t=1080824">тема на форуме</a><br><span style="text-align: center; display: block;"><span style="color: Indigo"><span style="font-size: 20px; line-height: normal"><span style="font-weight: bold"> Морган / Morgan (2016) BDRip [H.264/720p-LQ]</span></span></span></span><span style="text-align: center; display: block;"><span style="color: gray"><span style="font-weight: bold">«Don't let it out»</span></span></span> <hr /><img src="{ASSETS}/forum/image.php?link=http://s020.radikal.ru/i713/1612/4b/0b3129627bb5.jpg"><span style="font-weight: bold">Производство:</span> США / Scott Free Productions<br /><span style="font-weight: bold">Жанр:</span> Ужасы, Фантастика, Триллер, Детектив<br /><br /><span style="font-weight: bold">Режиссер:</span> Люк Скотт<br /><span style="font-weight: bold">Актеры:</span> Кейт Мара, Аня Тейлор-Джой, Роуз Лесли, Майкл Йар, Тоби Джонс, Крис Салливан, Бойд Холбрук, Винетт Робинсон, Мишель Йео, Брайан Кокс<br /><br /><span style="font-weight: bold">Описание:</span><br />Сотрудница по устранению аварий отправляется в отдаленный секретный филиал, где должна расследовать и оценить потери от ужасной катастрофы. На месте она узнает, что случившееся было вызвано, казалось бы, невинным «человеком», чье существование само по себе является опасной тайной.<br /><br /><span id="kpjsrch"></span> <a id="kp_id" href="http://www.kinopoisk.ru/film/906340/" target="_blank" rel="nofollow"><img src="https://www.kinopoisk.ru/rating/906340.gif"></a> <a id="imdb_id" href="http://www.imdb.com/title/tt4520364/" target="_blank" rel="nofollow"><img src="http://imdb.snick.ru/ratefor/02/tt4520364.png"></a><br /><span style="font-size: 11px; line-height: normal"><span style="font-weight: bold">Возраст:</span> <span style="color: #FF0000"><span style="font-weight: bold">18+</span></span> <span style="color: #CC0000">(зрителям, достигшим 18 лет. запрещено для детей)</span></span><br /><span style="font-size: 11px; line-height: normal"><span style="font-weight: bold">Рейтинг MPAA:</span> <span style="color: #FF6000"><span style="font-weight: bold">R</span> (лицам до 17 лет обязательно присутствие взрослого)</span></span><br /><span style="font-size: 11px; line-height: normal"><span style="font-weight: bold">Дата мировой премьеры:</span> 1 сентября 2016</span><br /><span style="font-size: 11px; line-height: normal"><span style="font-weight: bold">Дата российской премьеры:</span> 8 сентября 2016, «Двадцатый Век Фокс СНГ»</span><br /><br /><span style="font-weight: bold">Релиз от:</span> <img src="{ASSETS}/forum/image.php?link=http://s020.radikal.ru/i712/1503/80/49b7bc4e3261.gif"> <span style="color: blue">NNMClub</span><br /><br /><span style="font-weight: bold">Продолжительность:</span> 01:31:52<br /><span style="font-weight: bold">Качество видео:</span> BDRip <a href="http://sendfile.su/1288607" rel="nofollow" class="postLink"><img src="{ASSETS}/forum/image.php?link=http://nnmclub.to/forum/images/channel/sample_light_nnm.png"></a><br /><span style="font-weight: bold">Перевод:</span> Дублированный (iTunes)<br /><span style="font-weight: bold">Вид субтитров:</span> Вшитые отключаемые<br /><span style="font-weight: bold">Язык субтитров:</span> Русский (форсированные на иностранные надписи)<br /><br /><span style="font-weight: bold">Видео:</span> H.264/AVC, 1280x536, 2938 kbps, 23.976 fps<br /><span style="font-weight: bold">Аудио:</span> AC3, 6 ch, 384 Kbps - Русский </a><div class="clear"></div> </a><div class="clear"></div> <div class="clear"></div><span style="text-align: center; display: block;"><span style="font-weight: bold">Скриншоты:</span><br /><a href="http://i5.imageban.ru/out/2016/12/07/d35e0e0ae99ca77b3ebdc69e77ec85cf.png" class="highslide" onclick="return hs.expand(this,{slideshowGroup: '8668771'})" rel="nofollow"><img src="{ASSETS}/forum/image.php?link=http://i4.imageban.ru/out/2016/12/07/4fc737ff3ff2f5e21f4fdc8e3027e635.png"></a> <a href="http://i2.imageban.ru/out/2016/12/07/7637dcf726f41bd78ef402e4ef8b78c9.png" class="highslide" onclick="return hs.expand(this,{slideshowGroup: '8668771'})" rel="nofollow"><img src="{ASSETS}/forum/image.php?link=http://i3.imageban.ru/out/2016/12/07/a3af40b6b0117e8618196ce7ec2f6056.png"></a> <a href="http://i5.imageban.ru/out/2016/12/07/618b741b4b80ac0c1d462339ed545cf0.png" class="highslide" onclick="return hs.expand(this,{slideshowGroup: '8668771'})" rel="nofollow"><img src="{ASSETS}/forum/image.php?link=http://i1.imageban.ru/out/2016/12/07/163e19955ccd5ff8e8773cddb5f1c29e.png"></a> <a href="http://i3.imageban.ru/out/2016/12/07/8db0d0a44c1afe42868e6a84f4341f4c.png" class="highslide" onclick="return hs.expand(this,{slideshowGroup: '8668771'})" rel="nofollow"><img src="{ASSETS}/forum/image.php?link=http://i3.imageban.ru/out/2016/12/07/85bec5c826a2796e7378cd5d37ea22fe.png"></a><br /></span><br /><span style="text-align: center; display: block;"><a href="http://nnmclub.to/?q=Morgan+2016&amp;w=title" rel="nofollow" class="postLink"><span style="font-size: 16px; line-height: normal"><span style="color: #800000"><span style="font-weight: bold">Все одноименные релизы в Клубе</span></span></span></a></span><br /><span style="font-size: 12px; line-height: normal"><span style="font-weight: bold">Время раздачи:</span> 24/7 до первых 10-и скачавших</span></description>
and we can see the following part:
... href="http://www.kinopoisk.ru/film/906340/" ...
The script find this url by regexp and get the kinopoisk id.
You can use this manipulate for any pages with kinopoisk urls. Or you can rewrite the regexp to get the kinopoisk id from another data types.
how we login to nnmclub? where to set cookies or what's uk ?
uk
is the passkey from the update profile page:
https://nnmclub.to/forum/profile.php?mode=editprofile
2018-04-22 21:21 CRITICAL task nnm-club BUG: Unhandled error in plugin kinopoisk: not well-formed (invalid token): line 1, column 0
Traceback (most recent call last):
File "d:\program\python\python27\lib\site-packages\flexget\task.py", line 486, in __run_plugin
return method(*args, **kwargs)
File "d:\program\python\python27\lib\site-packages\flexget\event.py", line 23, in __call__
return self.func(*args, **kwargs)
File "C:\Users\222\flexget\plugins\kinopoisk.py", line 90, in on_task_filter
data = xmltodict.parse(doc)
File "d:\program\python\python27\lib\site-packages\xmltodict.py", line 330, in parse
parser.Parse(xml_input, True)
ExpatError: not well-formed (invalid token): line 1, column 0
Как пофиксить? Спасибо.
2018-04-22 21:21 CRITICAL task nnm-club BUG: Unhandled error in plugin kinopoisk: not well-formed (invalid token): line 1, column 0 Traceback (most recent call last): File "d:\program\python\python27\lib\site-packages\flexget\task.py", line 486, in __run_plugin return method(*args, **kwargs) File "d:\program\python\python27\lib\site-packages\flexget\event.py", line 23, in __call__ return self.func(*args, **kwargs) File "C:\Users\222\flexget\plugins\kinopoisk.py", line 90, in on_task_filter data = xmltodict.parse(doc) File "d:\program\python\python27\lib\site-packages\xmltodict.py", line 330, in parse parser.Parse(xml_input, True) ExpatError: not well-formed (invalid token): line 1, column 0
Как пофиксить? Спасибо.
Looks like sometimes it gives reponse in gzip format. It can be fixed like that:
doc = page.read()
page.close()
try:
data = xmltodict.parse(doc)
except ExpatError:
compressed_data = io.BytesIO(doc)
for compressed_data_item in gzip.GzipFile(fileobj=compressed_data):
data = xmltodict.parse(compressed_data_item)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@XBeg9
It works for me: