diff --git a/AVDC_Main.py b/AVDC_Main.py index e08fb7184..b378a0353 100644 --- a/AVDC_Main.py +++ b/AVDC_Main.py @@ -1,16 +1,15 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- import threading +import json +from PyQt5 import QtWidgets from PyQt5.QtGui import QPixmap from PyQt5.QtGui import QTextCursor, QCursor -from PyQt5.QtWidgets import * +from PyQt5.QtWidgets import QMainWindow, QTreeWidgetItem, QApplication from PyQt5.QtCore import pyqtSignal, Qt -from Ui.AVDC import * import sys import time import os.path -from Function.Function import * -from Function.getHtml import * import requests import shutil import base64 @@ -18,6 +17,10 @@ from aip import AipBodyAnalysis from PIL import Image import os +from configparser import ConfigParser +from Ui.AVDC import Ui_AVDV +from Function.Function import save_config, movie_lists, get_info, getDataFromJSON, escapePath, getNumber +from Function.getHtml import get_html class MyMAinWindow(QMainWindow, Ui_AVDV): @@ -30,9 +33,10 @@ def __init__(self, parent=None): self.Init_Ui() self.set_style() # 初始化需要的变量 - self.version = '3.92' + self.version = '3.93' self.m_drag = False self.m_DragPosition = 0 + self.count_claw = 0 # 批量刮削次数 self.item_succ = self.Ui.treeWidget_number.topLevelItem(0) self.item_fail = self.Ui.treeWidget_number.topLevelItem(1) self.json_array = {} @@ -52,19 +56,18 @@ def Init_Ui(self): ico_path = '' if os.path.exists('AVDC-ico.png'): ico_path = 'AVDC-ico.png' - elif os.path.exists('Ui/AVDC-ico.png'): - ico_path = 'Ui/AVDC-ico.png' + elif os.path.exists('Img/AVDC-ico.png'): + ico_path = 'Img/AVDC-ico.png' pix = QPixmap(ico_path) self.Ui.label_ico.setScaledContents(True) self.Ui.label_ico.setPixmap(pix) # 添加图标 self.Ui.progressBar_avdc.setValue(0) # 进度条清0 self.progressBarValue.connect(self.set_processbar) self.Ui.progressBar_avdc.setTextVisible(False) # 不显示进度条文字 - self.setWindowFlag(QtCore.Qt.FramelessWindowHint) # 隐藏边框 + self.setWindowFlag(Qt.FramelessWindowHint) # 隐藏边框 # self.setWindowOpacity(0.9) # 设置窗口透明度 - self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # 设置窗口背景透明 + self.setAttribute(Qt.WA_TranslucentBackground) # 设置窗口背景透明 self.Ui.treeWidget_number.expandAll() - self.Ui.checkBox_cover.setChecked(True) def set_style(self): # 控件美化 @@ -121,7 +124,7 @@ def set_style(self): border-radius:10px; padding:2px 4px; } - QPushButton#pushButton_start_cap,#pushButton_move_mp4,#pushButton_select_file,#pushButton_select_fanart{ + QPushButton#pushButton_start_cap,#pushButton_move_mp4,#pushButton_select_file,#pushButton_select_thumb{ font-size:20px; background:#F0F8FF; border:2px solid white; @@ -137,8 +140,7 @@ def set_style(self): border-radius:20px; padding:2px 4px; } - QPushButton#pushButton_save_config,#pushButton_show_pic_actor{ - font-size:20px; + QPushButton#pushButton_save_config,#pushButton_show_pic_actor,#pushButton_init_config{ background:#F0F8FF; border:2px solid white; width:300px; @@ -165,81 +167,16 @@ def Init(self): self.Ui.pushButton_about.clicked.connect(self.pushButton_about_clicked) self.Ui.pushButton_start_cap.clicked.connect(self.pushButton_start_cap_clicked) self.Ui.pushButton_save_config.clicked.connect(self.pushButton_save_config_clicked) + self.Ui.pushButton_init_config.clicked.connect(self.pushButton_init_config_clicked) self.Ui.pushButton_move_mp4.clicked.connect(self.move_file) self.Ui.pushButton_add_actor_pic.clicked.connect(self.pushButton_add_actor_pic_clicked) self.Ui.pushButton_show_pic_actor.clicked.connect(self.pushButton_show_pic_actor_clicked) - self.Ui.pushButton_select_fanart.clicked.connect(self.pushButton_select_fanart_clicked) + self.Ui.pushButton_select_thumb.clicked.connect(self.pushButton_select_thumb_clicked) self.Ui.pushButton_log.clicked.connect(self.pushButton_show_log_clicked) self.Ui.checkBox_cover.stateChanged.connect(self.cover_change) self.Ui.horizontalSlider_timeout.valueChanged.connect(self.lcdNumber_timeout_change) self.Ui.horizontalSlider_retry.valueChanged.connect(self.lcdNumber_retry_change) - - # ========================================================================加载config - def Load_Config(self): - config_file = 'config.ini' - config = ConfigParser() - config.read(config_file, encoding='UTF-8') - if int(config['common']['main_mode']) == 1: - self.Ui.radioButton_common.setChecked(True) - elif int(config['common']['main_mode']) == 2: - self.Ui.radioButton_sort.setChecked(True) - if int(config['common']['soft_link']) == 1: - self.Ui.radioButton_soft_on.setChecked(True) - elif int(config['common']['soft_link']) == 0: - self.Ui.radioButton_soft_off.setChecked(True) - if int(config['common']['failed_file_move']) == 1: - self.Ui.radioButton_fail_move_on.setChecked(True) - elif int(config['common']['failed_file_move']) == 0: - self.Ui.radioButton_fail_move_off.setChecked(True) - if int(config['update']['update_check']) == 1: - self.Ui.radioButton_update_on.setChecked(True) - elif int(config['update']['update_check']) == 0: - self.Ui.radioButton_update_off.setChecked(True) - if int(config['log']['save_log']) == 1: - self.Ui.radioButton_log_on.setChecked(True) - elif int(config['log']['save_log']) == 0: - self.Ui.radioButton_log_off.setChecked(True) - if int(config['debug_mode']['switch']) == 1: - self.Ui.radioButton_debug_on.setChecked(True) - elif int(config['debug_mode']['switch']) == 0: - self.Ui.radioButton_debug_off.setChecked(True) - if config['media']['media_warehouse'] == 'emby' or config['media']['media_warehouse'] == 'jellyfin': - self.Ui.radioButton_emby.setChecked(True) - elif config['media']['media_warehouse'] == 'plex': - self.Ui.radioButton_plex.setChecked(True) - elif config['media']['media_warehouse'] == 'kodi': - self.Ui.radioButton_kodi.setChecked(True) - if config['common']['website'] == 'all': - self.Ui.comboBox_website_all.setCurrentIndex(0) - elif config['common']['website'] == 'mgstage': - self.Ui.comboBox_website_all.setCurrentIndex(1) - elif config['common']['website'] == 'fc2club': - self.Ui.comboBox_website_all.setCurrentIndex(2) - elif config['common']['website'] == 'javbus': - self.Ui.comboBox_website_all.setCurrentIndex(3) - elif config['common']['website'] == 'javdb': - self.Ui.comboBox_website_all.setCurrentIndex(4) - elif config['common']['website'] == 'avsox': - self.Ui.comboBox_website_all.setCurrentIndex(5) - elif config['common']['website'] == 'dmm': - self.Ui.comboBox_website_all.setCurrentIndex(6) - self.Ui.lineEdit_success.setText(config['common']['success_output_folder']) - self.Ui.lineEdit_fail.setText(config['common']['failed_output_folder']) - self.Ui.lineEdit_escape_dir.setText(config['escape']['folders']) - self.Ui.lineEdit_escape_char.setText(config['escape']['literals']) - self.Ui.lineEdit_escape_dir_move.setText(config['escape']['folders']) - self.Ui.lineEdit_escape_string.setText(config['escape']['string']) - self.Ui.lineEdit_proxy.setText(config['proxy']['proxy']) - self.Ui.horizontalSlider_timeout.setValue(int(config['proxy']['timeout'])) - self.Ui.horizontalSlider_retry.setValue(int(config['proxy']['retry'])) - self.Ui.lineEdit_dir_name.setText(config['Name_Rule']['folder_name']) - self.Ui.lineEdit_media_name.setText(config['Name_Rule']['naming_media']) - self.Ui.lineEdit_local_name.setText(config['Name_Rule']['naming_file']) - self.Ui.lineEdit_emby_url.setText(config['emby']['emby_url']) - self.Ui.lineEdit_api_key.setText(config['emby']['api_key']) - self.Ui.lineEdit_movie_path.setText(str(config['media']['media_path']).replace('\\', '/')) - self.Ui.lineEdit_movie_type.setText(config['media']['media_type']) - self.Ui.lineEdit_sub_type.setText(config['media']['sub_type']) + self.Ui.horizontalSlider_mark_size.valueChanged.connect(self.lcdNumber_mark_size_change) # ========================================================================显示版本号 def show_version(self): @@ -294,10 +231,14 @@ def lcdNumber_retry_change(self): retry = self.Ui.horizontalSlider_retry.value() self.Ui.lcdNumber_retry.display(retry) + def lcdNumber_mark_size_change(self): + mark_size = self.Ui.horizontalSlider_mark_size.value() + self.Ui.lcdNumber_mark_size.display(mark_size) + def cover_change(self): if not self.Ui.checkBox_cover.isChecked(): self.Ui.label_poster.setText("封面图") - self.Ui.label_fanart.setText("缩略图") + self.Ui.label_thumb.setText("缩略图") def treeWidget_number_clicked(self, qmodeLindex): item = self.Ui.treeWidget_number.currentItem() @@ -312,11 +253,164 @@ def pushButton_start_cap_clicked(self): self.Ui.pushButton_start_cap.setEnabled(False) self.progressBarValue.emit(int(0)) try: + self.count_claw += 1 t = threading.Thread(target=self.AVDC_Main) t.start() # 启动线程,即让线程开始执行 except Exception as error_info: self.add_text_main('[-]Error in pushButton_start_cap_clicked: ' + str(error_info)) + # ========================================================================恢复默认config.ini + def pushButton_init_config_clicked(self): + try: + t = threading.Thread(target=self.init_config_clicked) + t.start() # 启动线程,即让线程开始执行 + except Exception as error_info: + self.add_text_main('[-]Error in pushButton_save_config_clicked: ' + str(error_info)) + + def init_config_clicked(self): + json_config = { + 'show_poster': 1, + 'main_mode': 1, + 'soft_link': 0, + 'switch_debug': 1, + 'failed_file_move': 1, + 'update_check': 1, + 'save_log': 1, + 'website': 'all', + 'failed_output_folder': 'failed', + 'success_output_folder': 'JAV_output', + 'proxy': '127.0.0.1:10809', + 'timeout': 7, + 'retry': 3, + 'folder_name': 'actor/number-title-release', + 'naming_media': 'number-title', + 'naming_file': 'number', + 'literals': '\()', + 'folders': 'failed,JAV_output', + 'string': '1080p,720p,22-sht.me,-HD', + 'emby_url': 'localhost:8096', + 'api_key': 'bb2e96d99cbf471ea83065d40b229fc1', + 'media_path': 'E:/TEMP', + 'media_type': '.mp4|.avi|.rmvb|.wmv|.mov|.mkv|.flv|.ts|.webm|.MP4|.AVI|.RMVB|.WMV|.MOV|.MKV|.FLV|.TS|.WEBM', + 'sub_type': '.smi|.srt|.idx|.sub|.sup|.psb|.ssa|.ass|.txt|.usf|.xss|.ssf|.rt|.lrc|.sbv|.vtt|.ttml', + 'poster_mark': 1, + 'thumb_mark': 1, + 'mark_size': 3, + 'mark_type': 'SUB, LEAK, UNCENSORED', + 'mark_pos': 'top_left', + 'uncensored_poster': 0, + 'uncensored_prefix': 'S2M|BT|LAF|SMD', + } + save_config(json_config) + self.Load_Config() + + # ========================================================================加载config + def Load_Config(self): + config_file = 'config.ini' + config = ConfigParser() + config.read(config_file, encoding='UTF-8') + # ========================================================================common + if int(config['common']['main_mode']) == 1: + self.Ui.radioButton_common.setChecked(True) + elif int(config['common']['main_mode']) == 2: + self.Ui.radioButton_sort.setChecked(True) + if int(config['common']['soft_link']) == 1: + self.Ui.radioButton_soft_on.setChecked(True) + elif int(config['common']['soft_link']) == 0: + self.Ui.radioButton_soft_off.setChecked(True) + if int(config['common']['failed_file_move']) == 1: + self.Ui.radioButton_fail_move_on.setChecked(True) + elif int(config['common']['failed_file_move']) == 0: + self.Ui.radioButton_fail_move_off.setChecked(True) + if int(config['common']['show_poster']) == 1: + self.Ui.checkBox_cover.setChecked(True) + elif int(config['common']['show_poster']) == 0: + self.Ui.checkBox_cover.setChecked(False) + if config['common']['website'] == 'all': + self.Ui.comboBox_website_all.setCurrentIndex(0) + elif config['common']['website'] == 'mgstage': + self.Ui.comboBox_website_all.setCurrentIndex(1) + elif config['common']['website'] == 'fc2club': + self.Ui.comboBox_website_all.setCurrentIndex(2) + elif config['common']['website'] == 'javbus': + self.Ui.comboBox_website_all.setCurrentIndex(3) + elif config['common']['website'] == 'jav321': + self.Ui.comboBox_website_all.setCurrentIndex(4) + elif config['common']['website'] == 'javdb': + self.Ui.comboBox_website_all.setCurrentIndex(5) + elif config['common']['website'] == 'avsox': + self.Ui.comboBox_website_all.setCurrentIndex(6) + elif config['common']['website'] == 'dmm': + self.Ui.comboBox_website_all.setCurrentIndex(7) + self.Ui.lineEdit_success.setText(config['common']['success_output_folder']) + self.Ui.lineEdit_fail.setText(config['common']['failed_output_folder']) + # ========================================================================proxy + self.Ui.lineEdit_proxy.setText(config['proxy']['proxy']) + self.Ui.horizontalSlider_timeout.setValue(int(config['proxy']['timeout'])) + self.Ui.horizontalSlider_retry.setValue(int(config['proxy']['retry'])) + # ========================================================================Name_Rule + self.Ui.lineEdit_dir_name.setText(config['Name_Rule']['folder_name']) + self.Ui.lineEdit_media_name.setText(config['Name_Rule']['naming_media']) + self.Ui.lineEdit_local_name.setText(config['Name_Rule']['naming_file']) + # ========================================================================update + if int(config['update']['update_check']) == 1: + self.Ui.radioButton_update_on.setChecked(True) + elif int(config['update']['update_check']) == 0: + self.Ui.radioButton_update_off.setChecked(True) + # ========================================================================log + if int(config['log']['save_log']) == 1: + self.Ui.radioButton_log_on.setChecked(True) + elif int(config['log']['save_log']) == 0: + self.Ui.radioButton_log_off.setChecked(True) + # ========================================================================media + self.Ui.lineEdit_movie_type.setText(config['media']['media_type']) + self.Ui.lineEdit_sub_type.setText(config['media']['sub_type']) + self.Ui.lineEdit_movie_path.setText(str(config['media']['media_path']).replace('\\', '/')) + # ========================================================================escape + self.Ui.lineEdit_escape_dir.setText(config['escape']['folders']) + self.Ui.lineEdit_escape_char.setText(config['escape']['literals']) + self.Ui.lineEdit_escape_dir_move.setText(config['escape']['folders']) + self.Ui.lineEdit_escape_string.setText(config['escape']['string']) + # ========================================================================debug_mode + if int(config['debug_mode']['switch']) == 1: + self.Ui.radioButton_debug_on.setChecked(True) + elif int(config['debug_mode']['switch']) == 0: + self.Ui.radioButton_debug_off.setChecked(True) + # ========================================================================emby + self.Ui.lineEdit_emby_url.setText(config['emby']['emby_url']) + self.Ui.lineEdit_api_key.setText(config['emby']['api_key']) + # ========================================================================mark + if int(config['mark']['poster_mark']) == 1: + self.Ui.radioButton_poster_mark_on.setChecked(True) + elif int(config['mark']['poster_mark']) == 0: + self.Ui.radioButton_poster_mark_off.setChecked(True) + if int(config['mark']['thumb_mark']) == 1: + self.Ui.radioButton_thumb_mark_on.setChecked(True) + elif int(config['mark']['thumb_mark']) == 0: + self.Ui.radioButton_thumb_mark_off.setChecked(True) + self.Ui.horizontalSlider_mark_size.setValue(int(config['mark']['mark_size'])) + if 'SUB' in config['mark']['mark_type']: + self.Ui.checkBox_sub.setChecked(True) + if 'LEAK' in config['mark']['mark_type']: + self.Ui.checkBox_leak.setChecked(True) + if 'UNCENSORED' in config['mark']['mark_type']: + self.Ui.checkBox_uncensored.setChecked(True) + if 'top_left' == config['mark']['mark_pos']: + self.Ui.radioButton_top_left.setChecked(True) + elif 'bottom_left' == config['mark']['mark_pos']: + self.Ui.radioButton_bottom_left.setChecked(True) + elif 'top_right' == config['mark']['mark_pos']: + self.Ui.radioButton_top_right.setChecked(True) + elif 'bottom_right' == config['mark']['mark_pos']: + self.Ui.radioButton_bottom_right.setChecked(True) + # ========================================================================uncensored + if int(config['uncensored']['uncensored_poster']) == 1: + self.Ui.radioButton_poster_cut.setChecked(True) + elif int(config['uncensored']['uncensored_poster']) == 0: + self.Ui.radioButton_poster_official.setChecked(True) + self.Ui.lineEdit_uncensored_prefix.setText(config['uncensored']['uncensored_prefix']) + + # ========================================================================读取设置页设置,保存在config.ini def pushButton_save_config_clicked(self): try: t = threading.Thread(target=self.save_config_clicked) @@ -324,16 +418,21 @@ def pushButton_save_config_clicked(self): except Exception as error_info: self.add_text_main('[-]Error in pushButton_save_config_clicked: ' + str(error_info)) - # ========================================================================读取设置页设置,保存在config.ini def save_config_clicked(self): main_mode = 1 failed_file_move = 1 soft_link = 0 + show_poster = 0 switch_debug = 0 update_check = 0 save_log = 0 - media_warehouse = '' website = '' + add_mark = 1 + mark_size = 3 + mark_type = '' + mark_pos = '' + uncensored_poster = 0 + # ========================================================================common if self.Ui.radioButton_common.isChecked(): # 普通模式 main_mode = 1 elif self.Ui.radioButton_sort.isChecked(): # 整理模式 @@ -342,10 +441,6 @@ def save_config_clicked(self): soft_link = 1 elif self.Ui.radioButton_soft_off.isChecked(): # 软链接关 soft_link = 0 - if self.Ui.radioButton_fail_move_on.isChecked(): # 失败移动开 - failed_file_move = 1 - elif self.Ui.radioButton_fail_move_off.isChecked(): # 失败移动关 - failed_file_move = 0 if self.Ui.radioButton_debug_on.isChecked(): # 调试模式开 switch_debug = 1 elif self.Ui.radioButton_debug_off.isChecked(): # 调试模式关 @@ -358,12 +453,10 @@ def save_config_clicked(self): save_log = 1 elif self.Ui.radioButton_log_off.isChecked(): # 关闭日志 save_log = 0 - if self.Ui.radioButton_emby.isChecked(): # emby/jellyfin - media_warehouse = 'emby' - elif self.Ui.radioButton_plex.isChecked(): # plex - media_warehouse = 'plex' - elif self.Ui.radioButton_kodi.isChecked(): # kodi - media_warehouse = 'kodi' + if self.Ui.radioButton_fail_move_on.isChecked(): # 失败移动开 + failed_file_move = 1 + elif self.Ui.radioButton_fail_move_off.isChecked(): # 失败移动关 + failed_file_move = 0 if self.Ui.comboBox_website_all.currentText() == 'All websites': # all website = 'all' elif self.Ui.comboBox_website_all.currentText() == 'mgstage': # mgstage @@ -372,20 +465,53 @@ def save_config_clicked(self): website = 'fc2club' elif self.Ui.comboBox_website_all.currentText() == 'javbus': # javbus website = 'javbus' + elif self.Ui.comboBox_website_all.currentText() == 'jav321': # jav321 + website = 'jav321' elif self.Ui.comboBox_website_all.currentText() == 'javdb': # javdb website = 'javdb' elif self.Ui.comboBox_website_all.currentText() == 'avsox': # avsox website = 'avsox' elif self.Ui.comboBox_website_all.currentText() == 'dmm': # dmm website = 'dmm' + if self.Ui.checkBox_cover.isChecked(): # 显示封面 + show_poster = 1 + else: # 关闭封面 + show_poster = 0 + # ========================================================================水印 + if self.Ui.radioButton_poster_mark_on.isChecked(): # 封面添加水印 + poster_mark = 1 + else: # 关闭封面添加水印 + poster_mark = 0 + if self.Ui.radioButton_thumb_mark_on.isChecked(): # 缩略图添加水印 + thumb_mark = 1 + else: # 关闭缩略图添加水印 + thumb_mark = 0 + if self.Ui.checkBox_sub.isChecked(): # 字幕 + mark_type += ',SUB' + if self.Ui.checkBox_leak.isChecked(): # 流出 + mark_type += ',LEAK' + if self.Ui.checkBox_uncensored.isChecked(): # 无码 + mark_type += ',UNCENSORED' + if self.Ui.radioButton_top_left.isChecked(): # 左上 + mark_pos = 'top_left' + elif self.Ui.radioButton_bottom_left.isChecked(): # 左下 + mark_pos = 'bottom_left' + elif self.Ui.radioButton_top_right.isChecked(): # 右上 + mark_pos = 'top_right' + elif self.Ui.radioButton_bottom_right.isChecked(): # 右下 + mark_pos = 'bottom_right' + if self.Ui.radioButton_poster_official.isChecked(): # 官方 + uncensored_poster = 0 + elif self.Ui.radioButton_poster_cut.isChecked(): # 裁剪 + uncensored_poster = 1 json_config = { + 'show_poster': show_poster, 'main_mode': main_mode, 'soft_link': soft_link, 'switch_debug': switch_debug, 'failed_file_move': failed_file_move, 'update_check': update_check, 'save_log': save_log, - 'media_warehouse': media_warehouse, 'website': website, 'failed_output_folder': self.Ui.lineEdit_fail.text(), 'success_output_folder': self.Ui.lineEdit_success.text(), @@ -403,6 +529,13 @@ def save_config_clicked(self): 'media_path': self.Ui.lineEdit_movie_path.text(), 'media_type': self.Ui.lineEdit_movie_type.text(), 'sub_type': self.Ui.lineEdit_sub_type.text(), + 'poster_mark': poster_mark, + 'thumb_mark': thumb_mark, + 'mark_size': self.Ui.horizontalSlider_mark_size.value(), + 'mark_type': mark_type.strip(','), + 'mark_pos': mark_pos, + 'uncensored_poster': uncensored_poster, + 'uncensored_prefix': self.Ui.lineEdit_uncensored_prefix.text(), } save_config(json_config) @@ -446,36 +579,31 @@ def select_file_thread(self, file_name): self.add_text_main("[*]======================================================") # ========================================================================小工具-裁剪封面图 - def pushButton_select_fanart_clicked(self): + def pushButton_select_thumb_clicked(self): path = self.Ui.lineEdit_movie_path.text() filePath, fileType = QtWidgets.QFileDialog.getOpenFileName(self, "选取缩略图", path, "Picture Files(*.jpg);;All Files(*)") if filePath != '': self.Ui.stackedWidget.setCurrentIndex(0) try: - t = threading.Thread(target=self.select_fanart_thread, args=(filePath,)) + t = threading.Thread(target=self.select_thumb_thread, args=(filePath,)) t.start() # 启动线程,即让线程开始执行 except Exception as error_info: - self.add_text_main('[-]Error in pushButton_select_fanart_clicked: ' + str(error_info)) + self.add_text_main('[-]Error in pushButton_select_thumb_clicked: ' + str(error_info)) - def select_fanart_thread(self, file_path): + def select_thumb_thread(self, file_path): file_name = file_path.split('/')[-1] file_path = file_path.replace('/' + file_name, '') - self.image_cut(file_path, file_name) + self.image_cut(file_path, file_name, 2) self.add_text_main("[*]======================================================") - def image_cut(self, path, file_name): + def image_cut(self, path, file_name, mode=1): + png_name = file_name.replace('-thumb.jpg', '-poster.jpg') file_path = os.path.join(path, file_name) - png_name = '' - if self.Ui.radioButton_emby.isChecked(): # emby/jellyfin - png_name = os.path.splitext(file_name)[0] + '.png' - elif self.Ui.radioButton_plex.isChecked(): # plex - png_name = 'poster.jpg' - elif self.Ui.radioButton_kodi.isChecked(): # kodi - png_name = file_name.replace('-fanart.jpg', '-poster.jpg') + png_path = os.path.join(path, png_name) try: - if os.path.exists(os.path.join(path, png_name)): - os.remove(os.path.join(path, png_name)) + if os.path.exists(png_path): + os.remove(png_path) except Exception as error_info: self.add_text_main('[-]Error in image_cut: ' + str(error_info)) return @@ -494,30 +622,43 @@ def image_cut(self, path, file_name): """ 读取图片 """ with open(file_path, 'rb') as fp: image = fp.read() - - """ 调用人体检测与属性识别 """ - result = client.bodyAnalysis(image) - ewidth = int(0.661538 * height) - ex = int(result["person_info"][0]['body_parts']['nose']['x']) - if width - ex < ewidth / 2: - ex = width - ewidth - else: - ex -= int(ewidth / 2) - ey = 0 - ew = ewidth - eh = height + ex, ey, ew, eh = 0, 0, 0, 0 + """ 获取裁剪区域 """ + if height / width <= 1.5: # 长宽比大于1.5,太宽 + """ 调用人体检测与属性识别 """ + result = client.bodyAnalysis(image) + ewidth = int(height / 1.5) + ex = int(result["person_info"][0]['body_parts']['nose']['x']) + if width - ex < ewidth / 2: + ex = width - ewidth + else: + ex -= int(ewidth / 2) + if ex < 0: + ex = 0 + ey = 0 + eh = height + if ewidth > width: + ew = width + else: + ew = ewidth + elif height / width > 1.5: # 长宽比小于1.5,太窄 + ex = 0 + ey = 0 + ew = int(width) + eh = ew * 1.5 fp = open(file_path, 'rb') img = Image.open(fp) img_new_png = img.crop((ex, ey, ew + ex, eh + ey)) fp.close() - img_new_png.save(path + '/' + png_name) + img_new_png.save(png_path) self.add_text_main('[+]Poster Cut ' + png_name + ' from ' + file_name + '!') - pix = QPixmap(file_path) - self.Ui.label_fanart.setScaledContents(True) - self.Ui.label_fanart.setPixmap(pix) # 添加图标 - pix = QPixmap(path + '/' + png_name) - self.Ui.label_poster.setScaledContents(True) - self.Ui.label_poster.setPixmap(pix) # 添加图标 + if mode == 2: + pix = QPixmap(file_path) + self.Ui.label_thumb.setScaledContents(True) + self.Ui.label_thumb.setPixmap(pix) # 添加图标 + pix = QPixmap(png_path) + self.Ui.label_poster.setScaledContents(True) + self.Ui.label_poster.setPixmap(pix) # 添加图标 # ========================================================================小工具-视频移动 def move_file(self): @@ -715,7 +856,7 @@ def upload_profile_picture(self, count, actor, pic_path): # 上传头像 header = {"Content-Type": 'image/png', } else: header = {"Content-Type": 'image/jpeg', } - respones = requests.post(url=url, data=b6_pic, headers=header) + requests.post(url=url, data=b6_pic, headers=header) self.add_text_main( '[+]' + "%4s" % str(count) + '.Success upload profile picture for ' + actor['Name'] + '!') except Exception as error_info: @@ -766,93 +907,73 @@ def DownloadFileWithFilename(self, url, filename, path, Config, filepath, failed proxy = Config['proxy']['proxy'] timeout = int(Config['proxy']['timeout']) retry_count = int(Config['proxy']['retry']) - except: - self.add_text_main('[-]Proxy config error! Please check the config.') + except Exception as error_info: + print('[-]Error in DownloadFileWithFilename! ' + str(error_info)) + self.add_text_main('[-]Error in DownloadFileWithFilename! Proxy config error! Please check the config.') i = 0 while i < retry_count: try: + if not os.path.exists(path): + os.makedirs(path) + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'} if not proxy == '': - if not os.path.exists(path): - os.makedirs(path) - headers = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'} r = requests.get(url, headers=headers, timeout=timeout, proxies={"http": "http://" + str(proxy), "https": "https://" + str(proxy)}) - if r == '': - self.add_text_main('[-]Movie Data not found!') - # os._exit(0) - with open(str(path) + "/" + filename, "wb") as code: - code.write(r.content) - code.close() - return else: - if not os.path.exists(path): - os.makedirs(path) - headers = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'} r = requests.get(url, timeout=timeout, headers=headers) - if r == '': - self.add_text_main('[-]Movie Data not found!') - # os._exit(0) - with open(str(path) + "/" + filename, "wb") as code: - code.write(r.content) - code.close() - return - except : + with open(str(path) + "/" + filename, "wb") as code: + code.write(r.content) + code.close() + return + except Exception as error_info: i += 1 + print('[-]Error in DownloadFileWithFilename! ' + str(error_info)) print('[-]Image Download : Connect retry ' + str(i) + '/' + str(retry_count)) self.add_text_main('[-]Connect Failed! Please check your Proxy or Network!') self.moveFailedFolder(filepath, failed_folder) # ========================================================================下载缩略图 - def fanartDownload(self, option, json_data, path, naming_rule, Config, filepath, failed_folder): - fanart_name = '' - if option == 'emby': - fanart_name = naming_rule + '.jpg' - elif option == 'plex': - fanart_name = 'fanart.jpg' - elif option == 'kodi': - fanart_name = naming_rule + '-fanart.jpg' - if os.path.exists(path + '/' + fanart_name): - self.add_text_main('[+]Fanart Existed! ' + fanart_name) + def thumbDownload(self, json_data, path, naming_rule, Config, filepath, failed_folder): + thumb_name = naming_rule + '-thumb.jpg' + if os.path.exists(path + '/' + thumb_name): + self.add_text_main('[+]Thumb Existed! ' + thumb_name) return i = 1 while i <= int(Config['proxy']['retry']): - self.DownloadFileWithFilename(json_data['cover'], fanart_name, path, Config, filepath, + self.DownloadFileWithFilename(json_data['cover'], thumb_name, path, Config, filepath, failed_folder) - if os.path.getsize(path + '/' + fanart_name) < 10240: + if os.path.getsize(path + '/' + thumb_name) < 10240: print('[!]Image Download Failed! Trying again. ' + str(i) + '/' + Config['proxy']['retry']) i = i + 1 else: break - if os.path.getsize(path + '/' + fanart_name) >= 10240: - self.add_text_main('[+]Fanart Downloaded! ' + fanart_name) + if os.path.getsize(path + '/' + thumb_name) >= 10240: + self.add_text_main('[+]Thumb Downloaded! ' + thumb_name) else: - os.remove(path + '/' + fanart_name) - raise Exception("The Size of Fanart is Error! Deleted " + fanart_name + '!') + os.remove(path + '/' + thumb_name) + raise Exception("The Size of Thumb is Error! Deleted " + thumb_name + '!') # ========================================================================无码片下载封面图 - def smallCoverDownload(self, path, naming_rule, json_data, option, Config, filepath, failed_folder): + def smallCoverDownload(self, path, naming_rule, json_data, Config, filepath, failed_folder): if json_data['imagecut'] == 3: - poster_name = '' - if option == 'emby': - poster_name = naming_rule + '.png' - elif option == 'kodi': - poster_name = naming_rule + '-poster.jpg' - elif option == 'plex': - poster_name = 'poster.jpg' + is_pic_open = 0 + poster_name = naming_rule + '-poster.jpg' if os.path.exists(path + '/' + poster_name): self.add_text_main('[+]Poster Existed! ' + poster_name) return self.DownloadFileWithFilename(json_data['cover_small'], 'cover_small.jpg', path, Config, filepath, failed_folder) try: + if os.path.getsize(path + '/cover_small.jpg') < 10240: + raise Exception("The Size of smallcover is Error! Deleted cover_small.jpg!") fp = open(path + '/cover_small.jpg', 'rb') + is_pic_open = 1 img = Image.open(fp) w = img.width h = img.height - if not (1.45 <= h/w <= 1.55): - self.add_text_main('[-]The size of cover_small.jpg is wrong, Try to cut fanart!') + if not (1.4 <= h/w <= 1.6): + self.add_text_main('[-]The size of cover_small.jpg is unfit, Try to cut thumb!') fp.close() os.remove(path + '/cover_small.jpg') return 'small_cover_error' @@ -862,13 +983,14 @@ def smallCoverDownload(self, path, naming_rule, json_data, option, Config, filep os.remove(path + '/cover_small.jpg') except Exception as error_info: self.add_text_main('[-]Error in smallCoverDownload: ' + str(error_info)) - fp.close() + if is_pic_open: + fp.close() os.remove(path + '/cover_small.jpg') - self.add_text_main('[+]Try to cut fanart!') + self.add_text_main('[+]Try to cut thumb!') return 'small_cover_error' # ========================================================================打印NFO - def PrintFiles(self, option, path, name_file, cn_sub, json_data, filepath, failed_folder): + def PrintFiles(self, path, name_file, cn_sub, leak, json_data, filepath, failed_folder): title, studio, publisher, year, outline, runtime, director, actor_photo, actor, release, tag, number, cover, website, series = get_info( json_data) name_media = json_data['naming_media'].replace('title', title).replace('studio', studio).replace('year', @@ -886,11 +1008,16 @@ def PrintFiles(self, option, path, name_file, cn_sub, json_data, filepath, faile with open(path + "/" + name_file + ".nfo", "wt", encoding='UTF-8') as code: print('', file=code) print("", file=code) - print(" " + name_media + "", file=code) + print(" " + name_media + "", file=code) print(" ", file=code) print(" ", file=code) + try: + if str(json_data['score']) != 'unknown' and str(json_data['score']) != '' and float(json_data['score']) != 0.0: + print(" " + str(json_data['score']) + "", file=code) + except Exception as err: + print("Error in json_data score!" + str(err)) if studio != 'unknown': - print(" " + studio + "+", file=code) + print(" " + studio + "", file=code) if str(year) != 'unknown': print(" " + year + "", file=code) if outline != 'unknown': @@ -900,20 +1027,12 @@ def PrintFiles(self, option, path, name_file, cn_sub, json_data, filepath, faile print(" " + str(runtime).replace(" ", "") + "", file=code) if director != 'unknown': print(" " + director + "", file=code) - if option == 'emby': - print(" " + name_file + ".png", file=code) - print(" " + name_file + ".png", file=code) - print(" " + name_file + '.jpg' + "", file=code) - elif option == 'kodi': - print(" " + name_file + "-poster.jpg", file=code) - print(" " + name_file + '-fanart.jpg' + "", file=code) - elif option == 'plex': - print(" poster.jpg", file=code) - print(" thumb.png", file=code) - print(" fanart.jpg", file=code) + print(" " + name_file + "-poster.jpg", file=code) + print(" " + name_file + "-thumb.jpg", file=code) + print(" " + name_file + '-fanart.jpg' + "", file=code) try: for key, value in actor_photo.items(): - if str(key) != 'unknown': + if str(key) != 'unknown' and str(key) != '': print(" ", file=code) print(" " + key + "", file=code) if not value == '': # or actor_photo == []: @@ -933,67 +1052,60 @@ def PrintFiles(self, option, path, name_file, cn_sub, json_data, filepath, faile print(" " + i + "", file=code) except Exception as error_info: self.add_text_main('[-]Error in tag: ' + str(error_info)) - if re.match('^\d{4,}', number) or re.match('n\d{4}', number) or 'HEYZO' in number.upper(): + if json_data['imagecut'] == 3: print(" 無碼", file=code) + if leak == 1: + print(" 流出", file=code) + if cn_sub == 1: + print(" 中文字幕", file=code) if series != 'unknown': print(" " + '系列:' + series + "", file=code) if studio != 'unknown': print(" " + '製作:' + studio + "", file=code) if publisher != 'unknown': print(" " + '發行:' + publisher + "", file=code) - if cn_sub == 1: - print(" 中文字幕", file=code) try: for i in tag: if i != 'unknown': print(" " + i + "", file=code) except Exception as error_info: self.add_text_main('[-]Error in genre: ' + str(error_info)) - if re.match('^\d{4,}', number) or re.match('n\d{4}', number) or 'HEYZO' in number.upper(): + if json_data['imagecut'] == 3: print(" 無碼", file=code) + if leak == 1: + print(" 流出", file=code) + if cn_sub == 1: + print(" 中文字幕", file=code) if series != 'unknown': print(" " + '系列:' + series + "", file=code) if studio != 'unknown': print(" " + '製作:' + studio + "", file=code) if publisher != 'unknown': print(" " + '發行:' + publisher + "", file=code) - if cn_sub == 1: - print(" 中文字幕", file=code) print(" " + number + "", file=code) if release != 'unknown': - if option == 'emby': - print(" " + release + "", file=code) - elif option == 'kodi' or option == 'plex': - print(" " + release + "", file=code) + print(" " + release + "", file=code) + print(" " + release + "", file=code) print(" " + cover + "", file=code) print(" " + website + "", file=code) print("", file=code) - self.add_text_main("[+]Nfo Writed! " + name_file + ".nfo") + self.add_text_main("[+]Nfo Wrote! " + name_file + ".nfo") except Exception as error_info: self.add_text_main("[-]Write Failed!") self.add_text_main('[-]Error in PrintFiles: ' + str(error_info)) self.moveFailedFolder(filepath, failed_folder) # ========================================================================有码片裁剪封面 - def cutImage(self, option, imagecut, path, naming_rule): + def cutImage(self, imagecut, path, naming_rule): if imagecut != 3: - poster_name = '' - fanart_name = '' - if option == 'emby': - poster_name = naming_rule + '.png' - fanart_name = naming_rule + '.jpg' - elif option == 'kodi': - poster_name = naming_rule + '-poster.jpg' - fanart_name = naming_rule + '-fanart.jpg' - elif option == 'plex': - poster_name = 'poster.jpg' - fanart_name = 'fanart.jpg' + thumb_name = naming_rule + '-thumb.jpg' + poster_name = naming_rule + '-poster.jpg' if os.path.exists(path + '/' + poster_name): self.add_text_main('[+]Poster Existed! ' + poster_name) return if imagecut == 1: try: - img = Image.open(path + '/' + fanart_name) + img = Image.open(path + '/' + thumb_name) w = img.width h = img.height img2 = img.crop((w / 1.9, 0, w, h)) @@ -1002,18 +1114,74 @@ def cutImage(self, option, imagecut, path, naming_rule): except: self.add_text_main('[-]Cover cut failed!') elif imagecut == 0: - self.image_cut(path, fanart_name) - - # ========================================================================jpg复制为Backdrop - def copyRenameJpgToBackdrop(self, option, path, naming_rule): - if not os.path.exists(path + '/Backdrop.jpg'): - if option == 'plex': - shutil.copy(path + '/fanart.jpg', path + '/Backdrop.jpg') - shutil.copy(path + '/poster.jpg', path + '/thumb.png') - if option == 'emby': - shutil.copy(path + '/' + naming_rule + '.jpg', path + '/Backdrop.jpg') - if option == 'kodi': - shutil.copy(path + '/' + naming_rule + '-fanart.jpg', path + '/Backdrop.jpg') + self.image_cut(path, thumb_name) + + # ========================================================================加水印 + def add_mark(self, poster_path, thumb_path, cn_sub, leak, uncensored, config): + mark_type = '' + if cn_sub: + mark_type += ',字幕' + if leak: + mark_type += ',流出' + if uncensored: + mark_type += ',无码' + if self.Ui.radioButton_thumb_mark_on.isChecked() and mark_type != '': + self.add_mark_thread(thumb_path, cn_sub, leak, uncensored) + self.add_text_main('[+]Thumb Add Mark: ' + mark_type.strip(',')) + if self.Ui.radioButton_poster_mark_on.isChecked() and mark_type != '': + self.add_mark_thread(poster_path, cn_sub, leak, uncensored) + self.add_text_main('[+]Poster Add Mark: ' + mark_type.strip(',')) + + def add_mark_thread(self, pic_path, cn_sub, leak, uncensored): + size = 14 - int(self.Ui.horizontalSlider_mark_size.value()) # 获取自定义大小的值 + img_pic = Image.open(pic_path) + count = 0 # 获取自定义位置,取余配合pos达到顺时针添加的效果 + if self.Ui.radioButton_top_left.isChecked(): + count = 0 + elif self.Ui.radioButton_top_right.isChecked(): + count = 1 + elif self.Ui.radioButton_bottom_right.isChecked(): + count = 2 + elif self.Ui.radioButton_bottom_left.isChecked(): + count = 3 + if self.Ui.checkBox_sub.isChecked() and cn_sub == 1: + self.add_to_pic(pic_path, img_pic, size, count, 1) # 添加 + count = (count + 1) % 4 + if self.Ui.checkBox_leak.isChecked() and leak == 1: + self.add_to_pic(pic_path, img_pic, size, count, 2) + count = (count + 1) % 4 + if self.Ui.checkBox_uncensored.isChecked() and uncensored == 1: + self.add_to_pic(pic_path, img_pic, size, count, 3) + img_pic.close() + + + def add_to_pic(self, pic_path, img_pic, size, count, mode): + mark_pic_path = '' + if mode == 1: + mark_pic_path = 'Img/SUB.png' + elif mode == 2: + mark_pic_path = 'Img/LEAK.png' + elif mode == 3: + mark_pic_path = 'Img/UNCENSORED.png' + img_subt = Image.open(mark_pic_path) + scroll_high = int(img_pic.height / size) + scroll_wide = int(scroll_high * img_subt.width / img_subt.height) + img_subt = img_subt.resize((scroll_wide, scroll_high), Image.ANTIALIAS) + r, g, b, a = img_subt.split() # 获取颜色通道,保持png的透明性 + # 封面四个角的位置 + pos = [ + {'x': 0, 'y': 0}, + {'x': img_pic.width - scroll_wide, 'y': 0}, + {'x': img_pic.width - scroll_wide, 'y': img_pic.height - scroll_high}, + {'x': 0, 'y': img_pic.height - scroll_high}, + ] + img_pic.paste(img_subt, (pos[count]['x'], pos[count]['y']), mask=a) + img_pic.save(pic_path, quality=95) + + # ========================================================================thumb复制为fanart + def copyRenameJpgToFanart(self, path, naming_rule): + if not os.path.exists(path + '/' + naming_rule + '-fanart.jpg'): + shutil.copy(path + '/' + naming_rule + '-thumb.jpg', path + '/' + naming_rule + '-fanart.jpg') # ========================================================================移动文件、字幕 def pasteFileToFolder(self, filepath, path, naming_rule, failed_folder): @@ -1034,7 +1202,7 @@ def pasteFileToFolder(self, filepath, path, naming_rule, failed_folder): if os.path.exists(path_old + '/' + filename + sub): # 字幕移动 shutil.move(path_old + '/' + filename + sub, path + '/' + naming_rule + sub) self.add_text_main('[+]Sub moved! ' + naming_rule + sub) - break + return True except FileExistsError: self.add_text_main('[+]Movie Existed! ' + naming_rule + type) if os.path.split(filepath)[0] != path: @@ -1043,6 +1211,7 @@ def pasteFileToFolder(self, filepath, path, naming_rule, failed_folder): self.add_text_main('[-]PermissionError! Please run as Administrator!') except Exception as error_info: self.add_text_main('[-]Error in pasteFileToFolder: ' + str(error_info)) + return False # ========================================================================获取分集序号 def get_part(self, filepath, failed_folder): @@ -1087,12 +1256,12 @@ def creatFolder(self, success_folder, json_data, config): runtime).replace( 'director', director).replace('actor', actor).replace('release', release).replace('number', number).replace( 'series', series).replace('publisher', publisher) # 生成文件夹名 - path = path.replace('//', '/').replace('--', '-').strip('-') + path = path.replace('--', '-').strip('-') if len(path) > 100: # 文件夹名过长 取标题前70个字符 self.add_text_main('[-]Error in Length of Path! Cut title!') path = path.replace(title, title[0:70]) path = success_folder + '/' + path - path = path.replace('//', '/').replace('--', '-').strip('-') + path = path.replace('--', '-').strip('-') if not os.path.exists(path): path = escapePath(path, config) os.makedirs(path) @@ -1100,77 +1269,114 @@ def creatFolder(self, success_folder, json_data, config): # ========================================================================从指定网站获取json_data def get_json_data(self, mode, number, config): - if mode == 5: # javdb模式 + if mode == 6: # javdb模式 self.add_text_main('[!]Please Wait Three Seconds!') time.sleep(3) - json_data = getDataFromJSON(number, config, 5) - else: - json_data = getDataFromJSON(number, config, mode) + json_data = getDataFromJSON(number, config, mode) return json_data # ========================================================================json_data添加到主界面 def add_label_info(self, json_data): + try: + t = threading.Thread(target=self.add_label_info_Thread, args=(json_data,)) + t.start() # 启动线程,即让线程开始执行 + except Exception as error_info: + self.add_text_main('[-]Error in pushButton_start_cap_clicked: ' + str(error_info)) + + def add_label_info_Thread(self, json_data): self.Ui.label_number.setText(json_data['number']) self.Ui.label_release.setText(json_data['release']) self.Ui.label_director.setText(json_data['director']) - self.Ui.label_publish.setText(json_data['publisher']) - self.Ui.label_studio.setText(json_data['studio']) self.Ui.label_label.setText(json_data['series']) + self.Ui.label_studio.setText(json_data['studio']) + self.Ui.label_publish.setText(json_data['publisher']) self.Ui.label_title.setText(json_data['title']) self.Ui.label_actor.setText(json_data['actor']) self.Ui.label_outline.setText(json_data['outline']) self.Ui.label_tag.setText(str(json_data['tag']).strip(" [',']").replace('\'', '')) if self.Ui.checkBox_cover.isChecked(): - fanart_path = json_data['fanart_path'] poster_path = json_data['poster_path'] - if os.path.exists(fanart_path): - pix = QPixmap(fanart_path) - self.Ui.label_fanart.setScaledContents(True) - self.Ui.label_fanart.setPixmap(pix) # 添加缩略图 + thumb_path = json_data['thumb_path'] if os.path.exists(poster_path): pix = QPixmap(poster_path) self.Ui.label_poster.setScaledContents(True) self.Ui.label_poster.setPixmap(pix) # 添加封面图 + if os.path.exists(thumb_path): + pix = QPixmap(thumb_path) + self.Ui.label_thumb.setScaledContents(True) + self.Ui.label_thumb.setPixmap(pix) # 添加缩略图 + + # ========================================================================检查更新 + def UpdateCheck(self): + if self.Ui.radioButton_update_on.isChecked(): + self.add_text_main('[!]Update Checking!') + html2 = get_html('https://raw.githubusercontent.com/moyy996/AVDC/master/update_check.json') + if html2 == 'ProxyError': + return 'ProxyError' + html = json.loads(str(html2)) + if float(self.version) < float(html['version']): + self.add_text_main('[*] * New update ' + html['version'] + ' *') + self.add_text_main('[*] ↓ Download ↓') + self.add_text_main('[*] ' + html['download']) + else: + self.add_text_main('[!]No Newer Version Available!') + self.add_text_main("[*]======================================================") + return 'True' + + # ========================================================================新建失败输出文件夹 + def CreatFailedFolder(self, failed_folder): + if self.Ui.radioButton_fail_move_on.isChecked() and not os.path.exists(failed_folder): + try: + os.makedirs(failed_folder + '/') + self.add_text_main('[+]Created folder named ' + failed_folder + '!') + except Exception as error_info: + self.add_text_main('[-]Error in CreatFailedFolder: ' + str(error_info)) - def Core_Main(self, file_path, number_th, mode, count): + # ========================================================================删除空目录 + def CEF(self, path): + if os.path.exists(path): + for root, dirs, files in os.walk(path): + for dir in dirs: + try: + os.removedirs(root.replace('\\', '/') + '/' + dir) # 删除这个空文件夹 + self.add_text_main('[+]Deleting empty folder ' + root.replace('\\', '/') + '/' + dir) + except: + delete_empty_folder_failed = '' + + def Core_Main(self, filepath, number, mode, count): # =======================================================================初始化所需变量 + leak = 0 + uncensored = 0 + cn_sub = 0 + c_word = '' multi_part = 0 part = '' - c_word = '' - option = '' - cn_sub = 0 - filepath = file_path # 影片的路径 - number = number_th - config_file = 'config.ini' program_mode = 0 + config_file = 'config.ini' Config = ConfigParser() Config.read(config_file, encoding='UTF-8') - if self.Ui.radioButton_emby.isChecked(): # emby/jellyfin - option = 'emby' - elif self.Ui.radioButton_plex.isChecked(): # plex - option = 'plex' - elif self.Ui.radioButton_kodi.isChecked(): # kodi - option = 'kodi' if self.Ui.radioButton_common.isChecked(): program_mode = 1 elif self.Ui.radioButton_sort.isChecked(): program_mode = 2 movie_path = self.Ui.lineEdit_movie_path.text() - success_folder = movie_path + '/' + self.Ui.lineEdit_success.text() # 成功输出目录 + if movie_path == '': + movie_path = os.getcwd().replace('\\', '/') failed_folder = movie_path + '/' + self.Ui.lineEdit_fail.text() # 失败输出目录 + success_folder = movie_path + '/' + self.Ui.lineEdit_success.text() # 成功输出目录 # =======================================================================获取json_data json_data = self.get_json_data(mode, number, Config) + # =======================================================================调试模式 + if self.Ui.radioButton_debug_on.isChecked(): + self.debug_mode(json_data) # =======================================================================是否找到影片信息 if json_data['website'] == 'timeout': self.add_text_main('[-]Connect Failed! Please check your Proxy or Network!') return 'error' - elif mode == 5 and json_data['actor'] == 'N/A': - self.add_text_main('[-]Your IP Has Been Blocked By JAVDB!') - return 'error' elif json_data['title'] == '': self.add_text_main('[-]Movie Data not found!') node = QTreeWidgetItem(self.item_fail) - node.setText(0, str(count) + '.' + os.path.splitext(filepath.split('/')[-1])[0]) + node.setText(0, str(self.count_claw) + '-' + str(count) + '.' + os.path.splitext(filepath.split('/')[-1])[0]) self.item_fail.addChild(node) self.moveFailedFolder(filepath, failed_folder) return 'not found' @@ -1178,103 +1384,69 @@ def Core_Main(self, file_path, number_th, mode, count): raise Exception('Cover Url is None!') elif json_data['imagecut'] == 3 and 'http' not in json_data['cover_small']: raise Exception('Cover_small Url is None!') - - # =======================================================================调试模式 - if self.Ui.radioButton_debug_on.isChecked(): - self.debug_mode(json_data) - # =======================================================================判断-C,-CD后缀 + # =======================================================================判断-C,-CD后缀,无码,流出 if '-CD' in filepath or '-cd' in filepath: multi_part = 1 part = self.get_part(filepath, failed_folder) if '-c.' in filepath or '-C.' in filepath or '中文' in filepath or '字幕' in filepath: cn_sub = 1 c_word = '-C' # 中文字幕影片后缀 + if json_data['imagecut'] == 3: # imagecut=3为无码 + uncensored = 1 + if '流出' in os.path.split(filepath)[1]: + leak = 1 # =======================================================================创建输出文件夹 - path = self.creatFolder(success_folder, json_data, Config) # 创建成功输出文件夹 + path = self.creatFolder(success_folder, json_data, Config) self.add_text_main('[+]Folder : ' + path) self.add_text_main('[+]From : ' + json_data['website']) - # =======================================================================刮削模式 + # =======================================================================文件命名规则 number = json_data['number'] naming_rule = str(self.get_naming_rule(json_data)).replace('--', '-').strip('-') + if leak == 1: + naming_rule += '-流出' if multi_part == 1: naming_rule += part if cn_sub == 1: naming_rule += c_word + # =======================================================================封面路径 + thumb_path = path + '/' + naming_rule + '-thumb.jpg' + poster_path = path + '/' + naming_rule + '-poster.jpg' + # =======================================================================无码封面获取方式 + if json_data['imagecut'] == 3 and self.Ui.radioButton_poster_cut.isChecked(): + json_data['imagecut'] = 0 + # =======================================================================刮削模式 if program_mode == 1: - # imagecut 1 裁剪右半面,0 裁剪缩略图为封面,3 下载小封面 - self.fanartDownload(option, json_data, path, naming_rule, Config, filepath, failed_folder) - if self.smallCoverDownload(path, naming_rule, json_data, option, Config, filepath, + # imagecut 0 判断人脸位置裁剪缩略图为封面,1 裁剪右半面,3 下载小封面 + self.thumbDownload(json_data, path, naming_rule, Config, filepath, failed_folder) + if self.smallCoverDownload(path, naming_rule, json_data, Config, filepath, failed_folder) == 'small_cover_error': # 下载小封面 json_data['imagecut'] = 0 - self.cutImage(option, json_data['imagecut'], path, naming_rule) # 裁剪图 - self.copyRenameJpgToBackdrop(option, path, naming_rule) - self.PrintFiles(option, path, naming_rule, cn_sub, json_data, filepath, failed_folder) # 打印文件 - self.pasteFileToFolder(filepath, path, naming_rule, failed_folder) # 移动文件 - # =======================================================================整理模式 + self.cutImage(json_data['imagecut'], path, naming_rule) # 裁剪图 + self.copyRenameJpgToFanart(path, naming_rule) + if self.pasteFileToFolder(filepath, path, naming_rule, failed_folder): # 移动文件,True 为有外挂字幕 + cn_sub = 1 + self.PrintFiles(path, naming_rule, cn_sub, leak, json_data, filepath, failed_folder) # 打印文件 + self.add_mark(poster_path, thumb_path, cn_sub, leak, uncensored, Config) + # =======================================================================整理模式 elif program_mode == 2: self.pasteFileToFolder(filepath, path, naming_rule, failed_folder) # 移动文件 # =======================================================================json添加封面项 - fanart_path = '' - poster_path = '' - if self.Ui.radioButton_emby.isChecked(): # emby/jellyfin - fanart_path = path + '/' + naming_rule + '.jpg' - poster_path = path + '/' + naming_rule + '.png' - elif self.Ui.radioButton_plex.isChecked(): # plex - fanart_path = path + '/fanart.jpg' - poster_path = path + '/poster.jpg' - elif self.Ui.radioButton_kodi.isChecked(): # kodi - fanart_path = path + '/' + naming_rule + '-fanart.jpg' - poster_path = path + '/' + naming_rule + '-poster.jpg' - json_data['fanart_path'] = fanart_path + json_data['thumb_path'] = thumb_path json_data['poster_path'] = poster_path json_data['number'] = number self.add_label_info(json_data) - self.json_array[str(count)] = json_data + self.json_array[str(self.count_claw) + '-' + str(count)] = json_data return part + c_word - # ========================================================================检查更新 - def UpdateCheck(self): - if self.Ui.radioButton_update_on.isChecked(): - self.add_text_main('[!]Update Checking!') - html2 = get_html('https://raw.githubusercontent.com/moyy996/AVDC/master/update_check.json') - if html2 == 'ProxyError': - return 'ProxyError' - html = json.loads(str(html2)) - if float(self.version) < float(html['version']): - self.add_text_main('[*] * New update ' + html['version'] + ' *') - self.add_text_main('[*] ↓ Download ↓') - self.add_text_main('[*] ' + html['download']) - else: - self.add_text_main('[!]No Newer Version Available!') - self.add_text_main("[*]======================================================") - return 'True' - - # ========================================================================新建失败输出文件夹 - def CreatFailedFolder(self, failed_folder): - if self.Ui.radioButton_fail_move_on.isChecked() and not os.path.exists(failed_folder): - try: - os.makedirs(failed_folder + '/') - self.add_text_main('[+]Created folder named ' + failed_folder + '!') - except Exception as error_info: - self.add_text_main('[-]Error in CreatFailedFolder: ' + str(error_info)) - - # ========================================================================删除空目录 - def CEF(self, path): - if os.path.exists(path): - for root, dirs, files in os.walk(path): - for dir in dirs: - try: - os.removedirs(root.replace('\\', '/') + '/' + dir) # 删除这个空文件夹 - self.add_text_main('[+]Deleting empty folder ' + root.replace('\\', '/') + '/' + dir) - except: - delete_empty_folder_failed = '' - def AVDC_Main(self): # =======================================================================初始化所需变量 + os.chdir(os.getcwd()) config_file = 'config.ini' config = ConfigParser() config.read(config_file, encoding='UTF-8') movie_path = self.Ui.lineEdit_movie_path.text() + if movie_path == '': + movie_path = os.getcwd().replace('\\', '/') failed_folder = movie_path + '/' + self.Ui.lineEdit_fail.text() # 失败输出目录 escape_folder = self.Ui.lineEdit_escape_dir.text() # 多级目录刮削需要排除的目录 mode = self.Ui.comboBox_website_all.currentIndex() + 1 @@ -1301,21 +1473,21 @@ def AVDC_Main(self): self.Ui.label_progress.setText('当前: ' + str(count) + '/' + str(count_all)) percentage = str(count / int(count_all) * 100)[:4] + '%' value = int(count / int(count_all) * 100) - self.add_text_main('[!] - ' + percentage + ' [' + str(count) + '/' + count_all + '] -') + self.add_text_main('[!] - ' + str(self.count_claw) + ' - ' + percentage + ' - [' + str(count) + '/' + count_all + '] -') try: movie_number = getNumber(movie, escape_string) self.add_text_main("[!]Making Data for [" + movie + "], the number is [" + movie_number + "]") result = self.Core_Main(movie, movie_number, mode, count) if result != 'not found' and movie_number != '' and result != 'error': node = QTreeWidgetItem(self.item_succ) - node.setText(0, str(count) + '.' + movie_number + result) + node.setText(0, str(self.count_claw) + '-' + str(count) + '.' + movie_number + result) self.item_succ.addChild(node) elif result == 'error': break self.add_text_main("[*]======================================================") except Exception as error_info: node = QTreeWidgetItem(self.item_fail) - node.setText(0, str(count) + '.' + os.path.splitext(movie.split('/')[-1])[0]) + node.setText(0, str(self.count_claw) + '-' + str(count) + '.' + os.path.splitext(movie.split('/')[-1])[0]) self.item_fail.addChild(node) self.add_text_main('[-]Error in AVDC_Main: ' + str(error_info)) if self.Ui.radioButton_fail_move_on.isChecked() and not os.path.exists(failed_folder + '/' + os.path.split(movie)[1]): diff --git a/Function/Function.py b/Function/Function.py index 987796425..3b9d26aca 100644 --- a/Function/Function.py +++ b/Function/Function.py @@ -1,13 +1,10 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- - import re import os import json from configparser import ConfigParser -import requests -from lxml import etree -from Getter import avsox, javbus, javdb, fc2fans_club, mgstage, dmm +from Getter import avsox, javbus, javdb, fc2fans_club, mgstage, dmm, jav321 # ========================================================================获取config @@ -22,6 +19,35 @@ def get_config(): return config +# ========================================================================是否为无码 +def is_uncensored(number): + if re.match('^\d{4,}', number) or re.match('n\d{4}', number) or 'HEYZO' in number.upper(): + return True + config = get_config() + prefix_list = str(config['uncensored']['uncensored_prefix']).split('|') + for pre in prefix_list: + if pre.upper() in number.upper(): + return True + return False + + +# ========================================================================元数据获取失败检测 +def getDataState(json_data): + if json_data['title'] == '' or json_data['title'] == 'None' or json_data['title'] == 'null': + return 0 + else: + return 1 + + +# ========================================================================去掉异常字符 +def escapePath(path, Config): # Remove escape literals + escapeLiterals = Config['escape']['literals'] + backslash = '\\' + for literal in escapeLiterals: + path = path.replace(backslash + literal, '') + return path + + # ========================================================================获取视频列表 def movie_lists(escape_folder, movie_type, movie_path): if escape_folder != '': @@ -99,31 +125,27 @@ def getNumber(filepath, escape_string): return os.path.splitext(filepath.split('/')[-1])[0] -# ========================================================================去掉异常字符 -def escapePath(path, Config): # Remove escape literals - escapeLiterals = Config['escape']['literals'] - backslash = '\\' - for literal in escapeLiterals: - path = path.replace(backslash + literal, '') - return path - - # ========================================================================根据番号获取数据 def getDataFromJSON(file_number, config, mode): # 从JSON返回元数据 # ================================================网站规则添加开始================================================ + isuncensored = is_uncensored(file_number) json_data = {} if mode == 1: # 从全部网站刮削 - # =======================================================================无码抓取:111111-111,n1111,HEYZO-1111 - if re.match('^\d{4,}', file_number) or re.match('n\d{4}', file_number) or 'HEYZO' in file_number.upper(): + # =======================================================================无码抓取:111111-111,n1111,HEYZO-1111,SMD-115 + if isuncensored: json_data = json.loads(javbus.main_uncensored(file_number)) if getDataState(json_data) == 0: - json_data = json.loads(javdb.main(file_number)) + json_data = json.loads(javdb.main(file_number, True)) + if getDataState(json_data) == 0 and 'HEYZO' in file_number.upper(): + json_data = json.loads(jav321.main(file_number, True)) if getDataState(json_data) == 0: json_data = json.loads(avsox.main(file_number)) # =======================================================================259LUXU-1111 elif re.match('\d+[a-zA-Z]+-\d+', file_number) or 'SIRO' in file_number.upper(): json_data = json.loads(mgstage.main(file_number)) file_number = re.search('[a-zA-Z]+-\d+', file_number).group() + if getDataState(json_data) == 0: + json_data = json.loads(jav321.main(file_number)) if getDataState(json_data) == 0: json_data = json.loads(javdb.main(file_number)) if getDataState(json_data) == 0: @@ -144,6 +166,8 @@ def getDataFromJSON(file_number, config, mode): # 从JSON返回元数据 # =======================================================================MIDE-139 else: json_data = json.loads(javbus.main(file_number)) + if getDataState(json_data) == 0: + json_data = json.loads(jav321.main(file_number)) if getDataState(json_data) == 0: json_data = json.loads(javdb.main(file_number)) if getDataState(json_data) == 0: @@ -159,20 +183,22 @@ def getDataFromJSON(file_number, config, mode): # 从JSON返回元数据 elif mode == 3: # 仅从fc2club json_data = json.loads(fc2fans_club.main(file_number)) elif mode == 4: # 仅从javbus - if re.match('^\d{5,}', file_number) or re.match('n\d{4}', file_number) or 'HEYZO' in file_number.upper(): + if isuncensored: json_data = json.loads(javbus.main_uncensored(file_number)) elif re.search('\D+.\d{2}.\d{2}.\d{2}', file_number): json_data = json.loads(javbus.main_us(file_number)) else: json_data = json.loads(javbus.main(file_number)) - elif mode == 5: # 仅从javdb + elif mode == 5: # 仅从jav321 + json_data = json.loads(jav321.main(file_number, isuncensored)) + elif mode == 6: # 仅从javdb if re.search('\D+.\d{2}.\d{2}.\d{2}', file_number): json_data = json.loads(javdb.main_us(file_number)) else: - json_data = json.loads(javdb.main(file_number)) - elif mode == 6: # 仅从avsox + json_data = json.loads(javdb.main(file_number, isuncensored)) + elif mode == 7: # 仅从avsox json_data = json.loads(avsox.main(file_number)) - elif mode == 7: # 仅从dmm + elif mode == 8: # 仅从dmm json_data = json.loads(dmm.main(file_number)) # ================================================网站规则添加结束================================================ @@ -273,8 +299,9 @@ def save_config(json_config): print("success_output_folder = " + json_config['success_output_folder'], file=code) print("failed_file_move = " + str(json_config['failed_file_move']), file=code) print("soft_link = " + str(json_config['soft_link']), file=code) + print("show_poster = " + str(json_config['show_poster']), file=code) print("website = " + json_config['website'], file=code) - print("# all or mgstage or fc2club or javbus or javdb or avsox or dmm", file=code) + print("# all or mgstage or fc2club or javbus or jav321 or javdb or avsox or dmm", file=code) print("", file=code) print("[proxy]", file=code) print("proxy = " + json_config['proxy'], file=code) @@ -296,8 +323,6 @@ def save_config(json_config): print("media_type = " + json_config['media_type'], file=code) print("sub_type = " + json_config['sub_type'], file=code) print("media_path = " + json_config['media_path'], file=code) - print("media_warehouse = " + json_config['media_warehouse'], file=code) - print("# emby or plex or kodi ,emby = jellyfin", file=code) print("", file=code) print("[escape]", file=code) print("literals = " + json_config['literals'], file=code) @@ -310,12 +335,20 @@ def save_config(json_config): print("[emby]", file=code) print("emby_url = " + json_config['emby_url'], file=code) print("api_key = " + json_config['api_key'], file=code) - code.close() - + print("", file=code) + print("[mark]", file=code) + print("poster_mark = " + str(json_config['poster_mark']), file=code) + print("thumb_mark = " + str(json_config['thumb_mark']), file=code) + print("mark_size = " + str(json_config['mark_size']), file=code) + print("mark_type = " + json_config['mark_type'], file=code) + print("mark_pos = " + json_config['mark_pos'], file=code) + print("# mark_size : range 1-5", file=code) + print("# mark_type : sub, leak, uncensored", file=code) + print("# mark_pos : bottom_right or bottom_left or top_right or top_left", file=code) + print("", file=code) + print("[uncensored]", file=code) + print("uncensored_prefix = " + str(json_config['uncensored_prefix']), file=code) + print("uncensored_poster = " + str(json_config['uncensored_poster']), file=code) + print("# 0 : official, 1 : cut", file=code) -# ========================================================================元数据获取失败检测 -def getDataState(json_data): - if json_data['title'] == '' or json_data['title'] == 'None' or json_data['title'] == 'null': - return 0 - else: - return 1 + code.close() diff --git a/Function/getHtml.py b/Function/getHtml.py index e40a13a8b..1671ad5d9 100644 --- a/Function/getHtml.py +++ b/Function/getHtml.py @@ -3,8 +3,8 @@ from configparser import ConfigParser -# ========================================================================网页请求 -def get_html(url, cookies=None): +# ========================================================================获取config +def get_config(): config_file = '' if os.path.exists('../config.ini'): config_file = '../config.ini' @@ -12,6 +12,12 @@ def get_html(url, cookies=None): config_file = 'config.ini' config = ConfigParser() config.read(config_file, encoding='UTF-8') + return config + + +# ========================================================================网页请求 +def get_html(url, cookies=None): + config = get_config() retry_count = 0 proxy = '' timeout = 0 @@ -19,7 +25,8 @@ def get_html(url, cookies=None): proxy = str(config['proxy']['proxy']) timeout = int(config['proxy']['timeout']) retry_count = int(config['proxy']['retry']) - except: + except Exception as error_info: + print('Error in get_html :' + str(error_info)) print('[-]Proxy config error! Please check the config.') i = 0 while i < retry_count: @@ -39,10 +46,40 @@ def get_html(url, cookies=None): getweb = requests.get(str(url), headers=headers, timeout=timeout, cookies=cookies) getweb.encoding = 'utf-8' return getweb.text - except: + except Exception as error_info: i += 1 + print('Error in get_html :' + str(error_info)) print('[-]Connect retry ' + str(i) + '/' + str(retry_count)) print('[-]Connect Failed! Please check your Proxy or Network!') return 'ProxyError' +def post_html(url: str, query: dict): + config = get_config() + retry_count = 3 + proxy = '' + timeout = 10 + try: + proxy = str(config['proxy']['proxy']) + timeout = int(config['proxy']['timeout']) + retry_count = int(config['proxy']['retry']) + except Exception as error_info: + print('Error in post_html :' + str(error_info)) + print('[-]Proxy config error! Please check the config.') + if proxy: + proxies = {"http": "http://" + proxy, "https": "https://" + proxy} + else: + proxies = {} + for i in range(retry_count): + try: + result = requests.post(url, data=query, proxies=proxies, timeout=timeout) + result.encoding = 'utf-8' + result = result.text + return result + except Exception as error_info: + print('Error in post_html :' + str(error_info)) + print("[-]Connect retry {}/{}".format(i + 1, retry_count)) + print("[-]Connect Failed! Please check your Proxy or Network!") + return 'ProxyError' + + diff --git a/Getter/avsox.py b/Getter/avsox.py index 248b93d4b..a8655d960 100644 --- a/Getter/avsox.py +++ b/Getter/avsox.py @@ -1,6 +1,5 @@ import json import re - from bs4 import BeautifulSoup from lxml import etree from Function.getHtml import get_html @@ -22,7 +21,7 @@ def getTitle(a): try: html = etree.fromstring(a, etree.HTMLParser()) result = str(html.xpath('/html/body/div[2]/h3/text()')).strip(" ['']") # [0] - return result.replace('/', '').replace('_', '-') + return result.replace('/', '') except: return '' @@ -57,7 +56,7 @@ def getSeries(a): def getNum(a): html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//span[contains(text(),"识别码:")]/../span[2]/text()')).strip(" ['']").replace('_', '-') + result1 = str(html.xpath('//span[contains(text(),"识别码:")]/../span[2]/text()')).strip(" ['']") return result1 @@ -81,17 +80,10 @@ def getCover(htmlcode): return result -def getCover_small(htmlcode, number): +def getCover_small(htmlcode, count): html = etree.fromstring(htmlcode, etree.HTMLParser()) - counts = len(html.xpath("//div[@id='waterfall']/div/a/div")) - if counts == 0: - return '' - for count in range(1, counts + 1): # 遍历搜索结果,找到需要的番号 - number_get = html.xpath("//div[@id='waterfall']/div[" + str(count) + "]/a/div[@class='photo-info']/span/date[1]/text()") - if len(number_get) > 0 and number_get[0] == number: - cover_small = html.xpath("//div[@id='waterfall']/div[" + str(count) + "]/a/div[@class='photo-frame']/img/@src")[0] - return cover_small - return '' + cover_small = html.xpath("//div[@id='waterfall']/div[" + str(count) + "]/a/div[@class='photo-frame']/img/@src")[0] + return cover_small def getTag(a): # 获取演员 @@ -103,54 +95,64 @@ def getTag(a): # 获取演员 return d +def getUrl(number): + response = get_html('https://avsox.host/cn/search/' + number) + html = etree.fromstring(response, etree.HTMLParser()) # //table/tr[1]/td[1]/text() + url_list = html.xpath('//*[@id="waterfall"]/div/a/@href') + if len(url_list) > 0: + for i in range(1, len(url_list) + 1): + number_get = str(html.xpath('//*[@id="waterfall"]/div[' + str(i) + ']/a/div[@class="photo-info"]/span/date[1]/text()')).strip(" ['']") + if number.upper() == number_get.upper(): + return i, response, str(html.xpath('//*[@id="waterfall"]/div[' + str(i) + ']/a/@href')).strip(" ['']") + return response, '' + + def main(number): - a = get_html('https://avsox.host/cn/search/' + number) - html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//*[@id="waterfall"]/div/a/@href')).strip(" ['']") - if result1 == '' or result1 == 'null' or result1 == 'None': - a = get_html('https://avsox.host/cn/search/' + number.replace('-', '_')) - html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//*[@id="waterfall"]/div/a/@href')).strip(" ['']") - if result1 == '' or result1 == 'null' or result1 == 'None': - a = get_html('https://avsox.host/cn/search/' + number.replace('_', '')) - html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//*[@id="waterfall"]/div/a/@href')).strip(" ['']") - web = get_html(result1) - soup = BeautifulSoup(web, 'lxml') - info = str(soup.find(attrs={'class': 'row movie'})) try: + count, response, url = getUrl(number) + if str(response) == 'ProxyError': + raise TimeoutError + if url == '': + raise Exception('Movie Data not found in avsox!') + web = get_html(url) + soup = BeautifulSoup(web, 'lxml') + info = str(soup.find(attrs={'class': 'row movie'})) + number = getNum(web) + print(1) dic = { 'actor': getActor(web), - 'title': getTitle(web).strip(getNum(web)).strip().replace(' ', '-'), + 'title': getTitle(web).strip(number).strip().replace(' ', '-'), 'studio': getStudio(info), - 'publisher': '', - 'outline': '', # 'runtime': getRuntime(info), - 'director': '', # 'release': getRelease(info), 'number': getNum(info), - 'cover': getCover(web), - 'cover_small': getCover_small(a, number), - 'imagecut': 3, 'tag': getTag(web), 'series': getSeries(info), - 'year': getYear(getRelease(info)), # str(re.search('\d{4}',getRelease(a)).group()), + 'year': getYear(getRelease(info)), 'actor_photo': getActorPhoto(web), - 'website': result1, + 'cover': getCover(web), + 'cover_small': getCover_small(response, count), + 'imagecut': 3, + 'director': '', + 'publisher': '', + 'outline': '', + 'score': '', + 'website': url, 'source': 'avsox.py', } - except: - if a == 'ProxyError': - dic = { - 'title': '', - 'website': 'timeout', - } - else: - dic = { - 'title': '', - 'website': '', - } + except TimeoutError: + dic = { + 'title': '', + 'website': 'timeout', + } + except Exception as error_info: + print('Error in avsox.main : ' + str(error_info)) + dic = { + 'title': '', + 'website': '', + } js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'), ) # .encode('UTF-8') return js # print(main('051119-917')) +# print(main('032620_001')) diff --git a/Getter/dmm.py b/Getter/dmm.py index 2bbd3c0da..2011db385 100644 --- a/Getter/dmm.py +++ b/Getter/dmm.py @@ -118,54 +118,57 @@ def getOutline(htmlcode): return result +def getScore(htmlcode): + html = etree.fromstring(htmlcode, etree.HTMLParser()) + result = str(html.xpath("//p[@class='d-review__average']/strong/text()")[0]).replace('\\n', '').replace('\n', '').replace('点', '') + return result + + def main(number): - htmlcode = get_html('https://www.dmm.co.jp/digital/videoa/-/detail/=/cid=' + number) - url = 'https://www.dmm.co.jp/digital/videoa/-/detail/=/cid=' + number - if '404 Not Found' in htmlcode: - htmlcode = get_html('https://www.dmm.co.jp/mono/dvd/-/detail/=/cid=' + number) - url = 'https://www.dmm.co.jp/mono/dvd/-/detail/=/cid=' + number - if '404 Not Found' in htmlcode: - dic = { - 'title': '', - 'website': '', - } - js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':')) # .encode('UTF-8') - return js try: + htmlcode = get_html('https://www.dmm.co.jp/digital/videoa/-/detail/=/cid=' + number) + url = 'https://www.dmm.co.jp/digital/videoa/-/detail/=/cid=' + number + if '404 Not Found' in htmlcode: + htmlcode = get_html('https://www.dmm.co.jp/mono/dvd/-/detail/=/cid=' + number) + url = 'https://www.dmm.co.jp/mono/dvd/-/detail/=/cid=' + number + if '404 Not Found' in htmlcode: + raise Exception('Movie Data not found in dmm!') + if str(htmlcode) == 'ProxyError': + raise TimeoutError actor = getActor(htmlcode) dic = { 'title': getTitle(htmlcode).strip(getActor(htmlcode)), 'studio': getStudio(htmlcode), 'publisher': getPublisher(htmlcode), 'outline': getOutline(htmlcode), + 'score': getScore(htmlcode), 'runtime': getRuntime(htmlcode), 'director': getDirector(htmlcode), 'actor': actor, 'release': getRelease(htmlcode), 'number': getNum(htmlcode), - 'cover': getCover(htmlcode, number), - 'imagecut': 1, 'tag': getTag(htmlcode), - 'series': getSeries(htmlcode), + 'series': getSeries(htmlcode).replace('-', ''), 'year': getYear(getRelease(htmlcode)), # str(re.search('\d{4}',getRelease(a)).group()), 'actor_photo': getActorPhoto(actor), + 'cover': getCover(htmlcode, number), + 'imagecut': 1, 'website': url, 'source': 'dmm.py', } - except: - if htmlcode == 'ProxyError': - dic = { - 'title': '', - 'website': 'timeout', - } - else: - dic = { - 'title': '', - 'website': '', - } + except TimeoutError: + dic = { + 'title': '', + 'website': 'timeout', + } + except Exception as error_info: + print('Error in dmm.main : ' + str(error_info)) + dic = { + 'title': '', + 'website': '', + } js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':')) # .encode('UTF-8') return js # main('DV-1562') -# input("[+][+]Press enter key exit, you can check the error messge before you exit.\n[+][+]按回车键结束,你可以在结束之前查看和错误信息。") # print(main('mide00139')) diff --git a/Getter/fc2fans_club.py b/Getter/fc2fans_club.py index aff4a1c7c..2f845ddd6 100644 --- a/Getter/fc2fans_club.py +++ b/Getter/fc2fans_club.py @@ -1,15 +1,13 @@ import re -from lxml import etree # need install +from lxml import etree import json from Function.getHtml import get_html -def getTitle(htmlcode): # 获取厂商 - # print(htmlcode) +def getTitle(htmlcode): # 获取标题 html = etree.fromstring(htmlcode, etree.HTMLParser()) result = str(html.xpath('/html/body/div[2]/div/div[1]/h3/text()')).strip(" ['']") result2 = str(re.sub('\D{2}2-\d+', '', result)).replace(' ', '', 1) - # print(result2) return result2 @@ -22,7 +20,7 @@ def getActor(htmlcode): return '' -def getActorPhoto(actor): # //*[@id="star_qdt"]/li/a/img +def getActorPhoto(actor): actor = actor.split('/') d = {} for i in actor: @@ -45,29 +43,23 @@ def getNum(htmlcode): # 获取番号 def getRelease(htmlcode2): # - # a=ADC_function.get_html('http://adult.contents.fc2.com/article_search.php?id='+str(number).lstrip("FC2-").lstrip("fc2-").lstrip("fc2_").lstrip("fc2-")+'&utm_source=aff_php&utm_medium=source_code&utm_campaign=from_aff_php') html = etree.fromstring(htmlcode2, etree.HTMLParser()) result = str(html.xpath('//*[@id="container"]/div[1]/div/article/section[1]/div/div[2]/dl/dd[4]/text()')).strip( " ['']") return result -def getCover(htmlcode, number, htmlcode2): # 获取厂商 # - # a = ADC_function.get_html('http://adult.contents.fc2.com/article_search.php?id=' + str(number).lstrip("FC2-").lstrip("fc2-").lstrip("fc2_").lstrip("fc2-") + '&utm_source=aff_php&utm_medium=source_code&utm_campaign=from_aff_php') - html = etree.fromstring(htmlcode2, etree.HTMLParser()) - result = str(html.xpath('//*[@id="container"]/div[1]/div/article/section[1]/div/div[1]/a/img/@src')).strip(" ['']") - if result == '': - html = etree.fromstring(htmlcode, etree.HTMLParser()) - result2 = str(html.xpath('//*[@id="slider"]/ul[1]/li[1]/img/@src')).strip(" ['']") - return 'https://fc2club.com' + result2 - return 'http:' + result +def getCover(htmlcode): # 获取封面 # + html = etree.fromstring(htmlcode, etree.HTMLParser()) + result2 = str(html.xpath('//*[@id="slider"]/ul[1]/li[1]/img/@src')).strip(" ['']") + return 'https://fc2club.com' + result2 -def getOutline(htmlcode2): # 获取番号 # - html = etree.fromstring(htmlcode2, etree.HTMLParser()) - result = str(html.xpath('/html/body/div[1]/div[2]/div[2]/div[1]/div/article/section[4]/p/text()')).strip( - " ['']").replace("\\n", '', 10000).replace("'", '', 10000).replace(', ,', '').strip(' ').replace('。,', ',') - return result +def getScore(htmlcode): # 获取评分 # + if re.search(r'影片评分:(\d+)分', htmlcode): + score = str(re.findall(r'影片评分:(\d+)分', htmlcode)).strip(" ['']") + score = float(int(score) / 100.0 * 5) + return str(score) def getTag(htmlcode): # 获取番号 @@ -85,44 +77,47 @@ def getYear(release): def main(number): - htmlcode2 = get_html( - 'http://adult.contents.fc2.com/article_search.php?id=' + number + '&utm_source=aff_php&utm_medium=source_code&utm_campaign=from_aff_php') - htmlcode = get_html('https://fc2club.com//html/FC2-' + number + '.html') - actor = getActor(htmlcode) - if len(actor) == 0: - actor = 'FC2系列' try: + htmlcode = get_html('https://fc2club.com//html/FC2-' + number + '.html') + if str(htmlcode) == 'ProxyError': + raise TimeoutError + actor = getActor(htmlcode) + if len(actor) == 0: + actor = 'FC2系列' dic = { - 'title': getTitle(htmlcode).replace(' ', '-'), + 'title': getTitle(htmlcode).strip(' '), 'studio': getStudio(htmlcode), - 'publisher': '', - 'year': '', # str(re.search('\d{4}',getRelease(number)).group()), - 'outline': getOutline(htmlcode2).replace('\n', ''), + 'score': getScore(htmlcode), 'runtime': getYear(getRelease(htmlcode)), - 'director': '', 'actor': actor.replace('/', ','), 'release': getRelease(number), 'number': 'FC2-' + number, - 'cover': getCover(htmlcode, number, htmlcode2), - 'imagecut': 0, - 'series': '', 'tag': getTag(htmlcode), 'actor_photo': getActorPhoto(actor), + 'cover': getCover(htmlcode), + 'imagecut': 0, + 'director': '', + 'series': '', + 'publisher': '', + 'year': '', + 'outline': '', 'website': 'https://fc2club.com//html/FC2-' + number + '.html', 'source': 'fc2fans_club.py', } - except: - if htmlcode2 == 'ProxyError': - dic = { - 'title': '', - 'website': 'timeout', - } - else: - dic = { - 'title': '', - 'website': '', - } - js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'), ) # .encode('UTF-8') + except TimeoutError: + dic = { + 'title': '', + 'website': 'timeout', + } + except Exception as error_info: + print('Error in fc2fans_club.main : ' + str(error_info)) + dic = { + 'title': '', + 'website': '', + } + js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'), ) return js + # print(main('1251689')) +# print(main('674239')) diff --git a/Getter/jav321.py b/Getter/jav321.py new file mode 100644 index 000000000..763ed4070 --- /dev/null +++ b/Getter/jav321.py @@ -0,0 +1,152 @@ +import re +from lxml import etree +import json +from Function.getHtml import post_html + + +def getActorPhoto(actor): + data = {} + for i in actor: + actor_photo = {i: ''} + data.update(actor_photo) + return data + + +def getTitle(response): + return str(re.findall(r'

(.+) ', response)).strip(" ['']") + + +def getActor(response): + if re.search(r'(\S+)  ', response): + return str(re.findall(r'(\S+)  ', response)).strip(" [',']").replace('\'', '') + elif re.search(r'(\S+)  ', response): + return str(re.findall(r'(\S+)  ', response)).strip(" [',']").replace('\'', + '') + else: + return str(re.findall(r'女优: (.+)  
', response)).strip(" [',']").replace('\'', '') + + +def getStudio(response): + return str(re.findall(r'(\S+)', response)).strip(" ['']") + + +def getRuntime(response): + return str(re.findall(r'播放时长: (\d+) \S+
', response)).strip(" ['']") + + +def getSeries(response): + return str(re.findall(r'系列: (\S+)', response)).strip(" ['']") + + +def getWebsite(detail_page): + return 'https:' + detail_page.xpath('//a[contains(text(),"简体中文")]/@href')[0] + + +def getNum(response): + return str(re.findall(r'番号: (\S+)
', response)).strip(" ['']").upper() + + +def getScore(response): + if re.search(r'评分: ', response): + score = re.findall(r'评分: ', response)[0] + return str(float(score) / 10.0) + else: + return str(re.findall(r'评分: (.+)
', response)).strip(" [',']").replace('\'', '') + + +def getYear(release): + try: + result = str(re.search('\d{4}', release).group()) + return result + except: + return release + + +def getRelease(response): + return str(re.findall(r'发行日期: (\d+-\d+-\d+)
', response)).strip(" ['']").replace('0000-00-00', '') + + +def getCover(detail_page): + cover_url = str(detail_page.xpath("/html/body/div[@class='row'][2]/div[@class='col-md-3']/div[@class='col-xs-12 " + "col-md-12'][1]/p/a/img[@class='img-responsive']/@src")).strip(" ['']") + if cover_url == '': + cover_url = str( + detail_page.xpath("//*[@id='vjs_sample_player']/@poster")).strip(" ['']") + return cover_url + + +def getCoverSmall(detail_page): + return str(detail_page.xpath("//div[@class='panel-body']/div[@class='row'][1]/div[@class='col-md-3']/img[" + "@class='img-responsive']/@src")).strip(" ['']") + + +def getTag(response): # 获取演员 + return re.findall(r'(\S+)', response) + + +def getOutline(detail_page): + return str(detail_page.xpath('/html/body/div[2]/div[1]/div[1]/div[2]/div[3]/div/text()')).strip(" ['']") + + +def main(number, isuncensored=False): + try: + response = post_html("https://www.jav321.com/search", query={"sn": number}) + if str(response) == 'ProxyError': + raise TimeoutError + if '未找到您要找的AV' in response: + raise Exception('Movie Data not found in jav321!') + detail_page = etree.fromstring(response, etree.HTMLParser()) + release = getRelease(response) + actor = getActor(response) + imagecut = 1 + cover_small = '' + if 'HEYZO' in number.upper() or isuncensored: + imagecut = 3 + cover_small = getCoverSmall(detail_page) + if cover_small == '': + imagecut = 0 + dic = { + 'actor': actor, + 'title': getTitle(response), + 'studio': getStudio(response), + 'outline': getOutline(detail_page), + 'runtime': getRuntime(response), + 'release': release, + 'number': getNum(response), + 'score': getScore(response), + 'tag': getTag(response), + 'series': getSeries(response), + 'year': getYear(release), + 'actor_photo': getActorPhoto(actor.split(',')), + 'cover': getCover(detail_page), + 'cover_small': cover_small, + 'imagecut': imagecut, + 'director': '', + 'publisher': '', + 'website': getWebsite(detail_page), + 'source': 'jav321.py', + } + except TimeoutError: + dic = { + 'title': '', + 'website': 'timeout', + } + except Exception as error_info: + print('Error in jav321.main : ' + str(error_info)) + dic = { + 'title': '', + 'website': '', + } + js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'), ) # .encode('UTF-8') + return js + + +''' +print(main('msfh-010')) +print(main('kavr-065')) +print(main('ssni-645')) +print(main('sivr-038')) +print(main('ara-415')) +print(main('luxu-1257')) +print(main('heyzo-1031')) +''' diff --git a/Getter/javbus.py b/Getter/javbus.py index 12c5a1505..2b1309bd8 100644 --- a/Getter/javbus.py +++ b/Getter/javbus.py @@ -1,12 +1,13 @@ import re -from pyquery import PyQuery as pq # need install -from lxml import etree # need install -from bs4 import BeautifulSoup # need install +from pyquery import PyQuery as pq +from lxml import etree +from bs4 import BeautifulSoup import json from Function.getHtml import get_html +from Function.getHtml import post_html -def getActorPhoto(htmlcode): # //*[@id="star_qdt"]/li/a/img +def getActorPhoto(htmlcode): soup = BeautifulSoup(htmlcode, 'lxml') a = soup.find_all(attrs={'class': 'star-name'}) d = {} @@ -89,16 +90,16 @@ def getDirector(htmlcode): # 获取导演 return result -def getOutline(number): # 获取简介 - try: - dww_htmlcode = get_html('https://www.dmm.co.jp/digital/videoa/-/detail/=/cid=' + number.replace("-", '00')) - if '404 Not Found' in dww_htmlcode: - dww_htmlcode = get_html('https://www.dmm.co.jp/mono/dvd/-/detail/=/cid=' + number.replace("-", '00')) - except: - dww_htmlcode = '' - html = etree.fromstring(dww_htmlcode, etree.HTMLParser()) - result = str(html.xpath("//div[@class='mg-b20 lh4']/text()")).strip(" ['']") - return result.replace('\n', '').replace('\\n', '').replace('\'', '').replace(',', '').replace(' ', '') +def getOutlineScore(number): # 获取简介 + response = post_html("https://www.jav321.com/search", query={"sn": number}) + detail_page = etree.fromstring(response, etree.HTMLParser()) + outline = str(detail_page.xpath('/html/body/div[2]/div[1]/div[1]/div[2]/div[3]/div/text()')).strip(" ['']") + if re.search(r'评分: ', response): + score = re.findall(r'评分: ', response)[0] + score = str(float(score) / 10.0) + else: + score = str(re.findall(r'评分: (.+)
', response)).strip(" [',']").replace('\'', '') + return outline, score def getSeries(htmlcode): @@ -109,21 +110,13 @@ def getSeries(htmlcode): def getCover_small(number): # 从avsox获取封面图 htmlcode = get_html('https://avsox.host/cn/search/' + number) - html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result = str(html.xpath('//*[@id="waterfall"]/div/a/@href')).strip(" ['']") - if result == '' or result == 'null' or result == 'None': - htmlcode = get_html('https://avsox.host/cn/search/' + number.replace('-', '_')) - html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result = str(html.xpath('//*[@id="waterfall"]/div/a/@href')).strip(" ['']") - if result == '' or result == 'null' or result == 'None': - htmlcode = get_html('https://avsox.host/cn/search/' + number.replace('_', '')) html = etree.fromstring(htmlcode, etree.HTMLParser()) counts = len(html.xpath("//div[@id='waterfall']/div/a/div")) if counts == 0: return '' for count in range(1, counts + 1): # 遍历搜索结果,找到需要的番号 number_get = html.xpath("//div[@id='waterfall']/div[" + str(count) + "]/a/div[@class='photo-info']/span/date[1]/text()") - if len(number_get) > 0 and number_get[0] == number: + if len(number_get) > 0 and number_get[0].upper() == number.upper(): cover_small = html.xpath("//div[@id='waterfall']/div[" + str(count) + "]/a/div[@class='photo-frame']/img/@src")[0] return cover_small return '' @@ -142,7 +135,6 @@ def getTag(htmlcode): # 获取标签 def find_number(number): # =======================================================================有码搜索 - counts = 0 if not (re.match('^\d{4,}', number) or re.match('n\d{4}', number) or 'HEYZO' in number.upper()): htmlcode = get_html('https://www.javbus.com/search/' + number + '&type=1') html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() @@ -150,12 +142,9 @@ def find_number(number): if counts != 0: for count in range(1, counts + 1): # 遍历搜索结果,找到需要的番号 number_get = html.xpath("//div[@id='waterfall']/div[@id='waterfall']/div[" + str(count) + "]/a[@class='movie-box']/div[@class='photo-info']/span/date[1]/text()")[0] - # number_get = number_get.replace('_', '-') - if number_get == number.upper() or number_get == number.upper().replace('-', '') or number_get == number.upper().replace('_', ''): - result_url = html.xpath( - "//div[@id='waterfall']/div[@id='waterfall']/div[" + str(count) + "]/a[@class='movie-box']/@href")[0] - return result_url - elif number_get == number.lower() or number_get == number.lower().replace('-', '') or number_get == number.lower().replace('_', ''): + number_get = number_get.upper() + number = number.upper() + if number_get == number or number_get == number.replace('-', '') or number_get == number.replace('_', ''): result_url = html.xpath( "//div[@id='waterfall']/div[@id='waterfall']/div[" + str(count) + "]/a[@class='movie-box']/@href")[0] return result_url @@ -167,12 +156,9 @@ def find_number(number): return 'not found' for count in range(1, counts + 1): # 遍历搜索结果,找到需要的番号 number_get = html.xpath("//div[@id='waterfall']/div[@id='waterfall']/div[" + str(count) + "]/a[@class='movie-box']/div[@class='photo-info']/span/date[1]/text()")[0] - # number_get = number_get.replace('_', '-') - if number_get == number.upper() or number_get == number.upper().replace('-', '') or number_get == number.upper().replace('_', ''): - result_url = html.xpath( - "//div[@id='waterfall']/div[@id='waterfall']/div[" + str(count) + "]/a[@class='movie-box']/@href")[0] - return result_url - elif number_get == number.lower() or number_get == number.lower().replace('-', '') or number_get == number.lower().replace('_', ''): + number_get = number_get.upper() + number = number.upper() + if number_get == number or number_get == number.replace('-', '') or number_get == number.replace('_', ''): result_url = html.xpath( "//div[@id='waterfall']/div[@id='waterfall']/div[" + str(count) + "]/a[@class='movie-box']/@href")[0] return result_url @@ -184,25 +170,22 @@ def find_number(number): def main(number): - result_url = find_number(number) - if result_url == 'not found': - dic = { - 'title': '', - 'actor': '', - 'website': '', - } - js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, - separators=(',', ':'), ) # .encode('UTF-8') - return js - htmlcode = get_html(result_url) try: + result_url = find_number(number) + if result_url == 'not found': + raise Exception('Movie Data not found in javbus.main!') + htmlcode = get_html(result_url) + if str(htmlcode) == 'ProxyError': + raise TimeoutError + outline, score = getOutlineScore(number) number = getNum(htmlcode) dic = { 'title': str(getTitle(htmlcode)).replace(number, '').strip().replace(' ', '-'), 'studio': getStudio(htmlcode), 'publisher': getPublisher(htmlcode), 'year': getYear(getRelease(htmlcode)), - 'outline': getOutline(number), + 'outline': outline, + 'score': score, 'runtime': getRuntime(htmlcode).replace('分鐘', '').strip(), 'director': getDirector(htmlcode), 'actor': getActor(htmlcode), @@ -216,42 +199,41 @@ def main(number): 'website': result_url, 'source': 'javbus.py', } + except TimeoutError: + dic = { + 'title': '', + 'website': 'timeout', + } except Exception as error_info: - print('Error in javbus.main :' + str(error_info)) - if htmlcode == 'ProxyError': - dic = { - 'title': '', - 'website': 'timeout', - } - else: - dic = { - 'title': '', - 'website': '', - } + print('Error in javbus.main : ' + str(error_info)) + dic = { + 'title': '', + 'website': '', + } js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'), ) # .encode('UTF-8') return js def main_uncensored(number): - result_url = find_number(number) - if result_url == 'not found': - dic = { - 'title': '', - 'actor': '', - 'website': '', - } - js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, - separators=(',', ':'), ) # .encode('UTF-8') - return js - htmlcode = get_html(result_url) try: + result_url = find_number(number) + if result_url == 'not found': + raise Exception('Movie Data not found in javbus.main_uncensored!') + htmlcode = get_html(result_url) + if str(htmlcode) == 'ProxyError': + raise TimeoutError number = getNum(htmlcode) + outline = '' + score = '' + if 'HEYZO' in number.upper(): + outline, score = getOutlineScore(number) dic = { 'title': getTitle(htmlcode).replace(number, '').strip().replace(' ', '-'), 'studio': getStudio(htmlcode), 'publisher': '', 'year': getYear(getRelease(htmlcode)), - 'outline': '', + 'outline': outline, + 'score': score, 'runtime': getRuntime(htmlcode).replace('分鐘', '').strip(), 'director': getDirector(htmlcode), 'actor': getActor(htmlcode), @@ -268,96 +250,90 @@ def main_uncensored(number): } if dic['cover_small'] == '': dic['imagecut'] = 0 - except Exception as error_info: - print('Error in javbus.main_uncensored :' + str(error_info)) - if htmlcode == 'ProxyError': - dic = { - 'title': '', - 'website': 'timeout', - } - else: - dic = { - 'title': '', - 'website': '', - } - js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'), ) # .encode('UTF-8') - return js - - -def main_us(number): - htmlcode = get_html('https://www.javbus.zone/search/' + number) - html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - counts = len(html.xpath("//div[@class='row']/div[@id='waterfall']/div")) - if counts == 0: + except TimeoutError: dic = { 'title': '', - 'actor': '', - 'website': '', + 'website': 'timeout', } - js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, - separators=(',', ':'), ) # .encode('UTF-8') - return js - result_url = '' - cover_small = '' - for count in range(1, counts + 1): # 遍历搜索结果,找到需要的番号 - number_get = html.xpath("//div[@id='waterfall']/div[" + str( - count) + "]/a[@class='movie-box']/div[@class='photo-info']/span/date[1]/text()")[0] - if number_get.upper() == number.upper() or number_get.replace('-', '').upper() == number.upper(): - result_url = html.xpath( - "//div[@id='waterfall']/div[" + str(count) + "]/a[@class='movie-box']/@href")[0] - cover_small = html.xpath( - "//div[@id='waterfall']/div[" + str( - count) + "]/a[@class='movie-box']/div[@class='photo-frame']/img[@class='img']/@src")[0] - break - if result_url == 'not found': + except Exception as error_info: + print('Error in javbus.main_uncensored : ' + str(error_info)) dic = { 'title': '', - 'actor': '', 'website': '', } - js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, - separators=(',', ':'), ) # .encode('UTF-8') - return js - htmlcode = get_html(result_url) + js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'), ) # .encode('UTF-8') + return js + + +def main_us(number): try: + htmlcode = get_html('https://www.javbus.zone/search/' + number) + if str(htmlcode) == 'ProxyError': + raise TimeoutError + html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() + counts = len(html.xpath("//div[@class='row']/div[@id='waterfall']/div")) + if counts == 0: + raise Exception('Movie Data not found in javbus.main_us!') + result_url = '' + cover_small = '' + for count in range(1, counts + 1): # 遍历搜索结果,找到需要的番号 + number_get = html.xpath("//div[@id='waterfall']/div[" + str( + count) + "]/a[@class='movie-box']/div[@class='photo-info']/span/date[1]/text()")[0] + if number_get.upper() == number.upper() or number_get.replace('-', '').upper() == number.upper(): + result_url = html.xpath( + "//div[@id='waterfall']/div[" + str(count) + "]/a[@class='movie-box']/@href")[0] + cover_small = html.xpath( + "//div[@id='waterfall']/div[" + str( + count) + "]/a[@class='movie-box']/div[@class='photo-frame']/img[@class='img']/@src")[0] + break + if result_url == '': + raise Exception('Movie Data not found in javbus.main_us!') + htmlcode = get_html(result_url) + if str(htmlcode) == 'ProxyError': + raise TimeoutError number = getNum(htmlcode) dic = { 'title': getTitle(htmlcode).replace(number, '').strip(), 'studio': getStudio(htmlcode), - 'publisher': '', 'year': getYear(getRelease(htmlcode)), - 'outline': '', 'runtime': getRuntime(htmlcode).replace('分鐘', '').strip(), 'director': getDirector(htmlcode), 'actor': getActor(htmlcode), 'release': getRelease(htmlcode), 'number': getNum(htmlcode), - 'cover': getCover(htmlcode), 'tag': getTag(htmlcode), 'series': getSeries(htmlcode), - 'imagecut': 3, + 'cover': getCover(htmlcode), 'cover_small': cover_small, + 'imagecut': 3, 'actor_photo': getActorPhoto(htmlcode), + 'publisher': '', + 'outline': '', + 'score': '', 'website': result_url, 'source': 'javbus.py', } + except TimeoutError: + dic = { + 'title': '', + 'website': 'timeout', + } except Exception as error_info: - print('Error in javbus.main_us :' + str(error_info)) - if htmlcode == 'ProxyError': - dic = { - 'title': '', - 'website': 'timeout', - } - else: - dic = { - 'title': '', - 'website': '', - } + print('Error in javbus.main_us : ' + str(error_info)) + dic = { + 'title': '', + 'website': '', + } js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'), ) # .encode('UTF-8') return js -# print(find_number('KA-001')) -# print(main('OFJE-175')) -# print(main_uncensored('010115-001')) -# print(main_uncensored('012715-793')) -# print(main_us('sexart.15.06.10')) + +''' +print(find_number('KA-001')) +print(main_uncensored('010115-001')) +print(main('ssni-644')) +print(main_uncensored('012715-793')) +print(main_us('sexart.15.06.10')) +print(main_uncensored('heyzo-1031')) +''' + diff --git a/Getter/javdb.py b/Getter/javdb.py index d04b26707..e4bf409ad 100644 --- a/Getter/javdb.py +++ b/Getter/javdb.py @@ -1,7 +1,9 @@ import re +from bs4 import BeautifulSoup, SoupStrainer from lxml import etree import json from Function.getHtml import get_html +from Function.getHtml import post_html def getTitle(htmlcode): @@ -15,8 +17,8 @@ def getTitle(htmlcode): def getActor(htmlcode): # //*[@id="center_column"]/div[2]/div[1]/div/table/tbody/tr[1]/td/text() html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = html.xpath('//strong[contains(text(),"演員")]/../following-sibling::span/text()') - result2 = html.xpath('//strong[contains(text(),"演員")]/../following-sibling::span/a/text()') + result1 = html.xpath('//strong[contains(text(),"演員")]/../span/text()') + result2 = html.xpath('//strong[contains(text(),"演員")]/../span/a/text()') return result1 + result2 @@ -31,37 +33,37 @@ def getActorPhoto(actor): # //*[@id="star_qdt"]/li/a/img def getStudio(htmlcode): html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//strong[contains(text(),"片商")]/../following-sibling::span/text()')).strip(" ['']") - result2 = str(html.xpath('//strong[contains(text(),"片商")]/../following-sibling::span/a/text()')).strip(" ['']") + result1 = str(html.xpath('//strong[contains(text(),"片商")]/../span/text()')).strip(" ['']") + result2 = str(html.xpath('//strong[contains(text(),"片商")]/../span/a/text()')).strip(" ['']") return str(result1 + result2).strip('+').replace("', '", '').replace('"', '') def getPublisher(htmlcode): html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//strong[contains(text(),"發行")]/../following-sibling::span/text()')).strip(" ['']") - result2 = str(html.xpath('//strong[contains(text(),"發行")]/../following-sibling::span/a/text()')).strip(" ['']") + result1 = str(html.xpath('//strong[contains(text(),"發行")]/../span/text()')).strip(" ['']") + result2 = str(html.xpath('//strong[contains(text(),"發行")]/../span/a/text()')).strip(" ['']") return str(result1 + result2).strip('+').replace("', '", '').replace('"', '') def getRuntime(htmlcode): html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//strong[contains(text(),"時長")]/../following-sibling::span/text()')).strip(" ['']") - result2 = str(html.xpath('//strong[contains(text(),"時長")]/../following-sibling::span/a/text()')).strip(" ['']") + result1 = str(html.xpath('//strong[contains(text(),"時長")]/../span/text()')).strip(" ['']") + result2 = str(html.xpath('//strong[contains(text(),"時長")]/../span/a/text()')).strip(" ['']") return str(result1 + result2).strip('+').rstrip('mi') def getSeries(htmlcode): html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//strong[contains(text(),"系列")]/../following-sibling::span/text()')).strip(" ['']") - result2 = str(html.xpath('//strong[contains(text(),"系列")]/../following-sibling::span/a/text()')).strip(" ['']") + result1 = str(html.xpath('//strong[contains(text(),"系列")]/../span/text()')).strip(" ['']") + result2 = str(html.xpath('//strong[contains(text(),"系列")]/../span/a/text()')).strip(" ['']") return str(result1 + result2).strip('+').replace("', '", '').replace('"', '') def getNumber(htmlcode): html = etree.fromstring(htmlcode, etree.HTMLParser()) - result1 = str(html.xpath('//strong[contains(text(),"番號")]/../following-sibling::span/text()')).strip( + result1 = str(html.xpath('//strong[contains(text(),"番號")]/../span/text()')).strip( " ['']").replace('_', '-') - result2 = str(html.xpath('//strong[contains(text(),"番號")]/../following-sibling::span/a/text()')).strip( + result2 = str(html.xpath('//strong[contains(text(),"番號")]/../span/a/text()')).strip( " ['']").replace('_', '-') return str(result2 + result1).strip('+') @@ -76,23 +78,23 @@ def getYear(getRelease): def getRelease(htmlcode): html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//strong[contains(text(),"時間")]/../following-sibling::span/text()')).strip(" ['']") - result2 = str(html.xpath('//strong[contains(text(),"時間")]/../following-sibling::span/a/text()')).strip(" ['']") + result1 = str(html.xpath('//strong[contains(text(),"時間")]/../span/text()')).strip(" ['']") + result2 = str(html.xpath('//strong[contains(text(),"時間")]/../span/a/text()')).strip(" ['']") return str(result1 + result2).strip('+') def getTag(htmlcode): html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//strong[contains(text(),"类别")]/../following-sibling::span/text()')).strip(" ['']") - result2 = str(html.xpath('//strong[contains(text(),"类别")]/../following-sibling::span/a/text()')).strip(" ['']") + result1 = str(html.xpath('//strong[contains(text(),"類別")]/../span/text()')).strip(" ['']") + result2 = str(html.xpath('//strong[contains(text(),"類別")]/../span/a/text()')).strip(" ['']") return str(result1 + result2).strip('+').replace(",\\xa0", "").replace("'", "").replace(' ', '').replace(',,', '').lstrip( ',') def getCover_small(htmlcode, count): - html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result = html.xpath("//div[@class='item-image fix-scale-cover']/img/@src")[count] + html = etree.fromstring(htmlcode, etree.HTMLParser()) + result = html.xpath("//div[@class='grid-item column']/a[@class='box']/div/img/@src")[count] if not 'https' in result: result = 'https:' + result return result @@ -100,131 +102,140 @@ def getCover_small(htmlcode, count): def getCover(htmlcode): html = etree.fromstring(htmlcode, etree.HTMLParser()) - result = str(html.xpath("//div[@class='column column-video-cover']/a/img/@src")).strip(" ['']") + result = str(html.xpath("//img[@class='box video-cover']/@src")).strip(" ['']") + # 有时xpath找不到元素,所以要用bs4 + if not result: + soup = BeautifulSoup(htmlcode, 'lxml', parse_only=SoupStrainer('img', {'class': 'box video-cover'})) + if soup.img is not None: + result = soup.img['src'] return result def getDirector(htmlcode): html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//strong[contains(text(),"導演")]/../following-sibling::span/text()')).strip(" ['']") - result2 = str(html.xpath('//strong[contains(text(),"導演")]/../following-sibling::span/a/text()')).strip(" ['']") + result1 = str(html.xpath('//strong[contains(text(),"導演")]/../span/text()')).strip(" ['']") + result2 = str(html.xpath('//strong[contains(text(),"導演")]/../span/a/text()')).strip(" ['']") return str(result1 + result2).strip('+').replace("', '", '').replace('"', '') -def getOutline(number): # 获取简介 - try: - dww_htmlcode = get_html('https://www.dmm.co.jp/digital/videoa/-/detail/=/cid=' + number.replace("-", '00')) - if '404 Not Found' in dww_htmlcode: - dww_htmlcode = get_html('https://www.dmm.co.jp/mono/dvd/-/detail/=/cid=' + number.replace("-", '00')) - except: - dww_htmlcode = '' - html = etree.fromstring(dww_htmlcode, etree.HTMLParser()) - result = str(html.xpath("//div[@class='mg-b20 lh4']/text()")).strip(" ['']") - return result.replace('\n', '').replace('\\n', '').replace('\'', '').replace(',', '').replace(' ', '') - - -def main(number): - htmlcode = '' +def getScore(htmlcode): + html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() + result = str(html.xpath("//span[@class='score-label']/text()")).strip(" ['']") + score = 0 + if re.search(r'\(.+分\)', result): + score = re.findall(r'\((.+)分\)', result)[0] + return format(float(score), '0.1f') + + +def getOutlineScore(number): # 获取简介 + response = post_html("https://www.jav321.com/search", query={"sn": number}) + detail_page = etree.fromstring(response, etree.HTMLParser()) + outline = str(detail_page.xpath('/html/body/div[2]/div[1]/div[1]/div[2]/div[3]/div/text()')).strip(" ['']") + if re.search(r'评分: ', response): + score = re.findall(r'评分: ', response)[0] + score = str(float(score) / 10.0) + else: + score = str(re.findall(r'评分: (.+)
', response)).strip(" [',']").replace('\'', '') + return outline, score + + +def main(number, isuncensored=False): try: + # ========================================================================搜索番号 htmlcode = get_html('https://javdb.com/search?q=' + number + '&f=all').replace(u'\xa0', u' ') + if str(htmlcode) == 'ProxyError': + raise TimeoutError html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() counts = len(html.xpath( '//div[@id=\'videos\']/div[@class=\'grid columns\']/div[@class=\'grid-item column\']')) if counts == 0: - dic = { - 'title': '', - 'actor': '', - 'website': '', - } - js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, - separators=(',', ':'), ) # .encode('UTF-8') - return js + raise Exception('Movie Data not found in javdb.main!') + # ========================================================================遍历搜索结果,找到需要的番号所在URL count = 1 number_get = '' movie_found = 0 - for count in range(1, counts + 1): # 遍历搜索结果,找到需要的番号 + for count in range(1, counts + 1): number_get = html.xpath( '//div[@id=\'videos\']/div[@class=\'grid columns\']/div[@class=\'grid-item column\'][' + str( count) + ']/a[@class=\'box\']/div[@class=\'uid\']/text()')[0] - # number_get = number_get.replace('_', '-') - if number_get == number.upper() or number_get == number.lower(): + if number_get.upper() == number.upper(): movie_found = 1 break + if movie_found == 0: + raise Exception('Movie Data not found in javdb.main!') result_url = 'https://javdb.com' + html.xpath('//*[@id="videos"]/div/div/a/@href')[count - 1] - b = get_html(result_url).replace(u'\xa0', u' ') - actor = getActor(b) + # ========================================================================请求、判断结果 + html_info = get_html(result_url).replace(u'\xa0', u' ') + if str(html_info) == 'ProxyError': + raise TimeoutError + # ========================================================================获取评分、简介 + imagecut = 1 + cover_small = '' + outline = '' + if isuncensored or re.match('^\d{4,}', number) or re.match('n\d{4}', number): # 无码,收集封面、评分 + imagecut = 3 + cover_small = getCover_small(htmlcode, count - 1) + score = getScore(html_info) + elif 'HEYZO' in number.upper(): # HEYZO,收集封面、评分、简介 + imagecut = 3 + cover_small = getCover_small(htmlcode, count - 1) + outline, score = getOutlineScore(number) + else: # 其他,收集评分、简介 + outline, score = getOutlineScore(number) + # ========================================================================收集信息 + actor = getActor(html_info) if len(actor) == 0 and 'FC2-' in number_get: actor.append('FC2-NoActor') - if movie_found == 1: - imagecut = 1 - cover_small = '' - outline = '' - if re.match('^\d{4,}', number) or re.match('n\d{4}', number) or 'HEYZO' in number.upper(): - imagecut = 3 - cover_small = getCover_small(htmlcode, count - 1) - else: - outline = getOutline(number) - dic = { - 'actor': str(actor).strip(" [',']").replace('\'', ''), - 'title': getTitle(b).replace('中文字幕', '').replace("\\n", '').replace('_', '-').replace(number_get, - '').strip().replace( - ' ', '-').replace('--', '-'), - 'studio': getStudio(b), - 'publisher': getPublisher(b), - 'outline': outline, - 'runtime': getRuntime(b).replace(' 分鍾', ''), - 'director': getDirector(b), - 'release': getRelease(b), - 'number': number_get, - 'cover': getCover(b), - 'cover_small': cover_small, - 'imagecut': imagecut, - 'tag': getTag(b), - 'series': getSeries(b), - 'year': getYear(getRelease(b)), # str(re.search('\d{4}',getRelease(htmlcode)).group()), - 'actor_photo': getActorPhoto(actor), - 'website': result_url, - 'source': 'javdb.py', - } - else: # 未找到番号 - dic = { - 'title': '', - 'actor': str(actor).strip(" [',']").replace('\'', ''), - 'website': '', - } - except: # actor 用于判断ip是否被封 - if htmlcode == 'ProxyError': - dic = { - 'title': '', - 'actor': '', - 'website': 'timeout', - } - else: - dic = { - 'title': '', - 'actor': '', - 'website': '', - } + dic = { + 'actor': str(actor).strip(" [',']").replace('\'', ''), + 'title': getTitle(html_info).replace('中文字幕', '').replace('無碼', '').replace("\\n", '').replace('_', + '-').replace( + number_get, '').strip().replace(' ', '-').replace('--', '-'), + 'studio': getStudio(html_info), + 'publisher': getPublisher(html_info), + 'outline': outline, + 'score': score, + 'runtime': getRuntime(html_info).replace(' 分鍾', ''), + 'director': getDirector(html_info), + 'release': getRelease(html_info), + 'number': number_get, + 'cover': getCover(html_info), + 'cover_small': cover_small, + 'imagecut': imagecut, + 'tag': getTag(html_info), + 'series': getSeries(html_info), + 'year': getYear(getRelease(html_info)), # str(re.search('\d{4}',getRelease(htmlcode)).group()), + 'actor_photo': getActorPhoto(actor), + 'website': result_url, + 'source': 'javdb.py', + } + except TimeoutError: + dic = { + 'title': '', + 'website': 'timeout', + } + except Exception as error_info: + print('Error in javdb.main : ' + str(error_info)) + dic = { + 'title': '', + 'website': '', + } js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'), ) # .encode('UTF-8') return js def main_us(number): - htmlcode = '' try: + # ========================================================================搜索番号 htmlcode = get_html('https://javdb.com/search?q=' + number + '&f=all').replace(u'\xa0', u' ') + if str(htmlcode) == 'ProxyError': + raise TimeoutError html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() counts = len(html.xpath( '//div[@id=\'videos\']/div[@class=\'grid columns\']/div[@class=\'grid-item column\']')) if counts == 0: - dic = { - 'title': '', - 'actor': '', - 'website': '', - } - js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, - separators=(',', ':'), ) # .encode('UTF-8') - return js + raise Exception('Movie Data not found in javdb.main_us!') + # ========================================================================遍历搜索结果,找到需要的番号所在URL number_series = number.split('.')[0] number_date = '20' + number.replace(number_series, '').strip('.') number_date = number_date.replace('.', '-') @@ -240,60 +251,66 @@ def main_us(number): if re.search('\d{4}-\d{1,2}-\d{1,2}', date_get): date_get = re.findall('\d{4}-\d{1,2}-\d{1,2}', date_get)[0] series_get = series_get.replace(' ', '') - if (series_get.upper() == number_series.upper() or series_get.replace('-', '').upper() == number_series.upper()) and number_date == date_get: + if (series_get.upper() == number_series.upper() or series_get.replace('-', + '').upper() == number_series.upper()) and number_date == date_get: movie_found = 1 break + if movie_found == 0: + raise Exception('Movie Data not found in javdb.main_us!') result_url = 'https://javdb.com' + html.xpath('//*[@id="videos"]/div/div/a/@href')[count - 1] + # ========================================================================请求、判断结果 html_info = get_html(result_url).replace(u'\xa0', u' ') + if str(html_info) == 'ProxyError': + raise TimeoutError + # ========================================================================收集信息 actor = getActor(html_info) number = getNumber(html_info) - if movie_found == 1: - dic = { - 'actor': str(actor).strip(" [',']").replace('\'', ''), - 'title': getTitle(html_info).replace('中文字幕', '').replace("\\n", '').replace('_', '-').replace(number, '').strip(), - 'studio': getStudio(html_info), - 'publisher': getPublisher(html_info), - 'outline': getOutline(html_info).replace('\n', ''), - 'runtime': getRuntime(html_info).replace(' 分鍾', ''), - 'director': getDirector(html_info), - 'release': getRelease(html_info), - 'number': number, - 'cover': getCover(html_info), - 'cover_small': getCover_small(htmlcode, count - 1), - 'imagecut': 3, - 'tag': getTag(html_info), - 'series': getSeries(html_info), - 'year': getYear(getRelease(html_info)), # str(re.search('\d{4}',getRelease(htmlcode)).group()), - 'actor_photo': getActorPhoto(actor), - 'website': result_url, - 'source': 'javdb.py', - } - else: # 未找到番号 - dic = { - 'title': '', - 'actor': str(actor).strip(" [',']").replace('\'', ''), - 'website': '', - } - except: # actor 用于判断ip是否被封 - if htmlcode == 'ProxyError': - dic = { - 'title': '', - 'actor': '', - 'website': 'timeout', - } - else: - dic = { - 'title': '', - 'actor': '', - 'website': '', - } + dic = { + 'actor': str(actor).strip(" [',']").replace('\'', ''), + 'title': getTitle(html_info).replace('中文字幕', '').replace("\\n", '').replace('_', '-').replace(number, + '').strip(), + 'studio': getStudio(html_info), + 'publisher': getPublisher(html_info), + 'outline': '', + 'score': getScore(html_info), + 'runtime': getRuntime(html_info).replace(' 分鍾', ''), + 'director': getDirector(html_info), + 'release': getRelease(html_info), + 'number': number, + 'cover': getCover(html_info), + 'cover_small': getCover_small(htmlcode, count - 1), + 'imagecut': 3, + 'tag': getTag(html_info), + 'series': getSeries(html_info), + 'year': getYear(getRelease(html_info)), # str(re.search('\d{4}',getRelease(htmlcode)).group()), + 'actor_photo': getActorPhoto(actor), + 'website': result_url, + 'source': 'javdb.py', + } + except TimeoutError: + dic = { + 'title': '', + 'website': 'timeout', + } + except Exception as error_info: + print('Error in javdb.main_us : ' + str(error_info)) + dic = { + 'title': '', + 'website': '', + } js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'), ) # .encode('UTF-8') return js -# print(main('LUXU-1217')) -# input("[+][+]Press enter key exit, you can check the error messge before you exit.\n[+][+]按回车键结束,你可以在结束之前查看和错误信息。") -# print(main('abs-141')) -# print(main('HYSD-00083')) -# print(main_us('x-art.19.11.03')) -# print(main('n1403')) +''' +print(main('abs-141')) +print(main('HYSD-00083')) +print(main('IESP-660')) +print(main('n1403')) +print(main('GANA-1910')) +print(main('heyzo-1031')) +print(main_us('x-art.19.11.03')) +print(main('032020-001')) +print(main('S2M-055')) +print(main('LUXU-1217')) +''' diff --git a/Getter/mgstage.py b/Getter/mgstage.py index 43b5b592f..c408ca489 100644 --- a/Getter/mgstage.py +++ b/Getter/mgstage.py @@ -1,28 +1,26 @@ import re from lxml import etree import json -from bs4 import BeautifulSoup from Function.getHtml import get_html -def getTitle(a): +def getTitle(htmlcode): try: - html = etree.fromstring(a, etree.HTMLParser()) + html = etree.fromstring(htmlcode, etree.HTMLParser()) result = str(html.xpath('//*[@id="center_column"]/div[1]/h1/text()')).strip(" ['']") return result.replace('/', ',') except: return '' -def getActor(a): # //*[@id="center_column"]/div[2]/div[1]/div/table/tbody/tr[1]/td/text() - html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//th[contains(text(),"出演:")]/../td/a/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - result2 = str(html.xpath('//th[contains(text(),"出演:")]/../td/text()')).strip(" ['']").strip('\\n ').strip('\\n') - return str(result1 + result2).strip('+').replace("', '", '').replace('"', '').replace('/', ',') +def getActor(htmlcode): + html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() + result1 = str(html.xpath('//th[contains(text(),"出演")]/../td/a/text()')).strip(" ['']") + result2 = str(html.xpath('//th[contains(text(),"出演")]/../td/text()')).strip(" ['']") + return str(result1 + result2).replace('/', ',').replace('\'', '').replace(' ', '').replace('\\n', '') -def getActorPhoto(actor): # //*[@id="star_qdt"]/li/a/img +def getActorPhoto(actor): d = {} for i in actor: if ',' not in i or ')' in i: @@ -31,49 +29,39 @@ def getActorPhoto(actor): # //*[@id="star_qdt"]/li/a/img return d -def getStudio(a): - html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//th[contains(text(),"メーカー:")]/../td/a/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - result2 = str(html.xpath('//th[contains(text(),"メーカー:")]/../td/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - return str(result1 + result2).strip('+').replace("', '", '').replace('"', '') +def getStudio(htmlcode): + html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() + result1 = str(html.xpath('//th[contains(text(),"メーカー:")]/../td/a/text()')).strip(" ['']") + result2 = str(html.xpath('//th[contains(text(),"メーカー:")]/../td/text()')).strip(" ['']") + return str(result1 + result2).replace('\'', '').replace(' ', '').replace('\\n', '') -def getPublisher(a): - html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//th[contains(text(),"レーベル:")]/../td/a/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - result2 = str(html.xpath('//th[contains(text(),"レーベル:")]/../td/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - return str(result1 + result2).strip('+').replace("', '", '').replace('"', '') +def getPublisher(htmlcode): + html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() + result1 = str(html.xpath('//th[contains(text(),"レーベル:")]/../td/a/text()')).strip(" ['']") + result2 = str(html.xpath('//th[contains(text(),"レーベル:")]/../td/text()')).strip(" ['']") + return str(result1 + result2).replace('\'', '').replace(' ', '').replace('\\n', '') -def getRuntime(a): - html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//th[contains(text(),"収録時間:")]/../td/a/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - result2 = str(html.xpath('//th[contains(text(),"収録時間:")]/../td/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - return str(result1 + result2).strip('+').rstrip('mi') +def getRuntime(htmlcode): + html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() + result1 = str(html.xpath('//th[contains(text(),"収録時間:")]/../td/a/text()')).strip(" ['']") + result2 = str(html.xpath('//th[contains(text(),"収録時間:")]/../td/text()')).strip(" ['']") + return str(result1 + result2).rstrip('min').replace('\'', '').replace(' ', '').replace('\\n', '') -def getSeries(a): - html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//th[contains(text(),"シリーズ:")]/../td/a/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - result2 = str(html.xpath('//th[contains(text(),"シリーズ:")]/../td/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - return str(result1 + result2).strip('+').replace("', '", '').replace('"', '') +def getSeries(htmlcode): + html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() + result1 = str(html.xpath('//th[contains(text(),"シリーズ:")]/../td/a/text()')).strip(" ['']") + result2 = str(html.xpath('//th[contains(text(),"シリーズ:")]/../td/text()')).strip(" ['']") + return str(result1 + result2).replace('\'', '').replace(' ', '').replace('\\n', '') -def getNum(a): - html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//th[contains(text(),"品番:")]/../td/a/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - result2 = str(html.xpath('//th[contains(text(),"品番:")]/../td/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - return str(result1 + result2).strip('+') +def getNum(htmlcode): + html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() + result1 = str(html.xpath('//th[contains(text(),"品番:")]/../td/a/text()')).strip(" ['']") + result2 = str(html.xpath('//th[contains(text(),"品番:")]/../td/text()')).strip(" ['']") + return str(result1 + result2).replace('\'', '').replace(' ', '').replace('\\n', '') def getYear(getRelease): @@ -84,28 +72,23 @@ def getYear(getRelease): return getRelease -def getRelease(a): - html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//th[contains(text(),"配信開始日:")]/../td/a/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - result2 = str(html.xpath('//th[contains(text(),"配信開始日:")]/../td/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - return str(result1 + result2).strip('+') +def getRelease(htmlcode): + html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() + result1 = str(html.xpath('//th[contains(text(),"配信開始日:")]/../td/a/text()')).strip(" ['']") + result2 = str(html.xpath('//th[contains(text(),"配信開始日:")]/../td/text()')).strip(" ['']") + return str(result1 + result2).replace('\'', '').replace(' ', '').replace('\\n', '') -def getTag(a): - html = etree.fromstring(a, etree.HTMLParser()) # //table/tr[1]/td[1]/text() - result1 = str(html.xpath('//th[contains(text(),"ジャンル:")]/../td/a/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - result2 = str(html.xpath('//th[contains(text(),"ジャンル:")]/../td/text()')).strip(" ['']").strip('\\n ').strip( - '\\n') - return str(result1 + result2).strip('+').replace("', '\\n", ",").replace("', '", "").replace('"', '') +def getTag(htmlcode): + html = etree.fromstring(htmlcode, etree.HTMLParser()) # //table/tr[1]/td[1]/text() + result1 = str(html.xpath('//th[contains(text(),"ジャンル:")]/../td/a/text()')).strip(" ['']") + result2 = str(html.xpath('//th[contains(text(),"ジャンル:")]/../td/text()')).strip(" ['']") + return str(result1 + result2).replace('\'', '').replace(' ', '').replace('\\n', '') def getCover(htmlcode): html = etree.fromstring(htmlcode, etree.HTMLParser()) result = str(html.xpath('//*[@id="center_column"]/div[1]/div[1]/div/div/h2/img/@src')).strip(" ['']") - # /html/body/div[2]/article[2]/div[1]/div[1]/div/div/h2/img/@src return result @@ -115,49 +98,54 @@ def getOutline(htmlcode): return result +def getScore(htmlcode): + return str(re.findall(r'5点満点中 (\S+)点', htmlcode)).strip(" ['']") + + def main(number): - number = number.upper() - htmlcode = str( - get_html('https://www.mgstage.com/product/product_detail/' + str(number) + '/', cookies={'adc': '1'})) - soup = BeautifulSoup(htmlcode, 'lxml') - a = str(soup.find(attrs={'class': 'detail_data'})).replace('\n ', - '').replace(' ', - '').replace('\n ', - '').replace( - '\n ', '') try: - actor = getActor(a).replace(' ', '') + number = number.upper() + htmlcode = str( + get_html('https://www.mgstage.com/product/product_detail/' + str(number) + '/', cookies={'adc': '1'})) + htmlcode = htmlcode.replace('ahref', 'a href') # 针对a标签、属性中间未分开 + if str(htmlcode) == 'ProxyError': + raise TimeoutError + actor = getActor(htmlcode).replace(' ', '') dic = { 'title': getTitle(htmlcode).replace("\\n", '').replace(' ', ''), - 'studio': getStudio(a), - 'publisher': getPublisher(a), + 'studio': getStudio(htmlcode), + 'publisher': getPublisher(htmlcode), 'outline': getOutline(htmlcode).replace('\n', ''), - 'runtime': getRuntime(a), - 'director': '', + 'score': getScore(htmlcode), + 'runtime': getRuntime(htmlcode), 'actor': actor, - 'release': getRelease(a), - 'number': getNum(a), + 'release': getRelease(htmlcode), + 'number': getNum(htmlcode), 'cover': getCover(htmlcode), 'imagecut': 0, - 'tag': getTag(a).strip(','), - 'series': getSeries(a).strip(','), - 'year': getYear(getRelease(a)), # str(re.search('\d{4}',getRelease(a)).group()), + 'tag': getTag(htmlcode).strip(','), + 'series': getSeries(htmlcode).strip(','), + 'year': getYear(getRelease(htmlcode)), 'actor_photo': getActorPhoto(actor.split(',')), + 'director': '', 'website': 'https://www.mgstage.com/product/product_detail/' + str(number) + '/', 'source': 'mgstage.py', } - except: - if htmlcode == 'ProxyError': - dic = { - 'title': '', - 'website': 'timeout', - } - else: - dic = { - 'title': '', - 'website': '', - } + except TimeoutError: + dic = { + 'title': '', + 'website': 'timeout', + } + except Exception as error_info: + print('Error in mgstage.main : ' + str(error_info)) + dic = { + 'title': '', + 'website': '', + } js = json.dumps(dic, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'), ) # .encode('UTF-8') return js - -# print(main('300MIUM-382')) +''' +print(main('200GANA-2240')) +print(main('SIRO-4042')) +print(main('300MIUM-382')) +''' diff --git a/Ui/AVDC-ico.png b/Img/AVDC-ico.png similarity index 100% rename from Ui/AVDC-ico.png rename to Img/AVDC-ico.png diff --git a/Img/AVDC.ico b/Img/AVDC.ico new file mode 100644 index 000000000..6decf924c Binary files /dev/null and b/Img/AVDC.ico differ diff --git a/Img/LEAK.png b/Img/LEAK.png new file mode 100644 index 000000000..5f6822528 Binary files /dev/null and b/Img/LEAK.png differ diff --git a/Img/SUB.png b/Img/SUB.png new file mode 100644 index 000000000..1b06f2862 Binary files /dev/null and b/Img/SUB.png differ diff --git a/Img/UNCENSORED.png b/Img/UNCENSORED.png new file mode 100644 index 000000000..094e4245e Binary files /dev/null and b/Img/UNCENSORED.png differ diff --git a/Ui/AVDC.py b/Ui/AVDC.py index 53377eb18..a59027f76 100644 --- a/Ui/AVDC.py +++ b/Ui/AVDC.py @@ -64,12 +64,12 @@ def setupUi(self, AVDV): self.gridLayout.setContentsMargins(0, 0, 0, 0) self.gridLayout.setHorizontalSpacing(7) self.gridLayout.setObjectName("gridLayout") - self.label_fanart = QtWidgets.QLabel(self.gridLayoutWidget) - self.label_fanart.setEnabled(True) - self.label_fanart.setFrameShape(QtWidgets.QFrame.Box) - self.label_fanart.setAlignment(QtCore.Qt.AlignCenter) - self.label_fanart.setObjectName("label_fanart") - self.gridLayout.addWidget(self.label_fanart, 0, 0, 1, 1) + self.label_thumb = QtWidgets.QLabel(self.gridLayoutWidget) + self.label_thumb.setEnabled(True) + self.label_thumb.setFrameShape(QtWidgets.QFrame.Box) + self.label_thumb.setAlignment(QtCore.Qt.AlignCenter) + self.label_thumb.setObjectName("label_thumb") + self.gridLayout.addWidget(self.label_thumb, 0, 0, 1, 1) self.line = QtWidgets.QFrame(self.page_avdc) self.line.setGeometry(QtCore.QRect(0, 50, 791, 20)) self.line.setFrameShape(QtWidgets.QFrame.HLine) @@ -208,6 +208,7 @@ def setupUi(self, AVDV): self.comboBox_website.addItem("") self.comboBox_website.addItem("") self.comboBox_website.addItem("") + self.comboBox_website.addItem("") self.label_2 = QtWidgets.QLabel(self.groupBox_7) self.label_2.setGeometry(QtCore.QRect(230, 30, 72, 21)) self.label_2.setObjectName("label_2") @@ -245,9 +246,9 @@ def setupUi(self, AVDV): self.groupBox_13 = QtWidgets.QGroupBox(self.page_tool) self.groupBox_13.setGeometry(QtCore.QRect(10, 470, 751, 111)) self.groupBox_13.setObjectName("groupBox_13") - self.pushButton_select_fanart = QtWidgets.QPushButton(self.groupBox_13) - self.pushButton_select_fanart.setGeometry(QtCore.QRect(10, 20, 201, 71)) - self.pushButton_select_fanart.setObjectName("pushButton_select_fanart") + self.pushButton_select_thumb = QtWidgets.QPushButton(self.groupBox_13) + self.pushButton_select_thumb.setGeometry(QtCore.QRect(10, 20, 201, 71)) + self.pushButton_select_thumb.setObjectName("pushButton_select_thumb") self.label_6 = QtWidgets.QLabel(self.groupBox_13) self.label_6.setGeometry(QtCore.QRect(230, 20, 511, 71)) self.label_6.setObjectName("label_6") @@ -263,26 +264,8 @@ def setupUi(self, AVDV): self.tab = QtWidgets.QWidget() self.tab.setObjectName("tab") self.groupBox_10 = QtWidgets.QGroupBox(self.tab) - self.groupBox_10.setGeometry(QtCore.QRect(10, 10, 761, 421)) + self.groupBox_10.setGeometry(QtCore.QRect(10, 10, 761, 351)) self.groupBox_10.setObjectName("groupBox_10") - self.formLayoutWidget_3 = QtWidgets.QWidget(self.groupBox_10) - self.formLayoutWidget_3.setGeometry(QtCore.QRect(0, 350, 751, 61)) - self.formLayoutWidget_3.setObjectName("formLayoutWidget_3") - self.formLayout = QtWidgets.QFormLayout(self.formLayoutWidget_3) - self.formLayout.setContentsMargins(0, 0, 0, 0) - self.formLayout.setObjectName("formLayout") - self.label_38 = QtWidgets.QLabel(self.formLayoutWidget_3) - self.label_38.setObjectName("label_38") - self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_38) - self.lineEdit_escape_char = QtWidgets.QLineEdit(self.formLayoutWidget_3) - self.lineEdit_escape_char.setObjectName("lineEdit_escape_char") - self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.lineEdit_escape_char) - self.label_39 = QtWidgets.QLabel(self.formLayoutWidget_3) - self.label_39.setObjectName("label_39") - self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_39) - self.lineEdit_escape_string = QtWidgets.QLineEdit(self.formLayoutWidget_3) - self.lineEdit_escape_string.setObjectName("lineEdit_escape_string") - self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.lineEdit_escape_string) self.verticalLayoutWidget_2 = QtWidgets.QWidget(self.groupBox_10) self.verticalLayoutWidget_2.setGeometry(QtCore.QRect(10, 20, 741, 321)) self.verticalLayoutWidget_2.setObjectName("verticalLayoutWidget_2") @@ -291,74 +274,99 @@ def setupUi(self, AVDV): self.verticalLayout_3.setObjectName("verticalLayout_3") self.groupBox = QtWidgets.QGroupBox(self.verticalLayoutWidget_2) self.groupBox.setObjectName("groupBox") - self.radioButton_common = QtWidgets.QRadioButton(self.groupBox) - self.radioButton_common.setGeometry(QtCore.QRect(200, 10, 181, 19)) + self.horizontalLayoutWidget_7 = QtWidgets.QWidget(self.groupBox) + self.horizontalLayoutWidget_7.setGeometry(QtCore.QRect(140, 10, 591, 31)) + self.horizontalLayoutWidget_7.setObjectName("horizontalLayoutWidget_7") + self.horizontalLayout_9 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_7) + self.horizontalLayout_9.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_9.setObjectName("horizontalLayout_9") + self.radioButton_common = QtWidgets.QRadioButton(self.horizontalLayoutWidget_7) self.radioButton_common.setObjectName("radioButton_common") - self.radioButton_sort = QtWidgets.QRadioButton(self.groupBox) - self.radioButton_sort.setGeometry(QtCore.QRect(510, 10, 181, 19)) + self.horizontalLayout_9.addWidget(self.radioButton_common) + self.radioButton_sort = QtWidgets.QRadioButton(self.horizontalLayoutWidget_7) self.radioButton_sort.setObjectName("radioButton_sort") + self.horizontalLayout_9.addWidget(self.radioButton_sort) self.verticalLayout_3.addWidget(self.groupBox) self.groupBox_2 = QtWidgets.QGroupBox(self.verticalLayoutWidget_2) self.groupBox_2.setObjectName("groupBox_2") - self.radioButton_soft_on = QtWidgets.QRadioButton(self.groupBox_2) - self.radioButton_soft_on.setGeometry(QtCore.QRect(200, 10, 181, 19)) + self.horizontalLayoutWidget_8 = QtWidgets.QWidget(self.groupBox_2) + self.horizontalLayoutWidget_8.setGeometry(QtCore.QRect(140, 10, 591, 31)) + self.horizontalLayoutWidget_8.setObjectName("horizontalLayoutWidget_8") + self.horizontalLayout_10 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_8) + self.horizontalLayout_10.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_10.setObjectName("horizontalLayout_10") + self.radioButton_soft_on = QtWidgets.QRadioButton(self.horizontalLayoutWidget_8) self.radioButton_soft_on.setObjectName("radioButton_soft_on") - self.radioButton_soft_off = QtWidgets.QRadioButton(self.groupBox_2) - self.radioButton_soft_off.setGeometry(QtCore.QRect(510, 10, 181, 19)) + self.horizontalLayout_10.addWidget(self.radioButton_soft_on) + self.radioButton_soft_off = QtWidgets.QRadioButton(self.horizontalLayoutWidget_8) self.radioButton_soft_off.setObjectName("radioButton_soft_off") + self.horizontalLayout_10.addWidget(self.radioButton_soft_off) self.verticalLayout_3.addWidget(self.groupBox_2) self.groupBox_3 = QtWidgets.QGroupBox(self.verticalLayoutWidget_2) self.groupBox_3.setObjectName("groupBox_3") - self.radioButton_debug_on = QtWidgets.QRadioButton(self.groupBox_3) - self.radioButton_debug_on.setGeometry(QtCore.QRect(200, 10, 181, 19)) + self.horizontalLayoutWidget_9 = QtWidgets.QWidget(self.groupBox_3) + self.horizontalLayoutWidget_9.setGeometry(QtCore.QRect(140, 10, 591, 31)) + self.horizontalLayoutWidget_9.setObjectName("horizontalLayoutWidget_9") + self.horizontalLayout_11 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_9) + self.horizontalLayout_11.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_11.setObjectName("horizontalLayout_11") + self.radioButton_debug_on = QtWidgets.QRadioButton(self.horizontalLayoutWidget_9) self.radioButton_debug_on.setObjectName("radioButton_debug_on") - self.radioButton_debug_off = QtWidgets.QRadioButton(self.groupBox_3) - self.radioButton_debug_off.setGeometry(QtCore.QRect(510, 10, 181, 19)) + self.horizontalLayout_11.addWidget(self.radioButton_debug_on) + self.radioButton_debug_off = QtWidgets.QRadioButton(self.horizontalLayoutWidget_9) self.radioButton_debug_off.setObjectName("radioButton_debug_off") + self.horizontalLayout_11.addWidget(self.radioButton_debug_off) self.verticalLayout_3.addWidget(self.groupBox_3) self.groupBox_4 = QtWidgets.QGroupBox(self.verticalLayoutWidget_2) self.groupBox_4.setObjectName("groupBox_4") - self.radioButton_update_on = QtWidgets.QRadioButton(self.groupBox_4) - self.radioButton_update_on.setGeometry(QtCore.QRect(200, 10, 181, 19)) + self.horizontalLayoutWidget_10 = QtWidgets.QWidget(self.groupBox_4) + self.horizontalLayoutWidget_10.setGeometry(QtCore.QRect(140, 10, 591, 31)) + self.horizontalLayoutWidget_10.setObjectName("horizontalLayoutWidget_10") + self.horizontalLayout_12 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_10) + self.horizontalLayout_12.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_12.setObjectName("horizontalLayout_12") + self.radioButton_update_on = QtWidgets.QRadioButton(self.horizontalLayoutWidget_10) self.radioButton_update_on.setObjectName("radioButton_update_on") - self.radioButton_update_off = QtWidgets.QRadioButton(self.groupBox_4) - self.radioButton_update_off.setGeometry(QtCore.QRect(510, 10, 181, 19)) + self.horizontalLayout_12.addWidget(self.radioButton_update_on) + self.radioButton_update_off = QtWidgets.QRadioButton(self.horizontalLayoutWidget_10) self.radioButton_update_off.setObjectName("radioButton_update_off") + self.horizontalLayout_12.addWidget(self.radioButton_update_off) self.verticalLayout_3.addWidget(self.groupBox_4) self.groupBox_17 = QtWidgets.QGroupBox(self.verticalLayoutWidget_2) self.groupBox_17.setObjectName("groupBox_17") - self.radioButton_log_on = QtWidgets.QRadioButton(self.groupBox_17) - self.radioButton_log_on.setGeometry(QtCore.QRect(200, 10, 181, 19)) + self.horizontalLayoutWidget_11 = QtWidgets.QWidget(self.groupBox_17) + self.horizontalLayoutWidget_11.setGeometry(QtCore.QRect(140, 10, 591, 31)) + self.horizontalLayoutWidget_11.setObjectName("horizontalLayoutWidget_11") + self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_11) + self.horizontalLayout_13.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_13.setObjectName("horizontalLayout_13") + self.radioButton_log_on = QtWidgets.QRadioButton(self.horizontalLayoutWidget_11) self.radioButton_log_on.setObjectName("radioButton_log_on") - self.radioButton_log_off = QtWidgets.QRadioButton(self.groupBox_17) - self.radioButton_log_off.setGeometry(QtCore.QRect(510, 10, 81, 19)) + self.horizontalLayout_13.addWidget(self.radioButton_log_on) + self.radioButton_log_off = QtWidgets.QRadioButton(self.horizontalLayoutWidget_11) self.radioButton_log_off.setObjectName("radioButton_log_off") + self.horizontalLayout_13.addWidget(self.radioButton_log_off) self.verticalLayout_3.addWidget(self.groupBox_17) self.groupBox_15 = QtWidgets.QGroupBox(self.verticalLayoutWidget_2) self.groupBox_15.setObjectName("groupBox_15") - self.radioButton_fail_move_on = QtWidgets.QRadioButton(self.groupBox_15) - self.radioButton_fail_move_on.setGeometry(QtCore.QRect(200, 10, 181, 19)) + self.horizontalLayoutWidget_12 = QtWidgets.QWidget(self.groupBox_15) + self.horizontalLayoutWidget_12.setGeometry(QtCore.QRect(140, 10, 591, 31)) + self.horizontalLayoutWidget_12.setObjectName("horizontalLayoutWidget_12") + self.horizontalLayout_14 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_12) + self.horizontalLayout_14.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_14.setObjectName("horizontalLayout_14") + self.radioButton_fail_move_on = QtWidgets.QRadioButton(self.horizontalLayoutWidget_12) self.radioButton_fail_move_on.setObjectName("radioButton_fail_move_on") - self.radioButton_fail_move_off = QtWidgets.QRadioButton(self.groupBox_15) - self.radioButton_fail_move_off.setGeometry(QtCore.QRect(510, 10, 81, 19)) + self.horizontalLayout_14.addWidget(self.radioButton_fail_move_on) + self.radioButton_fail_move_off = QtWidgets.QRadioButton(self.horizontalLayoutWidget_12) self.radioButton_fail_move_off.setObjectName("radioButton_fail_move_off") + self.horizontalLayout_14.addWidget(self.radioButton_fail_move_off) self.verticalLayout_3.addWidget(self.groupBox_15) - self.groupBox_5 = QtWidgets.QGroupBox(self.verticalLayoutWidget_2) - self.groupBox_5.setObjectName("groupBox_5") - self.radioButton_emby = QtWidgets.QRadioButton(self.groupBox_5) - self.radioButton_emby.setGeometry(QtCore.QRect(200, 10, 181, 19)) - self.radioButton_emby.setObjectName("radioButton_emby") - self.radioButton_plex = QtWidgets.QRadioButton(self.groupBox_5) - self.radioButton_plex.setGeometry(QtCore.QRect(450, 10, 81, 19)) - self.radioButton_plex.setObjectName("radioButton_plex") - self.radioButton_kodi = QtWidgets.QRadioButton(self.groupBox_5) - self.radioButton_kodi.setGeometry(QtCore.QRect(630, 10, 81, 19)) - self.radioButton_kodi.setObjectName("radioButton_kodi") - self.verticalLayout_3.addWidget(self.groupBox_5) - self.groupBox_11 = QtWidgets.QGroupBox(self.verticalLayoutWidget_2) + self.groupBox_11 = QtWidgets.QGroupBox(self.tab) + self.groupBox_11.setGeometry(QtCore.QRect(10, 370, 761, 61)) self.groupBox_11.setObjectName("groupBox_11") self.comboBox_website_all = QtWidgets.QComboBox(self.groupBox_11) - self.comboBox_website_all.setGeometry(QtCore.QRect(200, 10, 481, 21)) + self.comboBox_website_all.setGeometry(QtCore.QRect(150, 20, 591, 21)) self.comboBox_website_all.setObjectName("comboBox_website_all") self.comboBox_website_all.addItem("") self.comboBox_website_all.addItem("") @@ -367,7 +375,7 @@ def setupUi(self, AVDV): self.comboBox_website_all.addItem("") self.comboBox_website_all.addItem("") self.comboBox_website_all.addItem("") - self.verticalLayout_3.addWidget(self.groupBox_11) + self.comboBox_website_all.addItem("") self.tabWidget.addTab(self.tab, "") self.tab_2 = QtWidgets.QWidget() self.tab_2.setObjectName("tab_2") @@ -413,12 +421,18 @@ def setupUi(self, AVDV): self.lineEdit_movie_path = QtWidgets.QLineEdit(self.formLayoutWidget_5) self.lineEdit_movie_path.setObjectName("lineEdit_movie_path") self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.lineEdit_movie_path) - self.label_48 = QtWidgets.QLabel(self.formLayoutWidget_5) - self.label_48.setObjectName("label_48") - self.formLayout_2.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_48) - self.lineEdit_escape_dir = QtWidgets.QLineEdit(self.formLayoutWidget_5) - self.lineEdit_escape_dir.setObjectName("lineEdit_escape_dir") - self.formLayout_2.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.lineEdit_escape_dir) + self.label_40 = QtWidgets.QLabel(self.formLayoutWidget_5) + self.label_40.setObjectName("label_40") + self.formLayout_2.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_40) + self.lineEdit_movie_type = QtWidgets.QLineEdit(self.formLayoutWidget_5) + self.lineEdit_movie_type.setObjectName("lineEdit_movie_type") + self.formLayout_2.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.lineEdit_movie_type) + self.label_42 = QtWidgets.QLabel(self.formLayoutWidget_5) + self.label_42.setObjectName("label_42") + self.formLayout_2.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_42) + self.lineEdit_sub_type = QtWidgets.QLineEdit(self.formLayoutWidget_5) + self.lineEdit_sub_type.setObjectName("lineEdit_sub_type") + self.formLayout_2.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.lineEdit_sub_type) self.label_46 = QtWidgets.QLabel(self.formLayoutWidget_5) self.label_46.setObjectName("label_46") self.formLayout_2.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_46) @@ -432,22 +446,112 @@ def setupUi(self, AVDV): self.lineEdit_success = QtWidgets.QLineEdit(self.formLayoutWidget_5) self.lineEdit_success.setObjectName("lineEdit_success") self.formLayout_2.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.lineEdit_success) - self.label_40 = QtWidgets.QLabel(self.formLayoutWidget_5) - self.label_40.setObjectName("label_40") - self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_40) - self.lineEdit_movie_type = QtWidgets.QLineEdit(self.formLayoutWidget_5) - self.lineEdit_movie_type.setObjectName("lineEdit_movie_type") - self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.lineEdit_movie_type) - self.label_42 = QtWidgets.QLabel(self.formLayoutWidget_5) - self.label_42.setObjectName("label_42") - self.formLayout_2.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_42) - self.lineEdit_sub_type = QtWidgets.QLineEdit(self.formLayoutWidget_5) - self.lineEdit_sub_type.setObjectName("lineEdit_sub_type") - self.formLayout_2.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.lineEdit_sub_type) + self.label_48 = QtWidgets.QLabel(self.formLayoutWidget_5) + self.label_48.setObjectName("label_48") + self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_48) + self.lineEdit_escape_dir = QtWidgets.QLineEdit(self.formLayoutWidget_5) + self.lineEdit_escape_dir.setObjectName("lineEdit_escape_dir") + self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.lineEdit_escape_dir) self.label_7 = QtWidgets.QLabel(self.groupBox_16) self.label_7.setGeometry(QtCore.QRect(10, 210, 731, 61)) self.label_7.setObjectName("label_7") self.tabWidget.addTab(self.tab_2, "") + self.tab_4 = QtWidgets.QWidget() + self.tab_4.setObjectName("tab_4") + self.groupBox_14 = QtWidgets.QGroupBox(self.tab_4) + self.groupBox_14.setGeometry(QtCore.QRect(10, 150, 761, 71)) + self.groupBox_14.setObjectName("groupBox_14") + self.horizontalLayoutWidget_3 = QtWidgets.QWidget(self.groupBox_14) + self.horizontalLayoutWidget_3.setGeometry(QtCore.QRect(150, 30, 601, 31)) + self.horizontalLayoutWidget_3.setObjectName("horizontalLayoutWidget_3") + self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_3) + self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.checkBox_sub = QtWidgets.QCheckBox(self.horizontalLayoutWidget_3) + self.checkBox_sub.setObjectName("checkBox_sub") + self.horizontalLayout_5.addWidget(self.checkBox_sub) + self.checkBox_leak = QtWidgets.QCheckBox(self.horizontalLayoutWidget_3) + self.checkBox_leak.setObjectName("checkBox_leak") + self.horizontalLayout_5.addWidget(self.checkBox_leak) + self.checkBox_uncensored = QtWidgets.QCheckBox(self.horizontalLayoutWidget_3) + self.checkBox_uncensored.setObjectName("checkBox_uncensored") + self.horizontalLayout_5.addWidget(self.checkBox_uncensored) + self.groupBox_19 = QtWidgets.QGroupBox(self.tab_4) + self.groupBox_19.setGeometry(QtCore.QRect(10, 240, 761, 71)) + self.groupBox_19.setObjectName("groupBox_19") + self.horizontalLayoutWidget_2 = QtWidgets.QWidget(self.groupBox_19) + self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(150, 30, 601, 31)) + self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2) + self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.radioButton_top_left = QtWidgets.QRadioButton(self.horizontalLayoutWidget_2) + self.radioButton_top_left.setObjectName("radioButton_top_left") + self.horizontalLayout_4.addWidget(self.radioButton_top_left) + self.radioButton_bottom_left = QtWidgets.QRadioButton(self.horizontalLayoutWidget_2) + self.radioButton_bottom_left.setObjectName("radioButton_bottom_left") + self.horizontalLayout_4.addWidget(self.radioButton_bottom_left) + self.radioButton_top_right = QtWidgets.QRadioButton(self.horizontalLayoutWidget_2) + self.radioButton_top_right.setObjectName("radioButton_top_right") + self.horizontalLayout_4.addWidget(self.radioButton_top_right) + self.radioButton_bottom_right = QtWidgets.QRadioButton(self.horizontalLayoutWidget_2) + self.radioButton_bottom_right.setObjectName("radioButton_bottom_right") + self.horizontalLayout_4.addWidget(self.radioButton_bottom_right) + self.groupBox_21 = QtWidgets.QGroupBox(self.tab_4) + self.groupBox_21.setGeometry(QtCore.QRect(10, 330, 761, 81)) + self.groupBox_21.setObjectName("groupBox_21") + self.horizontalLayoutWidget_4 = QtWidgets.QWidget(self.groupBox_21) + self.horizontalLayoutWidget_4.setGeometry(QtCore.QRect(40, 30, 711, 41)) + self.horizontalLayoutWidget_4.setObjectName("horizontalLayoutWidget_4") + self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_4) + self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_6.setObjectName("horizontalLayout_6") + self.horizontalSlider_mark_size = QtWidgets.QSlider(self.horizontalLayoutWidget_4) + self.horizontalSlider_mark_size.setMinimum(1) + self.horizontalSlider_mark_size.setMaximum(5) + self.horizontalSlider_mark_size.setPageStep(1) + self.horizontalSlider_mark_size.setProperty("value", 3) + self.horizontalSlider_mark_size.setOrientation(QtCore.Qt.Horizontal) + self.horizontalSlider_mark_size.setObjectName("horizontalSlider_mark_size") + self.horizontalLayout_6.addWidget(self.horizontalSlider_mark_size) + self.lcdNumber_mark_size = QtWidgets.QLCDNumber(self.horizontalLayoutWidget_4) + self.lcdNumber_mark_size.setProperty("intValue", 3) + self.lcdNumber_mark_size.setObjectName("lcdNumber_mark_size") + self.horizontalLayout_6.addWidget(self.lcdNumber_mark_size) + self.groupBox_20 = QtWidgets.QGroupBox(self.tab_4) + self.groupBox_20.setGeometry(QtCore.QRect(10, 10, 761, 51)) + self.groupBox_20.setObjectName("groupBox_20") + self.horizontalLayoutWidget_5 = QtWidgets.QWidget(self.groupBox_20) + self.horizontalLayoutWidget_5.setGeometry(QtCore.QRect(150, 20, 601, 31)) + self.horizontalLayoutWidget_5.setObjectName("horizontalLayoutWidget_5") + self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_5) + self.horizontalLayout_7.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_7.setObjectName("horizontalLayout_7") + self.radioButton_poster_mark_on = QtWidgets.QRadioButton(self.horizontalLayoutWidget_5) + self.radioButton_poster_mark_on.setObjectName("radioButton_poster_mark_on") + self.horizontalLayout_7.addWidget(self.radioButton_poster_mark_on) + self.radioButton_poster_mark_off = QtWidgets.QRadioButton(self.horizontalLayoutWidget_5) + self.radioButton_poster_mark_off.setObjectName("radioButton_poster_mark_off") + self.horizontalLayout_7.addWidget(self.radioButton_poster_mark_off) + self.label_9 = QtWidgets.QLabel(self.tab_4) + self.label_9.setGeometry(QtCore.QRect(20, 430, 701, 61)) + self.label_9.setObjectName("label_9") + self.groupBox_22 = QtWidgets.QGroupBox(self.tab_4) + self.groupBox_22.setGeometry(QtCore.QRect(10, 80, 761, 51)) + self.groupBox_22.setObjectName("groupBox_22") + self.horizontalLayoutWidget_6 = QtWidgets.QWidget(self.groupBox_22) + self.horizontalLayoutWidget_6.setGeometry(QtCore.QRect(150, 20, 601, 31)) + self.horizontalLayoutWidget_6.setObjectName("horizontalLayoutWidget_6") + self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_6) + self.horizontalLayout_8.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_8.setObjectName("horizontalLayout_8") + self.radioButton_thumb_mark_on = QtWidgets.QRadioButton(self.horizontalLayoutWidget_6) + self.radioButton_thumb_mark_on.setObjectName("radioButton_thumb_mark_on") + self.horizontalLayout_8.addWidget(self.radioButton_thumb_mark_on) + self.radioButton_thumb_mark_off = QtWidgets.QRadioButton(self.horizontalLayoutWidget_6) + self.radioButton_thumb_mark_off.setObjectName("radioButton_thumb_mark_off") + self.horizontalLayout_8.addWidget(self.radioButton_thumb_mark_off) + self.tabWidget.addTab(self.tab_4, "") self.tab_3 = QtWidgets.QWidget() self.tab_3.setObjectName("tab_3") self.groupBox_9 = QtWidgets.QGroupBox(self.tab_3) @@ -501,7 +605,67 @@ def setupUi(self, AVDV): self.lcdNumber_retry.setObjectName("lcdNumber_retry") self.horizontalLayout_retry.addWidget(self.lcdNumber_retry) self.formLayout_4.setLayout(2, QtWidgets.QFormLayout.FieldRole, self.horizontalLayout_retry) + self.groupBox_39 = QtWidgets.QGroupBox(self.tab_3) + self.groupBox_39.setGeometry(QtCore.QRect(10, 250, 761, 121)) + self.groupBox_39.setObjectName("groupBox_39") + self.label_14 = QtWidgets.QLabel(self.groupBox_39) + self.label_14.setGeometry(QtCore.QRect(70, 60, 681, 61)) + self.label_14.setObjectName("label_14") + self.horizontalLayoutWidget_24 = QtWidgets.QWidget(self.groupBox_39) + self.horizontalLayoutWidget_24.setGeometry(QtCore.QRect(200, 20, 551, 31)) + self.horizontalLayoutWidget_24.setObjectName("horizontalLayoutWidget_24") + self.horizontalLayout_27 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_24) + self.horizontalLayout_27.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_27.setObjectName("horizontalLayout_27") + self.radioButton_poster_official = QtWidgets.QRadioButton(self.horizontalLayoutWidget_24) + self.radioButton_poster_official.setObjectName("radioButton_poster_official") + self.horizontalLayout_27.addWidget(self.radioButton_poster_official) + self.radioButton_poster_cut = QtWidgets.QRadioButton(self.horizontalLayoutWidget_24) + self.radioButton_poster_cut.setObjectName("radioButton_poster_cut") + self.horizontalLayout_27.addWidget(self.radioButton_poster_cut) + self.groupBox_40 = QtWidgets.QGroupBox(self.tab_3) + self.groupBox_40.setGeometry(QtCore.QRect(10, 380, 761, 111)) + self.groupBox_40.setObjectName("groupBox_40") + self.formLayoutWidget = QtWidgets.QWidget(self.groupBox_40) + self.formLayoutWidget.setGeometry(QtCore.QRect(0, 30, 751, 31)) + self.formLayoutWidget.setObjectName("formLayoutWidget") + self.formLayout_9 = QtWidgets.QFormLayout(self.formLayoutWidget) + self.formLayout_9.setContentsMargins(0, 0, 0, 0) + self.formLayout_9.setObjectName("formLayout_9") + self.label_16 = QtWidgets.QLabel(self.formLayoutWidget) + self.label_16.setObjectName("label_16") + self.formLayout_9.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_16) + self.lineEdit_uncensored_prefix = QtWidgets.QLineEdit(self.formLayoutWidget) + self.lineEdit_uncensored_prefix.setObjectName("lineEdit_uncensored_prefix") + self.formLayout_9.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.lineEdit_uncensored_prefix) + self.label_17 = QtWidgets.QLabel(self.groupBox_40) + self.label_17.setGeometry(QtCore.QRect(70, 70, 671, 31)) + self.label_17.setObjectName("label_17") + self.groupBox_18 = QtWidgets.QGroupBox(self.tab_3) + self.groupBox_18.setGeometry(QtCore.QRect(10, 140, 761, 101)) + self.groupBox_18.setObjectName("groupBox_18") + self.formLayoutWidget_3 = QtWidgets.QWidget(self.groupBox_18) + self.formLayoutWidget_3.setGeometry(QtCore.QRect(0, 30, 751, 61)) + self.formLayoutWidget_3.setObjectName("formLayoutWidget_3") + self.formLayout = QtWidgets.QFormLayout(self.formLayoutWidget_3) + self.formLayout.setContentsMargins(0, 0, 0, 0) + self.formLayout.setObjectName("formLayout") + self.label_38 = QtWidgets.QLabel(self.formLayoutWidget_3) + self.label_38.setObjectName("label_38") + self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_38) + self.lineEdit_escape_char = QtWidgets.QLineEdit(self.formLayoutWidget_3) + self.lineEdit_escape_char.setObjectName("lineEdit_escape_char") + self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.lineEdit_escape_char) + self.label_39 = QtWidgets.QLabel(self.formLayoutWidget_3) + self.label_39.setObjectName("label_39") + self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_39) + self.lineEdit_escape_string = QtWidgets.QLineEdit(self.formLayoutWidget_3) + self.lineEdit_escape_string.setObjectName("lineEdit_escape_string") + self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.lineEdit_escape_string) self.tabWidget.addTab(self.tab_3, "") + self.pushButton_init_config = QtWidgets.QPushButton(self.page_setting) + self.pushButton_init_config.setGeometry(QtCore.QRect(0, 680, 71, 28)) + self.pushButton_init_config.setObjectName("pushButton_init_config") self.stackedWidget.addWidget(self.page_setting) self.page_about = QtWidgets.QWidget() self.page_about.setObjectName("page_about") @@ -570,7 +734,7 @@ def setupUi(self, AVDV): def retranslateUi(self, AVDV): _translate = QtCore.QCoreApplication.translate - AVDV.setWindowTitle(_translate("AVDV", "AVDC-3.92")) + AVDV.setWindowTitle(_translate("AVDV", "AVDC-3.93")) self.pushButton_start_cap.setText(_translate("AVDV", "开始")) self.textBrowser_warning.setHtml(_translate("AVDV", "\n" "