mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-05-16 14:03:44 +08:00
2.5.11 若干调整
- 调整 TDMB 识别器 - 调整番剧补全功能 - 调整获取 torrent 添加过滤器
This commit is contained in:
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: build-docker-image
|
name: Build(Docker)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -163,13 +163,13 @@ cython_debug/
|
|||||||
|
|
||||||
# Custom
|
# Custom
|
||||||
/auto_bangumi/conf/const_dev.py
|
/auto_bangumi/conf/const_dev.py
|
||||||
/config/bangumi.json
|
/config
|
||||||
/auto_bangumi/tester.py
|
/auto_bangumi/tester.py
|
||||||
/resource/names.txt
|
/resource/names.txt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/auto_bangumi/parser/analyser/tmdb.py
|
/auto_bangumi/parser/analyser/tmdb_parser.py
|
||||||
|
|
||||||
/auto_bangumi/run_debug.sh
|
/auto_bangumi/run_debug.sh
|
||||||
/auto_bangumi/debug_run.sh
|
/auto_bangumi/debug_run.sh
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
DEFAULT_SETTINGS = {
|
DEFAULT_SETTINGS = {
|
||||||
"version": "2.5.10",
|
"version": "2.5.11",
|
||||||
"data_version": 4.0,
|
"data_version": 4.0,
|
||||||
"host_ip": "localhost:8080",
|
"host_ip": "localhost:8080",
|
||||||
"sleep_time": 7200,
|
"sleep_time": 7200,
|
||||||
@@ -12,7 +12,7 @@ DEFAULT_SETTINGS = {
|
|||||||
"method": "pn",
|
"method": "pn",
|
||||||
"enable_group_tag": False,
|
"enable_group_tag": False,
|
||||||
"info_path": "/config/bangumi.json",
|
"info_path": "/config/bangumi.json",
|
||||||
"not_contain": "720",
|
"not_contain": r"720|\d+-\d+",
|
||||||
"rule_name_re": r"\:|\/|\.",
|
"rule_name_re": r"\:|\/|\.",
|
||||||
"connect_retry_interval": 5,
|
"connect_retry_interval": 5,
|
||||||
"debug_mode": False,
|
"debug_mode": False,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
from attrdict import AttrDict
|
||||||
|
|
||||||
from downloader import getClient
|
from downloader import getClient
|
||||||
from downloader.exceptions import ConflictError
|
from downloader.exceptions import ConflictError
|
||||||
@@ -54,17 +55,25 @@ class DownloadClient:
|
|||||||
logger.info(f"Add {official_name} Season {season}")
|
logger.info(f"Add {official_name} Season {season}")
|
||||||
|
|
||||||
def rss_feed(self):
|
def rss_feed(self):
|
||||||
try:
|
if not settings.refresh_rss:
|
||||||
self.client.rss_remove_item(item_path="Mikan_RSS")
|
if self.client.get_rss_info() == settings.rss_link:
|
||||||
except ConflictError:
|
logger.info("RSS Already exists.")
|
||||||
logger.info("No feed exists, start adding feed.")
|
else:
|
||||||
try:
|
logger.info("No feed exists, start adding feed.")
|
||||||
self.client.rss_add_feed(url=settings.rss_link, item_path="Mikan_RSS")
|
self.client.rss_add_feed(url=settings.rss_link, item_path="Mikan_RSS")
|
||||||
logger.info("Add RSS Feed successfully.")
|
logger.info("Add RSS Feed successfully.")
|
||||||
except ConnectionError:
|
else:
|
||||||
logger.warning("Error with adding RSS Feed.")
|
try:
|
||||||
except ConflictError:
|
self.client.rss_remove_item(item_path="Mikan_RSS")
|
||||||
logger.info("RSS Already exists.")
|
except ConflictError:
|
||||||
|
logger.info("No feed exists, start adding feed.")
|
||||||
|
try:
|
||||||
|
self.client.rss_add_feed(url=settings.rss_link, item_path="Mikan_RSS")
|
||||||
|
logger.info("Add RSS Feed successfully.")
|
||||||
|
except ConnectionError:
|
||||||
|
logger.warning("Error with adding RSS Feed.")
|
||||||
|
except ConflictError:
|
||||||
|
logger.info("RSS Already exists.")
|
||||||
|
|
||||||
def add_collection_feed(self, rss_link, item_path):
|
def add_collection_feed(self, rss_link, item_path):
|
||||||
self.client.rss_add_feed(url=rss_link, item_path=item_path)
|
self.client.rss_add_feed(url=rss_link, item_path=item_path)
|
||||||
@@ -79,7 +88,7 @@ class DownloadClient:
|
|||||||
# logger.info("to rule.")
|
# logger.info("to rule.")
|
||||||
logger.debug("Finished.")
|
logger.debug("Finished.")
|
||||||
|
|
||||||
def get_torrent_info(self):
|
def get_torrent_info(self) -> [AttrDict]:
|
||||||
return self.client.torrents_info(
|
return self.client.torrents_info(
|
||||||
status_filter="completed", category="Bangumi"
|
status_filter="completed", category="Bangumi"
|
||||||
)
|
)
|
||||||
@@ -113,6 +122,7 @@ class DownloadClient:
|
|||||||
self.client.rss_add_feed(url=rss_link, item_path=item_path)
|
self.client.rss_add_feed(url=rss_link, item_path=item_path)
|
||||||
logger.info("Add RSS Feed successfully.")
|
logger.info("Add RSS Feed successfully.")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
put = DownloadClient()
|
put = DownloadClient()
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class FullSeasonGet:
|
|||||||
downloads = []
|
downloads = []
|
||||||
for torrent in torrents:
|
for torrent in torrents:
|
||||||
download_info = {
|
download_info = {
|
||||||
"url": torrent,
|
"url": torrent.torrent_link,
|
||||||
"save_path": os.path.join(
|
"save_path": os.path.join(
|
||||||
settings.download_path,
|
settings.download_path,
|
||||||
data["official_title"],
|
data["official_title"],
|
||||||
@@ -77,4 +77,4 @@ if __name__ == "__main__":
|
|||||||
"added": True,
|
"added": True,
|
||||||
"eps_collect": True
|
"eps_collect": True
|
||||||
}
|
}
|
||||||
print(a.init_eps_complete_search_str(data))
|
print(a.init_eps_complete_search_str(data))
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ class Renamer:
|
|||||||
self.client = download_client
|
self.client = download_client
|
||||||
self._renamer = TitleParser()
|
self._renamer = TitleParser()
|
||||||
|
|
||||||
def print_result(self, torrent_count, rename_count):
|
@staticmethod
|
||||||
|
def print_result(torrent_count, rename_count):
|
||||||
if rename_count != 0:
|
if rename_count != 0:
|
||||||
logger.info(f"Finished checking {torrent_count} files' name, renamed {rename_count} files.")
|
logger.info(f"Finished checking {torrent_count} files' name, renamed {rename_count} files.")
|
||||||
logger.debug(f"Checked {torrent_count} files")
|
logger.debug(f"Checked {torrent_count} files")
|
||||||
@@ -27,7 +28,8 @@ class Renamer:
|
|||||||
torrent_count = len(recent_info)
|
torrent_count = len(recent_info)
|
||||||
return recent_info, torrent_count
|
return recent_info, torrent_count
|
||||||
|
|
||||||
def split_path(self, path: str):
|
@staticmethod
|
||||||
|
def split_path(path: str):
|
||||||
suffix = os.path.splitext(path)[-1]
|
suffix = os.path.splitext(path)[-1]
|
||||||
path = path.replace(settings.download_path, "")
|
path = path.replace(settings.download_path, "")
|
||||||
path_parts = PurePath(path).parts \
|
path_parts = PurePath(path).parts \
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ class RSSAnalyser:
|
|||||||
self._title_analyser = TitleParser()
|
self._title_analyser = TitleParser()
|
||||||
self._request = RequestContent()
|
self._request = RequestContent()
|
||||||
|
|
||||||
def rss_to_datas(self, bangumi_info: list):
|
def rss_to_datas(self, bangumi_info: list) -> list:
|
||||||
rss_titles = self._request.get_titles(settings.rss_link)
|
rss_torrents = self._request.get_torrents(settings.rss_link)
|
||||||
self._request.close_session()
|
self._request.close_session()
|
||||||
for raw_title in rss_titles:
|
for torrent in rss_torrents:
|
||||||
|
raw_title = torrent.name
|
||||||
extra_add = True
|
extra_add = True
|
||||||
if bangumi_info is not []:
|
if bangumi_info is not []:
|
||||||
for d in bangumi_info:
|
for d in bangumi_info:
|
||||||
@@ -27,18 +28,16 @@ class RSSAnalyser:
|
|||||||
logger.debug(f"Had added {d['title_raw']} before")
|
logger.debug(f"Had added {d['title_raw']} before")
|
||||||
extra_add = False
|
extra_add = False
|
||||||
break
|
break
|
||||||
if re.search(settings.not_contain, raw_title) is not None:
|
|
||||||
extra_add = False
|
|
||||||
if extra_add:
|
if extra_add:
|
||||||
data = self._title_analyser.return_dict(raw_title)
|
data = self._title_analyser.return_dict(raw_title)
|
||||||
if data is not None and data["official_title"] not in bangumi_info:
|
if data is not None and data["official_title"] not in bangumi_info:
|
||||||
bangumi_info.append(data)
|
bangumi_info.append(data)
|
||||||
return bangumi_info
|
return bangumi_info
|
||||||
|
|
||||||
def rss_to_data(self, url):
|
def rss_to_data(self, url) -> dict:
|
||||||
rss_title = self._request.get_title(url)
|
rss_torrents = self._request.get_torrents(url)
|
||||||
self._request.close_session()
|
self._request.close_session()
|
||||||
data = self._title_analyser.return_dict(rss_title)
|
data = self._title_analyser.return_dict(rss_torrents[0].name)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def run(self, bangumi_info: list, download_client: DownloadClient):
|
def run(self, bangumi_info: list, download_client: DownloadClient):
|
||||||
|
|||||||
@@ -59,6 +59,13 @@ class QbDownloader:
|
|||||||
def torrents_rename_file(self, torrent_hash, old_path, new_path):
|
def torrents_rename_file(self, torrent_hash, old_path, new_path):
|
||||||
self._client.torrents_rename_file(torrent_hash=torrent_hash, old_path=old_path, new_path=new_path)
|
self._client.torrents_rename_file(torrent_hash=torrent_hash, old_path=old_path, new_path=new_path)
|
||||||
|
|
||||||
|
def get_rss_info(self):
|
||||||
|
item = self._client.rss_items().get("Mikan_RSS")
|
||||||
|
if item is not None:
|
||||||
|
return item.url
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def rss_add_feed(self, url, item_path):
|
def rss_add_feed(self, url, item_path):
|
||||||
try:
|
try:
|
||||||
self._client.rss_add_feed(url, item_path)
|
self._client.rss_add_feed(url, item_path)
|
||||||
|
|||||||
@@ -1,4 +1,14 @@
|
|||||||
|
import re
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from network.request import RequestURL
|
from network.request import RequestURL
|
||||||
|
from conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TorrentInfo:
|
||||||
|
name: str
|
||||||
|
torrent_link: str
|
||||||
|
|
||||||
|
|
||||||
class RequestContent:
|
class RequestContent:
|
||||||
@@ -6,23 +16,24 @@ class RequestContent:
|
|||||||
self._req = RequestURL()
|
self._req = RequestURL()
|
||||||
|
|
||||||
# Mikanani RSS
|
# Mikanani RSS
|
||||||
def get_titles(self, url):
|
def get_torrents(self, url: str) -> [TorrentInfo]:
|
||||||
soup = self._req.get_content(url)
|
soup = self._req.get_content(url)
|
||||||
items = soup.find_all("item")
|
torrent_titles = [item.title.string for item in soup.find_all("item")]
|
||||||
return [item.title.string for item in items]
|
keep_index = []
|
||||||
|
for idx, title in enumerate(torrent_titles):
|
||||||
|
if re.search(settings.not_contain, title) is None:
|
||||||
|
keep_index.append(idx)
|
||||||
|
torrent_urls = [item.get("url") for item in soup.find_all("enclosure")]
|
||||||
|
return [TorrentInfo(torrent_titles[i], torrent_urls[i]) for i in keep_index]
|
||||||
|
|
||||||
def get_title(self, url):
|
def get_torrent(self, url) -> TorrentInfo:
|
||||||
soup = self._req.get_content(url)
|
soup = self._req.get_content(url)
|
||||||
item = soup.find("item")
|
item = soup.find("item")
|
||||||
return item.title.string
|
enclosure = item.find("enclosure")
|
||||||
|
return TorrentInfo(item.title.string, enclosure["url"])
|
||||||
def get_torrents(self, url):
|
|
||||||
soup = self._req.get_content(url)
|
|
||||||
enclosure = soup.find_all("enclosure")
|
|
||||||
return [t["url"] for t in enclosure]
|
|
||||||
|
|
||||||
# API JSON
|
# API JSON
|
||||||
def get_json(self, url):
|
def get_json(self, url) -> dict:
|
||||||
return self._req.get_content(url, content="json")
|
return self._req.get_content(url, content="json")
|
||||||
|
|
||||||
def close_session(self):
|
def close_session(self):
|
||||||
@@ -31,6 +42,8 @@ class RequestContent:
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
r = RequestContent()
|
r = RequestContent()
|
||||||
url = "https://mikanani.me/RSS/Bangumi?bangumiId=2685&subgroupid=552"
|
rss_url = "https://mikanani.me/RSS/Bangumi?bangumiId=2739&subgroupid=203"
|
||||||
title = r.get_title(url)
|
titles = r.get_torrents(rss_url)
|
||||||
print(title)
|
print(settings.not_contain)
|
||||||
|
for title in titles:
|
||||||
|
print(title.name, title.torrent_link)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
from .raw_parser import RawParser
|
from .raw_parser import RawParser
|
||||||
from .rename_parser import DownloadParser
|
from .rename_parser import DownloadParser
|
||||||
from .tmdb import TMDBMatcher
|
from .tmdb_parser import TMDBMatcher
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from network import RequestContent
|
|||||||
from conf import settings
|
from conf import settings
|
||||||
|
|
||||||
|
|
||||||
class BangumiAPI:
|
class BgmAPI:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.search_url = lambda e: \
|
self.search_url = lambda e: \
|
||||||
f"https://api.bgm.tv/search/subject/{e}?type=2"
|
f"https://api.bgm.tv/search/subject/{e}?type=2"
|
||||||
@@ -21,7 +21,6 @@ class BangumiAPI:
|
|||||||
return contents[0]["name"], contents[0]["name_cn"]
|
return contents[0]["name"], contents[0]["name_cn"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
BGM = BangumiAPI()
|
BGM = BgmAPI()
|
||||||
print(BGM.search("辉夜大小姐"))
|
print(BGM.search("辉夜大小姐"))
|
||||||
@@ -128,7 +128,7 @@ class RawParser:
|
|||||||
sub, dpi, source = self.find_tags(other) # 剩余信息处理
|
sub, dpi, source = self.find_tags(other) # 剩余信息处理
|
||||||
return name, season, season_raw, episode, sub, dpi, source, name_group, group
|
return name, season, season_raw, episode, sub, dpi, source, name_group, group
|
||||||
|
|
||||||
def analyse(self, raw):
|
def analyse(self, raw: str) -> Episode or None:
|
||||||
try:
|
try:
|
||||||
ret = self.process(raw)
|
ret = self.process(raw)
|
||||||
if ret is None:
|
if ret is None:
|
||||||
@@ -150,5 +150,6 @@ class RawParser:
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test = RawParser()
|
test = RawParser()
|
||||||
ep = test.analyse("[ANi] Classroom of the Elite S2 - 欢迎来到实力至上主义的教室 第二季 - 01 [1080P][Baha][WEB-DL][AAC AVC][CHT][MP4]")
|
test_txt = "[SWSUB][7月新番][继母的拖油瓶是我的前女友/継母の连れ子が元カノだった][001][GB_JP][AVC][1080P][网盘][无修正] [331.6MB] [复制磁连]"
|
||||||
print(ep.title, ep.ep_info.number)
|
ep = test.analyse(test_txt)
|
||||||
|
print(ep.title)
|
||||||
|
|||||||
@@ -1,12 +1,23 @@
|
|||||||
|
import dataclasses
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
from os import path
|
from os import path
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
# from .raw_parser import RawParser
|
# from .raw_parser import RawParser
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DownloadInfo:
|
||||||
|
name: str
|
||||||
|
season: int
|
||||||
|
suffix: str
|
||||||
|
file_name: str
|
||||||
|
folder_name: str
|
||||||
|
|
||||||
|
|
||||||
class DownloadParser:
|
class DownloadParser:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.rules = [
|
self.rules = [
|
||||||
@@ -18,82 +29,65 @@ class DownloadParser:
|
|||||||
r"(.*)第(\d*\.*\d*)話(?:END)?(.*)",
|
r"(.*)第(\d*\.*\d*)話(?:END)?(.*)",
|
||||||
]
|
]
|
||||||
|
|
||||||
def rename_normal(self, info_dict):
|
@staticmethod
|
||||||
name = info_dict["name"]
|
def rename_init(name, folder_name, season, suffix) -> DownloadInfo:
|
||||||
season = info_dict["season"]
|
n = re.split(r"[\[\]()【】()]", name)
|
||||||
|
suffix = suffix if suffix is not None else n[-1]
|
||||||
|
file_name = name.replace(f"[{n[1]}]", "")
|
||||||
|
if season < 10:
|
||||||
|
season = f"0{season}"
|
||||||
|
return DownloadInfo(name, season, suffix, file_name, folder_name)
|
||||||
|
|
||||||
|
def rename_normal(self, info: DownloadInfo):
|
||||||
for rule in self.rules:
|
for rule in self.rules:
|
||||||
match_obj = re.match(rule, name, re.I)
|
match_obj = re.match(rule, name, re.I)
|
||||||
if match_obj is not None:
|
if match_obj is not None:
|
||||||
title = re.sub(r"([Ss]|Season )\d{1,3}", "", match_obj.group(1)).strip()
|
title = re.sub(r"([Ss]|Season )\d{1,3}", "", match_obj.group(1)).strip()
|
||||||
new_name = f"{title} S{season}E{match_obj.group(2)}{match_obj.group(3)}"
|
new_name = f"{title} S{info.season}E{match_obj.group(2)}{match_obj.group(3)}"
|
||||||
return new_name
|
return new_name
|
||||||
|
|
||||||
def rename_pn(self, info_dict):
|
def rename_pn(self, info: DownloadInfo):
|
||||||
name = info_dict["name"]
|
|
||||||
season = info_dict["season"]
|
|
||||||
suffix = info_dict["suffix"]
|
|
||||||
n = re.split(r"[\[\]()【】()]", name)
|
|
||||||
file_name = name.replace(f"[{n[1]}]", "")
|
|
||||||
if season < 10:
|
|
||||||
season = f"0{season}"
|
|
||||||
for rule in self.rules:
|
for rule in self.rules:
|
||||||
match_obj = re.match(rule, file_name, re.I)
|
match_obj = re.match(rule, info.file_name, re.I)
|
||||||
if match_obj is not None:
|
if match_obj is not None:
|
||||||
title = re.sub(r"([Ss]|Season )\d{1,3}", "", match_obj.group(1)).strip()
|
title = re.sub(r"([Ss]|Season )\d{1,3}", "", match_obj.group(1)).strip()
|
||||||
title = title if title != "" else info_dict.get("folder_name")
|
title = title if title != "" else info.folder_name
|
||||||
new_name = re.sub(
|
new_name = re.sub(
|
||||||
r"[\[\]]",
|
r"[\[\]]",
|
||||||
"",
|
"",
|
||||||
f"{title} S{season}E{match_obj.group(2)}{suffix}",
|
f"{title} S{info.season}E{match_obj.group(2)}{info.suffix}",
|
||||||
)
|
)
|
||||||
return new_name
|
return new_name
|
||||||
|
|
||||||
def rename_advance(self, info_dict):
|
def rename_advance(self, info: DownloadInfo):
|
||||||
name = info_dict["name"]
|
|
||||||
folder_name = info_dict["folder_name"]
|
|
||||||
suffix = info_dict["suffix"]
|
|
||||||
season = info_dict["season"]
|
|
||||||
n = re.split(r"[\[\]()【】()]", name)
|
|
||||||
file_name = name.replace(f"[{n[1]}]", "")
|
|
||||||
if season < 10:
|
|
||||||
season = f"0{season}"
|
|
||||||
for rule in self.rules:
|
for rule in self.rules:
|
||||||
match_obj = re.match(rule, file_name, re.I)
|
match_obj = re.match(rule, info.file_name, re.I)
|
||||||
if match_obj is not None:
|
if match_obj is not None:
|
||||||
new_name = re.sub(
|
new_name = re.sub(
|
||||||
r"[\[\]]",
|
r"[\[\]]",
|
||||||
"",
|
"",
|
||||||
f"{folder_name} S{season}E{match_obj.group(2)}{suffix}",
|
f"{info.folder_name} S{info.season}E{match_obj.group(2)}{info.suffix}",
|
||||||
)
|
)
|
||||||
return new_name
|
return new_name
|
||||||
|
|
||||||
def rename_no_season_pn(self, info_dict):
|
def rename_no_season_pn(self, info: DownloadInfo):
|
||||||
name = info_dict["name"]
|
|
||||||
suffix = info_dict["suffix"]
|
|
||||||
n = re.split(r"[\[\]()【】()]", name)
|
|
||||||
file_name = name.replace(f"[{n[1]}]", "")
|
|
||||||
for rule in self.rules:
|
for rule in self.rules:
|
||||||
match_obj = re.match(rule, file_name, re.I)
|
match_obj = re.match(rule, info.file_name, re.I)
|
||||||
if match_obj is not None:
|
if match_obj is not None:
|
||||||
title = match_obj.group(1).strip()
|
title = match_obj.group(1).strip()
|
||||||
new_name = re.sub(
|
new_name = re.sub(
|
||||||
r"[\[\]]",
|
r"[\[\]]",
|
||||||
"",
|
"",
|
||||||
f"{title} E{match_obj.group(2)}{suffix}",
|
f"{title} E{match_obj.group(2)}{info.suffix}",
|
||||||
)
|
)
|
||||||
return new_name
|
return new_name
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def rename_none(info_dict):
|
def rename_none(info: DownloadInfo):
|
||||||
return info_dict["name"]
|
return info.name
|
||||||
|
|
||||||
def download_rename(self, name, folder_name, season,suffix, method):
|
def download_rename(self, name, folder_name, season, suffix, method):
|
||||||
info_dict = {
|
rename_info = self.rename_init(name, folder_name, season, suffix)
|
||||||
"name": name,
|
|
||||||
"folder_name": folder_name,
|
|
||||||
"season": season,
|
|
||||||
"suffix": suffix
|
|
||||||
}
|
|
||||||
method_dict = {
|
method_dict = {
|
||||||
"normal": self.rename_normal,
|
"normal": self.rename_normal,
|
||||||
"pn": self.rename_pn,
|
"pn": self.rename_pn,
|
||||||
@@ -102,11 +96,11 @@ class DownloadParser:
|
|||||||
"none": self.rename_none
|
"none": self.rename_none
|
||||||
}
|
}
|
||||||
logger.debug(f"Name: {folder_name}, File type: {path.splitext(name)[-1]}, Season {season}")
|
logger.debug(f"Name: {folder_name}, File type: {path.splitext(name)[-1]}, Season {season}")
|
||||||
return method_dict[method.lower()](info_dict)
|
return method_dict[method.lower()](rename_info)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
name = "[Isekai Meikyuu de Harem wo][01][BIG5][1080P][AT-X].mp4"
|
name = "[sub][Isekai Meikyuu de Harem wo][01][BIG5][1080P][AT-X].mp4"
|
||||||
rename = DownloadParser()
|
rename = DownloadParser()
|
||||||
new_name = rename.download_rename(name, "Made abyess", 1, ".mp4", "Advance")
|
new_name = rename.download_rename(name, "Made abyess", 1, ".mp4", "pn")
|
||||||
print(new_name)
|
print(new_name)
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from network import RequestContent
|
from network import RequestContent
|
||||||
from conf import settings
|
from conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
class TMDBInfo:
|
class TMDBInfo:
|
||||||
id: int
|
id: int
|
||||||
title_jp: str
|
title_jp: str
|
||||||
title_zh: str
|
title_zh: str
|
||||||
season: dict
|
season: dict
|
||||||
last_season: int
|
last_season: int
|
||||||
|
year_number: int
|
||||||
|
|
||||||
|
|
||||||
class TMDBMatcher:
|
class TMDBMatcher:
|
||||||
@@ -21,11 +24,11 @@ class TMDBMatcher:
|
|||||||
f"https://api.themoviedb.org/3/tv/{e}?api_key={settings.tmdb_api}&language=zh-CN"
|
f"https://api.themoviedb.org/3/tv/{e}?api_key={settings.tmdb_api}&language=zh-CN"
|
||||||
self._request = RequestContent()
|
self._request = RequestContent()
|
||||||
|
|
||||||
def is_animation(self, id):
|
def is_animation(self, tv_id) -> bool:
|
||||||
url_info = self.info_url(id)
|
url_info = self.info_url(tv_id)
|
||||||
type_id = self._request.get_json(url_info)["genres"]
|
type_id = self._request.get_json(url_info)["genres"]
|
||||||
for type in type_id:
|
for type in type_id:
|
||||||
if type["id"] == 16:
|
if type.get("id") == 16:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -37,39 +40,40 @@ class TMDBMatcher:
|
|||||||
# return title["title"]
|
# return title["title"]
|
||||||
# return None
|
# return None
|
||||||
|
|
||||||
def get_season(self, seasons: list):
|
@staticmethod
|
||||||
|
def get_season(seasons: list) -> int:
|
||||||
for season in seasons:
|
for season in seasons:
|
||||||
if re.search(r"第 \d 季", season["season"]) is not None:
|
if re.search(r"第 \d 季", season.get("season")) is not None:
|
||||||
date = season["air_date"].split("-")
|
date = season.get("air_date").split("-")
|
||||||
[year, _ , _] = date
|
[year, _ , _] = date
|
||||||
now_year = time.localtime().tm_year
|
now_year = time.localtime().tm_year
|
||||||
if int(year) == now_year:
|
if int(year) == now_year:
|
||||||
return int(re.findall(r"\d", season["season"])[0])
|
return int(re.findall(r"\d", season.get("season"))[0])
|
||||||
|
|
||||||
def tmdb_search(self, title):
|
def tmdb_search(self, title) -> TMDBInfo:
|
||||||
tmdb_info = TMDBInfo()
|
|
||||||
url = self.search_url(title)
|
url = self.search_url(title)
|
||||||
contents = self._request.get_json(url)["results"]
|
contents = self._request.get_json(url).get("results")
|
||||||
if contents.__len__() == 0:
|
if contents.__len__() == 0:
|
||||||
url = self.search_url(title.replace(" ", ""))
|
url = self.search_url(title.replace(" ", ""))
|
||||||
contents = self._request.get_json(url)["results"]
|
contents = self._request.get_json(url).get("results")
|
||||||
# 判断动画
|
# 判断动画
|
||||||
for content in contents:
|
for content in contents:
|
||||||
id = content["id"]
|
id = content["id"]
|
||||||
if self.is_animation(id):
|
if self.is_animation(id):
|
||||||
tmdb_info.id = id
|
|
||||||
break
|
break
|
||||||
url_info = self.info_url(tmdb_info.id)
|
url_info = self.info_url(id)
|
||||||
info_content = self._request.get_json(url_info)
|
info_content = self._request.get_json(url_info)
|
||||||
# 关闭链接
|
# 关闭链接
|
||||||
self._request.close_session()
|
self._request.close_session()
|
||||||
tmdb_info.season = [{"season": s["name"], "air_date": s["air_date"]} for s in info_content["seasons"]]
|
season = [{"season": s.get("name"), "air_date": s.get("air_date")} for s in info_content.get("seasons")]
|
||||||
tmdb_info.last_season = self.get_season(tmdb_info.season)
|
last_season = self.get_season(season)
|
||||||
tmdb_info.title_jp = info_content["original_name"]
|
title_jp = info_content.get("original_name")
|
||||||
tmdb_info.title_zh = info_content["name"]
|
title_zh = info_content.get("name")
|
||||||
return tmdb_info
|
year_number = info_content.get("first_air_date").split("-")[0]
|
||||||
|
return TMDBInfo(id, title_jp, title_zh, season, last_season, year_number)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test = " Love Live!虹咲学园 学园偶像同好会"
|
test = "辉夜大小姐"
|
||||||
print(TMDBMatcher().tmdb_search(test).title_zh)
|
info = TMDBMatcher().tmdb_search(test)
|
||||||
|
print(f"{info.title_zh}({info.year_number})")
|
||||||
@@ -10,27 +10,33 @@ class TitleParser:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._raw_parser = RawParser()
|
self._raw_parser = RawParser()
|
||||||
self._download_parser = DownloadParser()
|
self._download_parser = DownloadParser()
|
||||||
|
self._tmdb_parser = TMDBMatcher()
|
||||||
|
|
||||||
def raw_parser(self, raw):
|
def raw_parser(self, raw: str):
|
||||||
return self._raw_parser.analyse(raw)
|
return self._raw_parser.analyse(raw)
|
||||||
|
|
||||||
def download_parser(self, download_raw, folder_name, season, suffix, method=settings.method):
|
def download_parser(self, download_raw, folder_name, season, suffix, method=settings.method):
|
||||||
return self._download_parser.download_rename(download_raw, folder_name, season, suffix, method)
|
return self._download_parser.download_rename(download_raw, folder_name, season, suffix, method)
|
||||||
|
|
||||||
def return_dict(self, raw):
|
def tmdb_parser(self, title: str, season:int):
|
||||||
tmdb = TMDBMatcher()
|
try:
|
||||||
|
tmdb_info = self._tmdb_parser.tmdb_search(title)
|
||||||
|
logger.debug(f"TMDB Matched, title is {tmdb_info.title_zh}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning("Not Matched with TMDB")
|
||||||
|
return title, season
|
||||||
|
if settings.title_language == "zh":
|
||||||
|
official_title = f"{tmdb_info.title_zh}({tmdb_info.year_number})"
|
||||||
|
elif settings.title_language == "jp":
|
||||||
|
official_title = f"{tmdb_info.title_jp}({tmdb_info.year_number})"
|
||||||
|
season = tmdb_info.last_season
|
||||||
|
return official_title, season
|
||||||
|
|
||||||
|
def return_dict(self, raw: str):
|
||||||
try:
|
try:
|
||||||
episode = self.raw_parser(raw)
|
episode = self.raw_parser(raw)
|
||||||
if settings.enable_tmdb:
|
if settings.enable_tmdb:
|
||||||
try:
|
official_title, season = self.tmdb_parser(episode.title, episode.season_info.number)
|
||||||
tmdb_info = tmdb.tmdb_search(episode.title)
|
|
||||||
official_title = tmdb_info.title_zh if settings.title_language == "zh" else tmdb_info.title_jp
|
|
||||||
season = tmdb_info.last_season
|
|
||||||
except Exception as e:
|
|
||||||
logger.debug(e)
|
|
||||||
logger.info("Not Match in TMDB")
|
|
||||||
official_title = episode.title
|
|
||||||
season = episode.season_info.number
|
|
||||||
else:
|
else:
|
||||||
official_title = episode.title
|
official_title = episode.title
|
||||||
season = episode.season_info.number
|
season = episode.season_info.number
|
||||||
@@ -54,9 +60,10 @@ class TitleParser:
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import re
|
import re
|
||||||
|
from conf.const_dev import DEV_SETTINGS
|
||||||
|
settings.init(DEV_SETTINGS)
|
||||||
T = TitleParser()
|
T = TitleParser()
|
||||||
raw = "[Lilith-Raws] 神渣☆偶像 / Kami Kuzu☆Idol - 01 [Baha][WEB-DL][1080p][AVC AAC][CHT][MP4]"
|
raw = "[SWSUB][7月新番][继母的拖油瓶是我的前女友/継母の连れ子が元カノだった][001][GB_JP][AVC][1080P][网盘][无修正] [331.6MB] [复制磁连]"
|
||||||
season = int(re.search(r"\d{1,2}", "S02").group())
|
season = int(re.search(r"\d{1,2}", "S02").group())
|
||||||
title = T.raw_parser(raw)
|
dict = T.return_dict(raw)
|
||||||
print(season, title.title, title.ep_info.number)
|
print(dict)
|
||||||
print(T.return_dict(raw))
|
|
||||||
|
|||||||
@@ -17,3 +17,4 @@ soupsieve
|
|||||||
typing_extensions==4.3.0
|
typing_extensions==4.3.0
|
||||||
urllib3==1.26.9
|
urllib3==1.26.9
|
||||||
uvicorn
|
uvicorn
|
||||||
|
attrdict
|
||||||
|
|||||||
Reference in New Issue
Block a user