新功能:1.模式3增量整理 2.保存运行及错误日志到目录
This commit is contained in:
@@ -8,8 +8,10 @@ import typing
|
|||||||
import urllib3
|
import urllib3
|
||||||
|
|
||||||
import config
|
import config
|
||||||
|
import datetime
|
||||||
import time
|
import time
|
||||||
from ADC_function import get_html, is_link
|
from pathlib import Path
|
||||||
|
from ADC_function import file_modification_days, get_html, is_link
|
||||||
from number_parser import get_number
|
from number_parser import get_number
|
||||||
from core import core_main
|
from core import core_main
|
||||||
|
|
||||||
@@ -37,13 +39,87 @@ def argparse_function(ver: str) -> typing.Tuple[str, str, bool]:
|
|||||||
parser.add_argument("file", default='', nargs='?', help="Single Movie file path.")
|
parser.add_argument("file", default='', nargs='?', help="Single Movie file path.")
|
||||||
parser.add_argument("-p","--path",default='',nargs='?',help="Analysis folder path.")
|
parser.add_argument("-p","--path",default='',nargs='?',help="Analysis folder path.")
|
||||||
# parser.add_argument("-c", "--config", default='config.ini', nargs='?', help="The config file Path.")
|
# parser.add_argument("-c", "--config", default='config.ini', nargs='?', help="The config file Path.")
|
||||||
|
parser.add_argument("-o","--log-dir",dest='logdir',default='',nargs='?',
|
||||||
|
help="Duplicate from stdout and stderr to logfiles in log directory.")
|
||||||
parser.add_argument("-n", "--number", default='', nargs='?', help="Custom file number")
|
parser.add_argument("-n", "--number", default='', nargs='?', help="Custom file number")
|
||||||
parser.add_argument("-a", "--auto-exit", dest='autoexit', action="store_true",
|
parser.add_argument("-a", "--auto-exit", dest='autoexit', action="store_true",
|
||||||
help="Auto exit after program complete")
|
help="Auto exit after program complete")
|
||||||
parser.add_argument("-v", "--version", action="version", version=ver)
|
parser.add_argument("-v", "--version", action="version", version=ver)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
return args.file, args.path, args.number, args.autoexit
|
return args.file, args.path, args.number, args.autoexit, args.logdir
|
||||||
|
|
||||||
|
|
||||||
|
class OutLogger(object):
|
||||||
|
def __init__(self, logfile) -> None:
|
||||||
|
self.term = sys.stdout
|
||||||
|
self.log = open(logfile,"w",encoding='utf-8')
|
||||||
|
def __del__(self):
|
||||||
|
self.close()
|
||||||
|
def __enter__(self):
|
||||||
|
pass
|
||||||
|
def __exit__(self, *args):
|
||||||
|
self.close()
|
||||||
|
def write(self,msg):
|
||||||
|
self.term.write(msg)
|
||||||
|
self.log.write(msg)
|
||||||
|
def flush(self):
|
||||||
|
self.term.flush()
|
||||||
|
self.log.flush()
|
||||||
|
os.fsync(self.log.fileno())
|
||||||
|
def close(self):
|
||||||
|
if self.term != None:
|
||||||
|
sys.stdout = self.term
|
||||||
|
self.term = None
|
||||||
|
if self.log != None:
|
||||||
|
self.log.close()
|
||||||
|
self.log = None
|
||||||
|
|
||||||
|
|
||||||
|
class ErrLogger(OutLogger):
|
||||||
|
def __init__(self, logfile) -> None:
|
||||||
|
self.term = sys.stderr
|
||||||
|
self.log = open(logfile,"w",encoding='utf-8')
|
||||||
|
def close(self):
|
||||||
|
if self.term != None:
|
||||||
|
sys.stderr = self.term
|
||||||
|
self.term = None
|
||||||
|
if self.log != None:
|
||||||
|
self.log.close()
|
||||||
|
self.log = None
|
||||||
|
|
||||||
|
|
||||||
|
def dupe_stdout_to_logfile(logdir: str):
|
||||||
|
if not isinstance(logdir, str) or len(logdir) == 0:
|
||||||
|
return
|
||||||
|
if not os.path.isdir(logdir):
|
||||||
|
os.mkdir(logdir)
|
||||||
|
if not os.path.isdir(logdir):
|
||||||
|
return
|
||||||
|
|
||||||
|
log_tmstr = datetime.datetime.now().strftime("%Y%m%dT%H%M%S")
|
||||||
|
logfile = os.path.join(logdir, f'avdc_{log_tmstr}.txt')
|
||||||
|
errlog = os.path.join(logdir, f'avdc_{log_tmstr}_err.txt')
|
||||||
|
|
||||||
|
sys.stdout = OutLogger(logfile)
|
||||||
|
sys.stderr = ErrLogger(errlog)
|
||||||
|
|
||||||
|
|
||||||
|
def close_logfile(logdir: str):
|
||||||
|
if not isinstance(logdir, str) or len(logdir) == 0 or not os.path.isdir(logdir):
|
||||||
|
return
|
||||||
|
sys.stdout.close()
|
||||||
|
sys.stderr.close()
|
||||||
|
# 清理空文件
|
||||||
|
for current_dir, subdirs, files in os.walk(logdir, topdown=False):
|
||||||
|
try:
|
||||||
|
for f in files:
|
||||||
|
full_name = os.path.join(current_dir, f)
|
||||||
|
if os.path.getsize(full_name) == 0:
|
||||||
|
os.remove(full_name)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
G_trailerRE = re.compile(r'-trailer\.', re.IGNORECASE)
|
G_trailerRE = re.compile(r'-trailer\.', re.IGNORECASE)
|
||||||
@@ -60,6 +136,10 @@ def movie_lists(root, escape_folder):
|
|||||||
total += movie_lists(f, escape_folder)
|
total += movie_lists(f, escape_folder)
|
||||||
elif os.path.splitext(f)[1].upper() in file_type:
|
elif os.path.splitext(f)[1].upper() in file_type:
|
||||||
absf = os.path.abspath(f)
|
absf = os.path.abspath(f)
|
||||||
|
if conf.main_mode() == 3 and conf.mode3_nfo_skip_days() > 0:
|
||||||
|
nfo = Path(absf).with_suffix('.nfo')
|
||||||
|
if file_modification_days(nfo) <= conf.mode3_nfo_skip_days():
|
||||||
|
continue
|
||||||
if (conf.main_mode() == 3 or not is_link(absf)) and not G_trailerRE.search(f):
|
if (conf.main_mode() == 3 or not is_link(absf)) and not G_trailerRE.search(f):
|
||||||
total.append(absf)
|
total.append(absf)
|
||||||
return total
|
return total
|
||||||
@@ -97,7 +177,7 @@ def create_data_and_move(file_path: str, c: config.Config, debug):
|
|||||||
file_path = os.path.abspath(file_path)
|
file_path = os.path.abspath(file_path)
|
||||||
|
|
||||||
if debug == True:
|
if debug == True:
|
||||||
print("[!]Making Data for [{}], the number is [{}]".format(file_path, n_number))
|
print(f"[!]Making Data for [{file_path}], the number is [{n_number}]")
|
||||||
if n_number:
|
if n_number:
|
||||||
core_main(file_path, n_number, c)
|
core_main(file_path, n_number, c)
|
||||||
else:
|
else:
|
||||||
@@ -105,14 +185,14 @@ def create_data_and_move(file_path: str, c: config.Config, debug):
|
|||||||
print("[*]======================================================")
|
print("[*]======================================================")
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
print("[!]Making Data for [{}], the number is [{}]".format(file_path, n_number))
|
print(f"[!]Making Data for [{file_path}], the number is [{n_number}]")
|
||||||
if n_number:
|
if n_number:
|
||||||
core_main(file_path, n_number, c)
|
core_main(file_path, n_number, c)
|
||||||
else:
|
else:
|
||||||
raise ValueError("number empty")
|
raise ValueError("number empty")
|
||||||
print("[*]======================================================")
|
print("[*]======================================================")
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print("[-] [{}] ERROR:".format(file_path))
|
print(f"[-] [{file_path}] ERROR:")
|
||||||
print('[-]', err)
|
print('[-]', err)
|
||||||
|
|
||||||
# 3.7.2 New: Move or not move to failed folder.
|
# 3.7.2 New: Move or not move to failed folder.
|
||||||
@@ -157,7 +237,9 @@ if __name__ == '__main__':
|
|||||||
version = '4.7.2'
|
version = '4.7.2'
|
||||||
urllib3.disable_warnings() #Ignore http proxy warning
|
urllib3.disable_warnings() #Ignore http proxy warning
|
||||||
# Parse command line args
|
# Parse command line args
|
||||||
single_file_path, folder_path, custom_number, auto_exit = argparse_function(version)
|
single_file_path, folder_path, custom_number, auto_exit, logdir = argparse_function(version)
|
||||||
|
|
||||||
|
dupe_stdout_to_logfile(logdir)
|
||||||
|
|
||||||
print('[*]================== AV Data Capture ===================')
|
print('[*]================== AV Data Capture ===================')
|
||||||
print('[*]' + version.center(54))
|
print('[*]' + version.center(54))
|
||||||
@@ -194,12 +276,24 @@ if __name__ == '__main__':
|
|||||||
count = 0
|
count = 0
|
||||||
count_all = str(len(movie_list))
|
count_all = str(len(movie_list))
|
||||||
print('[+]Find', count_all, 'movies')
|
print('[+]Find', count_all, 'movies')
|
||||||
|
main_mode = conf.main_mode()
|
||||||
|
stop_count = conf.mode3_stop_counter()
|
||||||
|
if stop_count<1:
|
||||||
|
stop_count = 999999
|
||||||
|
elif main_mode == 3:
|
||||||
|
count_all = str(min(len(movie_list), stop_count))
|
||||||
|
print(
|
||||||
|
f'[!]运行模式:**维护模式**,本程序将在处理{count_all}个视频文件后停止,如需后台执行自动退出请结合 -a 参数。'
|
||||||
|
)
|
||||||
|
|
||||||
for movie_path in movie_list: # 遍历电影列表 交给core处理
|
for movie_path in movie_list: # 遍历电影列表 交给core处理
|
||||||
count = count + 1
|
count = count + 1
|
||||||
percentage = str(count / int(count_all) * 100)[:4] + '%'
|
percentage = str(count / int(count_all) * 100)[:4] + '%'
|
||||||
print('[!] - ' + percentage + ' [' + str(count) + '/' + count_all + '] -')
|
print('[!] - ' + percentage + ' [' + str(count) + '/' + count_all + '] -')
|
||||||
create_data_and_move(movie_path, conf, conf.debug())
|
create_data_and_move(movie_path, conf, conf.debug())
|
||||||
|
if main_mode == 3 and count >= stop_count:
|
||||||
|
print("[!]Mode 3 stop counter triggered!")
|
||||||
|
break
|
||||||
|
|
||||||
if conf.del_empty_folder():
|
if conf.del_empty_folder():
|
||||||
rm_empty_folder(conf.success_folder())
|
rm_empty_folder(conf.success_folder())
|
||||||
@@ -214,4 +308,7 @@ if __name__ == '__main__':
|
|||||||
print("[+]All finished!!!")
|
print("[+]All finished!!!")
|
||||||
if not (conf.auto_exit() or auto_exit):
|
if not (conf.auto_exit() or auto_exit):
|
||||||
input("Press enter key exit, you can check the error message before you exit...")
|
input("Press enter key exit, you can check the error message before you exit...")
|
||||||
|
|
||||||
|
close_logfile(logdir)
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|||||||
@@ -74,3 +74,12 @@ water=2
|
|||||||
[extrafanart]
|
[extrafanart]
|
||||||
switch=0
|
switch=0
|
||||||
extrafanart_folder=extrafanart
|
extrafanart_folder=extrafanart
|
||||||
|
|
||||||
|
; 整理模式 ([common] main_mode=3)
|
||||||
|
[main_mode_3]
|
||||||
|
; 整理时跳过最近(默认:30)天新修改过的.NFO,可避免反复整理靠前的文件,0为总是整理全部文件
|
||||||
|
nfo_skip_days=30
|
||||||
|
; 整理文件时达到指定个数即停止,配合google free翻译使用时,避免触发翻译次数上限导致的翻译失败,0为不限制
|
||||||
|
mode3_stop_counter=0
|
||||||
|
; 以上两个参数配合使用,可以用于定时执行的计划任务,例如将数千个视频文件的元数据在几周内分批更新
|
||||||
|
; 程序启动参数'-o 日志目录'则可生成日志,检查几周内日志可找出失败文件手工处理
|
||||||
|
|||||||
17
config.py
17
config.py
@@ -149,6 +149,18 @@ class Config:
|
|||||||
def debug(self) -> bool:
|
def debug(self) -> bool:
|
||||||
return self.conf.getboolean("debug_mode", "switch")
|
return self.conf.getboolean("debug_mode", "switch")
|
||||||
|
|
||||||
|
def mode3_nfo_skip_days(self) -> int:
|
||||||
|
try:
|
||||||
|
return self.conf.getint("main_mode_3", "nfo_skip_days")
|
||||||
|
except:
|
||||||
|
return 30
|
||||||
|
|
||||||
|
def mode3_stop_counter(self) -> int:
|
||||||
|
try:
|
||||||
|
return self.conf.getint("main_mode_3", "mode3_stop_counter")
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _exit(sec: str) -> None:
|
def _exit(sec: str) -> None:
|
||||||
print("[-] Read config error! Please check the {} section in config.ini", sec)
|
print("[-] Read config error! Please check the {} section in config.ini", sec)
|
||||||
@@ -236,6 +248,11 @@ class Config:
|
|||||||
conf.set(sec13, "switch", 1)
|
conf.set(sec13, "switch", 1)
|
||||||
conf.set(sec13, "extrafanart_folder", "extrafanart")
|
conf.set(sec13, "extrafanart_folder", "extrafanart")
|
||||||
|
|
||||||
|
sec14 = "main_mode_3"
|
||||||
|
conf.add_section(sec14)
|
||||||
|
conf.set(sec14, "nfo_skip_days", 30)
|
||||||
|
conf.set(sec14, "mode3_stop_counter", 0)
|
||||||
|
|
||||||
return conf
|
return conf
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user