def __init__(self): super(DownloaderMain_Function, self).__init__() # init UI self.setupUi() if Config().get_debugflag(): print("debug on: in DownloaderMain_Function, before load config ") print("configfilepath: " + Config().configfilepath) print("configfilepath_init: " + Config().configfilepath_init) self.config = Config() self.videoconfig = VideoConfig() self.videoconfigs = [] if self.config.get_debugflag(): print("debug on: in DownloaderMain_Function, after load config ") self.myTimer = QTimer(self) self.myTimer.timeout.connect(self.function_show_downloadvideo_info) self.myStartTimer() # self.function_show_downloadvideo_info() # About Action self.actionAbout.triggered.connect(self.function_about_information) # URL Action self.actionURL.triggered.connect(self.function_url_setting) self.URLSettingBtn.clicked.connect(self.function_url_setting) # User Config Action self.actionUser_Config.triggered.connect(self.function_userconfig) # System Config Action self.actionSystem_Config.triggered.connect(self.function_systemconfig) # Open Download Path self.DownloadResultBtn.clicked.connect(self.function_open_download_path) # Start Action self.startdownload_btn.clicked.connect(self.function_start_download)
def __init__(self): super(URLSetting_Function, self).__init__() self.setupUi() # show URL self.config = Config() self.url_file_path = self.config.get_url_file_path() if self.url_file_path != '': self.function_load_url_info(self.url_file_path) # Browser URL Action self.urlbrowserbutton.clicked.connect(self.function_import_url_setting) # OK/Cancel button action self.buttonBox.accepted.connect(self.function_accept) self.buttonBox.rejected.connect(self.function_reject)
def __init__(self): super(SystemSetting_Function, self).__init__() self.setupUi() self.config = Config() # show thread number self.thread_number = self.config.get_thread_number() self.function_load_thread_number_info(self.thread_number) # show retry times self.failed_retry_times = self.config.get_failed_retry_times() self.function_load_failed_retry_times_info(self.failed_retry_times) # show connect timeout, unit is second self.connect_timeout = self.config.get_connect_timeout() self.function_load_connect_timeout_info(self.connect_timeout) # show header text self.headertext = self.config.get_headertext() self.function_load_headertext_info(self.headertext) # OK/Cancel button action self.buttonBox.accepted.connect(self.function_accept) self.buttonBox.rejected.connect(self.function_reject)
def function_open_download_path(self): download_path = Config().get_download_dir() if(download_path == ""): curdir = os.getcwd() download_path = os.path.join(curdir, "download") if not os.path.exists(download_path) or not os.path.isdir(download_path): os.mkdir(download_path) platform_info = platform.system() if platform_info == 'Linux': os.system('xdg-open "%s"' % download_path) elif platform_info == 'Windows': os.startfile(download_path) elif platform_info == 'Darwin': os.system('open "%s"' % download_path) else: QMessageBox.about(self, '打开失败', '无法打开,请手动打开下载目录')
class SystemSetting_Function(Gui_SystemSetting): MIN_THREAD_NUMBER = 1 MAX_THREAD_NUMBER = 4 MIN_FAILED_RETRY_TIMES = 1 MAX_FAILED_RETRY_TIMES = 4 MIN_CONNECT_TIMEOUT = 1 MAX_CONNECT_TIMEOUT = 10 def __init__(self): super(SystemSetting_Function, self).__init__() self.setupUi() self.config = Config() # show thread number self.thread_number = self.config.get_thread_number() self.function_load_thread_number_info(self.thread_number) # show retry times self.failed_retry_times = self.config.get_failed_retry_times() self.function_load_failed_retry_times_info(self.failed_retry_times) # show connect timeout, unit is second self.connect_timeout = self.config.get_connect_timeout() self.function_load_connect_timeout_info(self.connect_timeout) # show header text self.headertext = self.config.get_headertext() self.function_load_headertext_info(self.headertext) # OK/Cancel button action self.buttonBox.accepted.connect(self.function_accept) self.buttonBox.rejected.connect(self.function_reject) def function_accept(self): config = self.config # 设置 thread 信息 # 判断 thread 数值,取值范围在[1,4] try: thread_num = int(self.threads_lineedit.text()) if thread_num < SystemSetting_Function.MIN_THREAD_NUMBER or thread_num > SystemSetting_Function.MAX_THREAD_NUMBER: QMessageBox.warning( self, '线程数(并行数量) 设置失败', '数值应该大于等于' + str(SystemSetting_Function.MIN_THREAD_NUMBER) + '且小于等于' + str(SystemSetting_Function.MAX_THREAD_NUMBER)) return else: config.set_thread_number(self.threads_lineedit.text()) except Exception as ex: QMessageBox.warning( self, '线程数(并行数量) 设置失败', '应该为 ' + str(SystemSetting_Function.MIN_THREAD_NUMBER) + '~' + str(SystemSetting_Function.MAX_THREAD_NUMBER) + ' 的数值') return # 设置 failed retry times 信息 # 判断 failed retry times 数值,取值范围在[1,4] try: failedretrytimes = int(self.failedretrytimes_lineedit.text()) if failedretrytimes < SystemSetting_Function.MIN_FAILED_RETRY_TIMES or thread_num > SystemSetting_Function.MAX_FAILED_RETRY_TIMES: QMessageBox.warning( self, '下载失败重复次数 设置失败', '数值应该大于等于' + str(SystemSetting_Function.MIN_FAILED_RETRY_TIMES) + '且小于等于' + str(SystemSetting_Function.MAX_FAILED_RETRY_TIMES)) return else: config.set_failed_retry_times( self.failedretrytimes_lineedit.text()) except Exception as ex: QMessageBox.warning( self, '下载失败重复次数 设置失败', '应该为 ' + str(SystemSetting_Function.MIN_FAILED_RETRY_TIMES) + '~' + str(SystemSetting_Function.MAX_FAILED_RETRY_TIMES) + ' 的数值') return # 设置 connect timeout 信息 # 判断 connect timeout 数值,取值范围在[1,10] try: connecttimeout = int(self.connecttimeout_lineedit.text()) if connecttimeout < SystemSetting_Function.MIN_CONNECT_TIMEOUT or thread_num > SystemSetting_Function.MAX_CONNECT_TIMEOUT: QMessageBox.warning( self, '连接超时(秒) 设置失败', '数值应该大于等于' + str(SystemSetting_Function.MIN_CONNECT_TIMEOUT) + '且小于等于' + str(SystemSetting_Function.MAX_CONNECT_TIMEOUT)) return else: config.set_connect_timeout(self.connecttimeout_lineedit.text()) except Exception as ex: QMessageBox.warning( self, '连接超时(秒) 设置失败', '应该为 ' + str(SystemSetting_Function.MIN_CONNECT_TIMEOUT) + '~' + str(SystemSetting_Function.MAX_CONNECT_TIMEOUT) + ' 的数值') return # 设置 报头 信息 headertext = self.header_textedit.toPlainText() if headertext == "": QMessageBox.warning( self, "报头 设置失败", "报头不能为空。样例:\n" "'accept-encoding': 'gzip, deflate, br',\n" "'accept-language': 'zh-CN,zh;q=0.9',\n" "'pragma': 'no-cache',\n" "'cache-control': 'no-cache',\n" "'upgrade-insecure-requests': '1',\n" "'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'" ) return else: config.set_headertext(self.header_textedit.toPlainText().replace( '\',\n', '\',').strip()) self.accept() def function_reject(self): self.reject() def function_load_thread_number_info(self, thread_number): self.threads_lineedit.setText(thread_number) # self.threads_lineedit.setEnabled(True) self.threads_lineedit.setEnabled(False) def function_load_failed_retry_times_info(self, failed_retry_time): self.failedretrytimes_lineedit.setText(failed_retry_time) self.failedretrytimes_lineedit.setEnabled(True) def function_load_connect_timeout_info(self, connect_timeout): self.connecttimeout_lineedit.setText(connect_timeout) self.connecttimeout_lineedit.setEnabled(True) def function_load_headertext_info(self, headertext): self.header_textedit.setText(headertext) self.header_textedit.setEnabled(True)
class DownloaderMain_Function(Gui_DownloaderMain): REFRESH_TIME_INTERVAL = 5 def __init__(self): super(DownloaderMain_Function, self).__init__() # init UI self.setupUi() if Config().get_debugflag(): print("debug on: in DownloaderMain_Function, before load config ") print("configfilepath: " + Config().configfilepath) print("configfilepath_init: " + Config().configfilepath_init) self.config = Config() self.videoconfig = VideoConfig() self.videoconfigs = [] if self.config.get_debugflag(): print("debug on: in DownloaderMain_Function, after load config ") self.myTimer = QTimer(self) self.myTimer.timeout.connect(self.function_show_downloadvideo_info) self.myStartTimer() # self.function_show_downloadvideo_info() # About Action self.actionAbout.triggered.connect(self.function_about_information) # URL Action self.actionURL.triggered.connect(self.function_url_setting) self.URLSettingBtn.clicked.connect(self.function_url_setting) # User Config Action self.actionUser_Config.triggered.connect(self.function_userconfig) # System Config Action self.actionSystem_Config.triggered.connect(self.function_systemconfig) # Open Download Path self.DownloadResultBtn.clicked.connect(self.function_open_download_path) # Start Action self.startdownload_btn.clicked.connect(self.function_start_download) # Stop Action # self.stopdownload_btn.clicked.connect(self.function_stop_download) # Pause Action # self.pausedownload_btn.clicked.connect(self.function_pause_download) # refreshThread = threading.Thread(target=self.monitor_download_info) # refreshThread.start() # Actions detail # Pop up a window to confirm whether you want to quit or not. def closeEvent(self, event): reply = QMessageBox.question(self, 'Message', '确定要退出吗', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: event.accept() # 为了解决终止进程时,主窗口关闭,子线程不结束而加入下面关闭语句 sys.exit(self.exec_()) else: event.ignore() # About def function_about_information(self): #tagtime = file_modify_time = time.strftime('%Y%m%d-%H%M%S', time.localtime(time.time())) tagtime = "2020-02-09" message = ''' 版本 Ver 2020.0.1 alpha BuildTime : ''' + tagtime + ''' 声明: 此版本为第一版,未对程序进行优化。现有如下问题: 1. 启动过程比较慢 2. 开始爬取后,获取加密签名过程较慢 请耐心~~~ 该程序为视频爱好者服务,提供下载指定抖音账号的全部视频 目前由两人进行维护,如果您希望参与或有需求,请联系: 微信: 15600203112 邮件: [email protected] ''' QMessageBox.about(self, 'About', message) # URL Setting def function_url_setting(self): urlsetting_Dialog = URLSetting_Function() urlsetting_Dialog.show() urlsetting_Dialog.exec_() # User Config Settinguser def function_userconfig(self): userconfig_Dialog = UserSetting_Function() userconfig_Dialog.show() userconfig_Dialog.exec_() # System Config Setting def function_systemconfig(self): systemconfig_Dialog = SystemSetting_Function() systemconfig_Dialog.show() systemconfig_Dialog.exec_() # Open Download Path # Linux/Mac 没有测试过; Windows会闪一个批处理窗口 # platform.system() # Linux: Linux # Mac: Darwin # Windows: Windows def function_open_download_path(self): download_path = Config().get_download_dir() if(download_path == ""): curdir = os.getcwd() download_path = os.path.join(curdir, "download") if not os.path.exists(download_path) or not os.path.isdir(download_path): os.mkdir(download_path) platform_info = platform.system() if platform_info == 'Linux': os.system('xdg-open "%s"' % download_path) elif platform_info == 'Windows': os.startfile(download_path) elif platform_info == 'Darwin': os.system('open "%s"' % download_path) else: QMessageBox.about(self, '打开失败', '无法打开,请手动打开下载目录') # os.system('start explorer.exe %s' % (download_path)) # os.popen('explorer.exe %s' % (download_path)) def function_start_download(self): # myStartTimer and new thread 是为了刷新界面 self.myStartTimer() download_thread = threading.Thread(target=self.download) download_thread.start() def download(self): self.startdownload_btn.setText("下载中...") self.startdownload_btn.setEnabled(False) urf_file_path = self.config.get_url_file_path() all_url_info = self.config.load_url_info(urf_file_path) cs = CrawlerScheduler_Douyin(all_url_info, self.config, self.videoconfig) while True: if cs.download_status == CrawlerScheduler_Douyin.STATUS_FINISH: # 弹出窗口会导致主线程死掉,需改进 # QMessageBox.about(self, '下载完成', '下载完成,请查看数据') self.startdownload_btn.setText("开始") self.startdownload_btn.setEnabled(True) break elif cs.download_status == CrawlerScheduler_Douyin.STATUS_INVALIDURL: # QMessageBox.about(self, '警告', '没有可以用于下载的连接,请检查URL是否可以正常打开') self.startdownload_btn.setText("开始") self.startdownload_btn.setEnabled(True) break def myStartTimer(self): # 设置刷新界面倒计时时间,秒为单位 self.myTimer.start(self.REFRESH_TIME_INTERVAL) def myStopTimer(self): self.myTimer.stop() def function_stop_download(self): print("need implement... in DownloaderMain_Function ...") def function_pause_download(self): print("need implement... in DownloaderMain_Function ...") def function_show_downloadvideo_info(self): self.myStopTimer() # 显示下载的视频信息 if not self.videoconfig.is_empty_config(): self.videoconfigs = self.videoconfig.load_vconfig() # 取消clear/setRowCount 来解决刷新问题 # self.download_info_table_show.clear() # self.download_info_table_show.setRowCount(0) self.download_info_table_show.setHorizontalHeaderLabels(['序号', '主播ID', '标题', '状态', '类型', '下载时间', '大小']) self.video_numbers = self.videoconfig.get_video_numbers() for videoconfig in self.videoconfigs: self.function_add_one_line_at_table(videoconfig, self.video_numbers) self.download_info_table_show.scrollToBottom() self.myStartTimer() # Add a new line at table # param video_pos: current line, start with the number of line: 0 # param blogger_column_items.: the first column: parameter # param vtitle_column_items: the second column: parameter # .... def function_add_one_line_at_table(self, config, rownumbers): # num_column_items = QTableWidgetItem(str(row + 1)) # num_column_items.setFlags(Qt.ItemIsEnabled) # url_column_items = QTableWidgetItem(config.) # url_column_items.setFlags(Qt.ItemIsEnabled) # '序号' : number # '主播' : blogger # '主播ID' : bloggerid # '标题' : vtitle # '状态' : status # '类型' : filetype # '下载时间' : downtime # '大小' : vsize # '文件标识' : identifykey # blogger_column_items = QTableWidgetItem(config.get('blogger')) # blogger_column_items.setFlags(Qt.ItemIsEditable) number_column_items = QTableWidgetItem(config.get('number')) number_column_items.setFlags(Qt.ItemIsEditable) bloggerid_column_items = QTableWidgetItem(config.get('bloggerid')) bloggerid_column_items.setFlags(Qt.ItemIsEditable) vtitle_column_items = QTableWidgetItem(config.get('vtitle')) vtitle_column_items.setFlags(Qt.ItemIsEditable) status_column_items = QTableWidgetItem(config.get('status')) status_column_items.setFlags(Qt.ItemIsEditable) filetype_column_items = QTableWidgetItem(config.get('filetype')) filetype_column_items.setFlags(Qt.ItemIsEditable) downtime_column_items = QTableWidgetItem(config.get('downtime')) downtime_column_items.setFlags(Qt.ItemIsEditable) vsize_column_items = QTableWidgetItem(config.get('vsize')) vsize_column_items.setFlags(Qt.ItemIsEditable) self.download_info_table_show.setRowCount(rownumbers) self.download_info_table_show.verticalHeader().setVisible(False) video_pos = self.videoconfig.get_vconfig_pos_by_id(config.get('number')) if video_pos is None : return # number_column_items = QTableWidgetItem(video_pos) self.download_info_table_show.setItem(video_pos, 0, QTableWidgetItem(number_column_items)) self.download_info_table_show.setItem(video_pos, 1, QTableWidgetItem(bloggerid_column_items)) self.download_info_table_show.setItem(video_pos, 2, QTableWidgetItem(vtitle_column_items)) self.download_info_table_show.setItem(video_pos, 3, QTableWidgetItem(status_column_items)) self.download_info_table_show.setItem(video_pos, 4, QTableWidgetItem(filetype_column_items)) self.download_info_table_show.setItem(video_pos, 5, QTableWidgetItem(downtime_column_items)) self.download_info_table_show.setItem(video_pos, 6, QTableWidgetItem(vsize_column_items))
class URLSetting_Function(Gui_URLSetting): def __init__(self): super(URLSetting_Function, self).__init__() self.setupUi() # show URL self.config = Config() self.url_file_path = self.config.get_url_file_path() if self.url_file_path != '': self.function_load_url_info(self.url_file_path) # Browser URL Action self.urlbrowserbutton.clicked.connect(self.function_import_url_setting) # OK/Cancel button action self.buttonBox.accepted.connect(self.function_accept) self.buttonBox.rejected.connect(self.function_reject) def function_accept(self): config = self.config config.set_url_file_path(self.url_path.text()) self.accept() def function_reject(self): self.reject() # Import URL file def function_import_url_setting(self): self.url_file_path = self.choose_one_file() if self.url_file_path == '': return self.function_load_url_info(self.url_file_path) def choose_one_file(self): file_path, file_type = QFileDialog.getOpenFileName( self, 'Choose URL File', './', "All Files (*);;") return file_path def function_load_url_info(self, urf_file_path): self.url_path.setText(urf_file_path) self.url_path.setEnabled(False) try: self.all_url_info = self.config.load_url_info(urf_file_path) self.function_show_url_value() except Exception: QMessageBox.warning(self, 'Warning', 'Analysis URL failed!', QMessageBox.Close) return # update table's info - url def function_show_url_value(self): # self.model_lines.clear() self.url_table_show.clear() self.url_table_show.setRowCount(0) self.url_table_show.setHorizontalHeaderLabels(['No.', 'URL']) for url in self.all_url_info: self.function_add_one_line_at_table(self.url_table_show.rowCount(), url.strip()) # Add a new line at table # param row:QTableWidgetItem current line, start with the number of line: 0 # param num.: the first column: parameter # param url: the second column: parameter def function_add_one_line_at_table(self, row, url): num_column_items = QTableWidgetItem(str(row + 1)) num_column_items.setFlags(Qt.ItemIsEnabled) url_column_items = QTableWidgetItem(url) url_column_items.setFlags(Qt.ItemIsEnabled) self.url_table_show.setRowCount(row + 1) self.url_table_show.verticalHeader().setVisible(False) self.url_table_show.setItem(row, 0, QTableWidgetItem(num_column_items)) self.url_table_show.setItem(row, 1, QTableWidgetItem(url_column_items))