def __init__(self, window_queue): self.queue = queue.Queue(5) self.win_queue = window_queue self.iJson = imageJson.imageJson() self.logger = LoggingProducer().get_default_logger() thread = threading.Thread(target=self.downloadThread, args=[]) thread.setDaemon(True) thread.start()
def __init__(self): try: self.logger = LoggingProducer().get_default_logger() rootdir = os.path.abspath(os.path.dirname(__file__)) cfgpath = "{}/{}".format(rootdir, "config.ini") self.config = config(cfgpath) self.DATABASE_IPADDRESS = self.config.get("database", "host") self.DATABASE_NAME = self.config.get("database", "databasename") self.DATABASE_USERNAME = self.config.get("database", "username") self.DATABASE_PASSWORD = self.config.get("database", "password") except Exception as e: print("warehouse init failed:{}".format(e))
def __init__(self, subject): self.q = queue.Queue(32) self.logger = LoggingProducer().get_logger() # SMTP服务器,腾讯企业邮箱端口是465,腾讯邮箱支持SSL(不强制), 不支持TLS # qq邮箱smtp服务器地址:smtp.qq.com,端口号:456 # 163邮箱smtp服务器地址:smtp.163.com,端口号:25 # 登录服务器,括号中对应的是发件人邮箱账号、邮箱密码 self.email_subject = subject time.sleep(0.1) self.confile_path = "{}/{}".format( os.path.abspath(os.path.dirname(__file__)), self.confile_filename) t = threading.Thread(target=self.email_task, args=[]) t.setDaemon(False) t.start() pass
def __init__(self): super(Window, self).__init__() self.setupUi(self) self.btn_savepath.clicked.connect(self.savePathFunc) self.btn_startdownload.clicked.connect(self.startDownloadFunc) self.btn_startdownload.setEnabled(False) self.btn_opensavepath.clicked.connect(self.openSaveImagePath) self.btn_opensavepath.setEnabled(False) self.textEdit.textChanged.connect(self.setDownloadButtonEnable) self.listWidget_downloadinfo.clicked.connect(self.clickedListWidget) self.listWidget_wiatdownload.clicked.connect(self.clickedListWidget) self.logger = LoggingProducer().get_default_logger() self.timer = QBasicTimer() self.timer.start(1, self) self.recv_queue = queue.Queue(10) self.gImage = getimage.getimage(self.recv_queue)
class tencent_email(): # 发件人邮箱账号 sender_email = '' sender_name = '' # user登录邮箱的用户名,password登录邮箱的密码(授权码,即客户端密码,非网页版登录密码),但用腾讯邮箱的登录密码也能登录成功 sender_password = '' q = None confile_filename = "config.ini" confile_path = "" email_server = None common_message = None def __init__(self, subject): self.q = queue.Queue(32) self.logger = LoggingProducer().get_logger() # SMTP服务器,腾讯企业邮箱端口是465,腾讯邮箱支持SSL(不强制), 不支持TLS # qq邮箱smtp服务器地址:smtp.qq.com,端口号:456 # 163邮箱smtp服务器地址:smtp.163.com,端口号:25 # 登录服务器,括号中对应的是发件人邮箱账号、邮箱密码 self.email_subject = subject time.sleep(0.1) self.confile_path = "{}/{}".format( os.path.abspath(os.path.dirname(__file__)), self.confile_filename) t = threading.Thread(target=self.email_task, args=[]) t.setDaemon(False) t.start() pass def email_task(self): while True: try: if not self.q.empty(): self.email_server = smtplib.SMTP_SSL( "smtp.exmail.qq.com", 465) self.email_server.login(self.sender_email, self.sender_password) while True: msgdict = self.q.get() self.q.task_done() message = "{}:{}".format(msgdict["sn"], msgdict["message"]) sendmsg = MIMEText(message, 'plain', 'utf-8') sendmsg['From'] = formataddr( [self.sender_name, self.sender_email]) #单独发送给个人时可以配置该选项 #sendmsg['To'] = formataddr([msgdict['rname'], msgdict['remail']]) sendmsg['Subject'] = self.email_subject self.email_server.sendmail(self.sender_email, msgdict['remail'], sendmsg.as_string()) if self.q.empty(): break self.email_server.quit() time.sleep(1) pass except Exception as e: self.logger.error("email_task error{}".format(e)) def send_email(self, receiver_email: list, receiver_name: list, device_sn: str, email_message: str): try: self.sender_email = config(self.confile_path).get( 'email', 'sender_email') self.sender_password = config(self.confile_path).get( 'email', 'sender_password') self.sender_name = config(self.confile_path).get( 'email', 'sender_name') #self.logger.info("self.sender_email={} self.sender_name={} self.sender_password={}".format(self.sender_email, self.sender_password, self.sender_name)) if len(self.sender_email) != 0 and len(self.sender_password) != 0: self.q.put({ "remail": receiver_email, "rname": receiver_name, "sn": device_sn, "message": email_message }) except Exception as e: self.logger.error("send_email error:{}".format(e))
class warehouse(): #在windows下使用localhost会出现10061错误 #DATABASE_IPADDRESS = '127.0.0.1' TABLE_IN_HEAD = 'in' TABLE_OUT_HEAD = 'out' def __init__(self): try: self.logger = LoggingProducer().get_default_logger() rootdir = os.path.abspath(os.path.dirname(__file__)) cfgpath = "{}/{}".format(rootdir, "config.ini") self.config = config(cfgpath) self.DATABASE_IPADDRESS = self.config.get("database", "host") self.DATABASE_NAME = self.config.get("database", "databasename") self.DATABASE_USERNAME = self.config.get("database", "username") self.DATABASE_PASSWORD = self.config.get("database", "password") except Exception as e: print("warehouse init failed:{}".format(e)) '''创建数据库''' def create_db(self): self.db = MySQLdb.connect(self.DATABASE_IPADDRESS, self.DATABASE_USERNAME, self.DATABASE_PASSWORD, charset='utf8') self.cursor = self.db.cursor() self.db.autocommit(False) self.cursor.execute('set names utf8') self.db.commit() try: self.cursor.execute('show databases') rows = self.cursor.fetchall() for row in rows: if self.DATABASE_NAME == row[0]: #self.logger.info("DataBase Already Exits") return True sql = 'create database {}'.format(self.DATABASE_NAME) self.cursor.execute(sql) self.db.commit() #self.logger.info("create db ok") return True except Exception as e: self.logger.error("db create error:{}".format(e)) self.db.rollback() return False finally: self.cursor.close() self.db.close() def create_tb(self): self.db = MySQLdb.connect(self.DATABASE_IPADDRESS, self.DATABASE_USERNAME, self.DATABASE_PASSWORD, self.DATABASE_NAME, charset='utf8') self.cursor = self.db.cursor() will_create_tb = [ 'warehouse', "{}{}".format(self.TABLE_IN_HEAD, time.strftime('%Y%m')), "{}{}".format(self.TABLE_OUT_HEAD, time.strftime('%Y%m')) ] need_create_tb = [] try: #name = '{}{}'.format(self.TABLENAME_HEAD, name) self.cursor.execute('show tables') rows = self.cursor.fetchall() for tbname in will_create_tb: flag = False for row in rows: if tbname == row[0]: #self.logger.info("Table[{}] Already Exits".format(tbname)) flag = True break if flag is False: need_create_tb.append(tbname) if len(need_create_tb) == 0: return True else: for tbname in need_create_tb: if tbname == 'warehouse': sql = "create table {}(\ u32ProductID int(1) unsigned primary key auto_increment,\ c64ProductName varchar(64) character set utf8 collate utf8_general_ci default \'null\',\ c64PinyinName varchar(64) character set utf8 collate utf8_general_ci default \'null\',\ u32Inventory int(1) unsigned default 0,\ u32Sold int(1) unsigned default 0,\ fCost float(10,1) unsigned default 0.0,\ fIncome float(10,1) unsigned default 0.0)".format(tbname) pass elif tbname.startswith(self.TABLE_OUT_HEAD): sql = "create table {}(\ u32Id int(1) unsigned primary key auto_increment,\ time datetime default NULL,\ u32ProductID int(1) unsigned default 0,\ u32Sold int(1) unsigned default 0,\ fIncome float(10,1) unsigned default 0.0)".format(tbname) pass elif tbname.startswith(self.TABLE_IN_HEAD): sql = "create table {}(\ u32Id int(1) unsigned primary key auto_increment,\ time datetime default NULL,\ u32ProductID int(1) unsigned default 0,\ u32Inventory int(1) unsigned default 0,\ fCost float(10,1) unsigned default 0.0)".format(tbname) pass else: continue self.cursor.execute(sql) self.db.commit() ''' sql = "create table {}(\ u32DeviceID int(1) unsigned primary key auto_increment,\ c20Name varchar(20) character set utf8 collate utf8_general_ci default \'NULL\',\ c20SName varchar(20) character set utf8 collate utf8_general_ci default \'NULL\',\ InTime datetime default NULL,\ OutTime datetime default NULL,\ TotalNum int(1) unsigned default 0,\ ShopNum int(1) unsigned default 0,\ InPrice float(10,1) unsigned default 0.0,\ OutPrice float(10,1) unsigned default 0.0,\ GroupSellID int(1) unsigned default 0,\ GroupMoney float(10,1) unsigned default 0.0)".format(name) self.cursor.execute(sql) self.db.commit() ''' #sql = 'alter table %s add index IndexUpload(cInUpload(1),cOutUpload(1))' % name #cursor.execute(sql) #db.commit() #self.logger.info('create tb success') return True except Exception as e: self.logger.error("create table error:{}".format(e)) self.db.rollback() return False finally: self.cursor.close() self.db.close() def get_version(self): self.db = MySQLdb.connect(self.DATABASE_IPADDRESS, self.DATABASE_USERNAME, self.DATABASE_PASSWORD, self.DATABASE_NAME, charset='utf8') self.cursor = self.db.cursor() try: self.cursor.execute('select version()') ret = self.cursor.fetchone() self.db.commit() return ret except Exception as e: self.logger.error("get_version error:{}".format(e)) self.db.rollback() finally: self.cursor.close() self.db.close() ''' def getGroupIDLast(self, tbname): self.db = MySQLdb.connect(self.DATABASE_IPADDRESS, self.DATABASE_USERNAME, self.DATABASE_PASSWORD, self.DATABASE_NAME, charset='utf8') self.cursor = self.db.cursor() try: sql = 'select GroupSellID from %s' % tbname + \ ' where GroupSellID in (select max(GroupSellID) from %s' % tbname + \ ' order by GroupSellID)' self.cursor.execute(sql) result = self.cursor.fetchone() if result: self.gGroupID = result[0] except Exception as e: self.logger.error("getGroupIDLast error:{}".format(e)) finally: self.cursor.close() self.db.close() #售出一种商品的情况 def sellOneItem(self, tbname, name, count, money): self.db = MySQLdb.connect(self.DATABASE_IPADDRESS, self.DATABASE_USERNAME, self.DATABASE_PASSWORD, self.DATABASE_NAME, charset='utf8') self.cursor = self.db.cursor() self.logger.info('table name:{}'.format(tbname)) try: #datetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) datetime = time.strftime('%Y-%m-%d %H:%M:%S') sql = 'insert into %s' % tbname + \ '(c20Name, OutTime, ShopNum, OutPrice)' + \ ' values(\'%s\', \'%s\', %d, %f)' % (name, datetime, count, money) self.cursor.execute(sql) self.db.commit() except Exception as e: self.logger.error("sellOneItem error:{}".format(e)) self.db.rollback() finally: self.cursor.close() self.db.close() #几件商品打包售出的情况 def sellSomeItem(self, tbname, name_count_list, money): self.db = MySQLdb.connect(self.DATABASE_IPADDRESS, self.DATABASE_USERNAME, self.DATABASE_PASSWORD, self.DATABASE_NAME, charset='utf8') self.cursor = self.db.cursor() self.gGroupID = self.gGroupID + 1 #datetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) datetime = time.strftime('%Y-%m-%d %H:%M:%S') try: for item in name_count_list: item_name = item[0] item_count = item[1] sql = 'insert into %s' % tbname + \ '(c20Name, OutTime, ShopNum, GroupSellID, GroupMoney)' + \ ' values(\'%s\', \'%s\', %d, %d, %f)' % (item_name, datetime, item_count, self.gGroupID, money) self.cursor.execute(sql) self.db.commit() except Exception as e: self.logger.error("sellSomeItem error:{}".format(e)) self.db.rollback() finally: self.cursor.close() self.db.close() ''' def __update_warehouse(self, productid, flag: int, number: int, money: float, productname: str, pinyinname: str): try: if productid is None: if flag == 0: #入库 sql = 'insert into warehouse(c64ProductName, c64PinyinName, u32Inventory, fCost) values(\'{}\', \'{}\', {}, {})'.format( productname, pinyinname, number, money) else: sql = 'insert into warehouse(c64ProductName, c64PinyinName, u32Sold, fIncome) values(\'{}\', \'{}\', {}, {})'.format( productname, pinyinname, number, money) self.cursor.execute(sql) self.db.commit() sql = 'select u32ProductID from warehouse where c64PinyinName=\'{}\''.format( pinyinname) self.cursor.execute(sql) result = self.cursor.fetchone() print(result) return result[0] else: sql = "select * from warehouse where u32ProductID={}".format( productid) find = False self.cursor.execute(sql) while True: result = self.cursor.fetchone() if result is not None: # print("result0={} type={}".format(result[0], type(result[0]))) if result[0] == productid: find = True if flag == 0: #入库 u32Inventory = result[3] # print("u32Inventory={} type={}".format(u32Inventory, type(u32Inventory))) fCost = result[5] # print("fCost={} type={}".format(fCost, type(fCost))) u32Inventory = u32Inventory + number fCost = fCost + money sql = "update warehouse set u32Inventory={},fCost={} where u32ProductID={}".format( u32Inventory, fCost, productid) else: #售出 u32Sold = result[4] fIncome = result[6] u32Sold = u32Sold + number fIncome = fIncome + money sql = "update warehouse set u32Sold={},fIncome={} where u32ProductID={}".format( u32Sold, fIncome, productid) self.cursor.execute(sql) self.db.commit() else: break return None except Exception as e: self.logger.error("__update_warehouse error:{}".format(e)) self.db.rollback() ''' name_count_list = [[ 商品ID, 商品名, 商品拼音名, 入库出库标志位, 数量, 金额 ], ] ''' def update(self, record_list: list): self.create_tb() self.db = MySQLdb.connect(self.DATABASE_IPADDRESS, self.DATABASE_USERNAME, self.DATABASE_PASSWORD, self.DATABASE_NAME, charset='utf8') self.cursor = self.db.cursor() intb = "{}{}".format(self.TABLE_IN_HEAD, time.strftime('%Y%m')) outtb = "{}{}".format(self.TABLE_OUT_HEAD, time.strftime('%Y%m')) try: for record in record_list: productid = record[0] productname = record[1] pinyinname = record[2] flag = record[3] number = record[4] money = record[5] proid = self.__update_warehouse(productid, flag, number, money, productname, pinyinname) if proid: productid = proid if flag == 0: #入库标志 sql = 'insert into {}(time, u32ProductID, u32Inventory, fCost) values(\'{}\', {}, {}, {})'.format( intb, time.strftime('%Y-%m-%d %H:%M:%S'), productid, number, money) self.cursor.execute(sql) self.db.commit() else: #售出标志 sql = 'insert into {}(time, u32ProductID, u32Sold, fIncome) values(\'{}\', {}, {}, {})'.format( outtb, time.strftime('%Y-%m-%d %H:%M:%S'), productid, number, money) self.cursor.execute(sql) self.db.commit() ''' sql = 'insert into %s' % tbname + \ '(c20Name, OutTime, ShopNum, OutPrice)' + \ ' values(\'%s\', \'%s\', %d, %f)' % (item[0], datetime, item[1], money) ''' except Exception as e: self.logger.error("update error:{}".format(e)) self.db.rollback() finally: self.cursor.close() self.db.close() ''' def putInStorage(self, tbname, str_list): self.db = MySQLdb.connect(self.DATABASE_IPADDRESS, self.DATABASE_USERNAME, self.DATABASE_PASSWORD, self.DATABASE_NAME, charset='utf8') self.cursor = self.db.cursor() name = str_list[0] name_pinyin = str_list[1] number = str_list[2] money = str_list[3] #datetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) datetime = time.strftime('%Y-%m-%d %H:%M:%S') try: sql = 'insert into %s' % tbname + \ '(c20Name, c20SName, InTime, TotalNum, InPrice)' + \ ' values(\'%s\', \'%s\', \'%s\', %d, %f)' % (name, name_pinyin, datetime, number, money) self.logger.info(sql) self.cursor.execute(sql) self.db.commit() except Exception as e: self.logger.error("putInStorage error:{}".format(e)) self.db.rollback() finally: self.cursor.close() self.db.close() ''' def getall(self): self.db = MySQLdb.connect(self.DATABASE_IPADDRESS, self.DATABASE_USERNAME, self.DATABASE_PASSWORD, self.DATABASE_NAME, charset='utf8') self.cursor = self.db.cursor() ret_list = [] try: sql = 'select * from warehouse' self.cursor.execute(sql) while True: result = self.cursor.fetchone() if result: ret_list.append(result) else: break except Exception as e: self.logger.error("getall error:{}".format(e)) finally: self.cursor.close() self.db.close() return ret_list
class Window(QtWidgets.QMainWindow, Ui_ImageDownloadtools): rootdir = "" recv_queue = None gImage = None download_flag = False DEFAULT_SAVE_DIR = 'C://Users//Administrator//autoDownloadImage//' wait_download_list = [] cur_download_url = None def __init__(self): super(Window, self).__init__() self.setupUi(self) self.btn_savepath.clicked.connect(self.savePathFunc) self.btn_startdownload.clicked.connect(self.startDownloadFunc) self.btn_startdownload.setEnabled(False) self.btn_opensavepath.clicked.connect(self.openSaveImagePath) self.btn_opensavepath.setEnabled(False) self.textEdit.textChanged.connect(self.setDownloadButtonEnable) self.listWidget_downloadinfo.clicked.connect(self.clickedListWidget) self.listWidget_wiatdownload.clicked.connect(self.clickedListWidget) self.logger = LoggingProducer().get_default_logger() self.timer = QBasicTimer() self.timer.start(1, self) self.recv_queue = queue.Queue(10) self.gImage = getimage.getimage(self.recv_queue) '''选择图片保存的目录''' def savePathFunc(self): self.rootdir = QFileDialog.getExistingDirectory(None, "选择图片保存目录", "/") self.logger.info("保存文件到:{}".format(self.rootdir)) self.label_curdlpath.setText(self.rootdir) self.btn_opensavepath.setEnabled(True) '''打开图片保存的文件夹''' def openSaveImagePath(self): if not os.path.exists(self.rootdir): self.logger.info("path:{} not exists".format(self.rootdir)) return if sys.platform == 'win32': os.startfile(self.rootdir) else: cmd = "open %s".format(self.rootdir) os.system(cmd) '''下载按钮使能禁止''' def setDownloadButtonEnable(self): text = self.textEdit.toPlainText() if not text: self.btn_startdownload.setEnabled(False) else: self.btn_startdownload.setEnabled(True) pass def clickedListWidget(self): self.logger.info("ListWidget click") '''启动下载''' def startDownloadFunc(self): textmsg = self.textEdit.toPlainText() '''链接等于上一次的链接,并且不为空''' if textmsg: if self.download_flag is True: if textmsg not in self.wait_download_list and textmsg != self.cur_download_url: self.wait_download_list.append(textmsg) msg = { 'req': 'waitdownload', 'url': textmsg, } self.recv_queue.put(json.dumps(msg)) self.logger.info(self.wait_download_list) QMessageBox.warning(self, "Warning", "已将该链接加入到下载等待队列", QMessageBox.Ok) return ''' 图片保存目录的生成,以self.savepath作为根目录,在该目录内创建文件夹,文件夹以年月日时分秒明明 更新:该目录作为图片保存的根目录,以图片链接内地title作为文件夹名 ''' tmp_save_dir = self.rootdir if not tmp_save_dir: '''没有设置默认目录''' if not os.path.exists('D://'): if not os.path.exists(self.DEFAULT_SAVE_DIR): os.mkdir(self.DEFAULT_SAVE_DIR) tmp_save_dir = self.DEFAULT_SAVE_DIR else: if not os.path.exists('D://autoDownloadImage'): os.mkdir('D://autoDownloadImage') tmp_save_dir = 'D://autoDownloadImage' self.rootdir = tmp_save_dir self.logger.info("save image root dir:{}".format(tmp_save_dir)) tmp_save_dir = tmp_save_dir.replace('//', '\\') tmp_save_dir = tmp_save_dir.replace('/', '\\') self.label_curdlpath.setText(tmp_save_dir) self.listWidget_downloadinfo.clear() self.label_total_num.setText("0") self.label_dl_num.setText("0") self.label_failed_num.setText("0") self.progressBar.setValue(0) self.logger.info("start download, url:{}".format(textmsg)) try: self.btn_opensavepath.setEnabled(True) self.gImage.start(textmsg, tmp_save_dir) self.download_flag = True self.cur_download_url = textmsg except Exception as e: self.logger.error("startDownloadFunc error:{}".format(e.args)) def timerEvent(self, event): if event.timerId() == self.timer.timerId(): if not self.recv_queue.empty(): msg = self.recv_queue.get() msgjson = json.loads(msg) if msgjson["req"] == "ready": imgtotal = msgjson["total"] self.label_total_num.setText(str(imgtotal)) pass elif msgjson["req"] == "download": imgcount = msgjson["count"] imgdlper = msgjson["percent"] imgdlstatus = msgjson["status"] imgurl = msgjson["url"] imgdlfailed = msgjson["failed"] self.label_dl_num.setText(str(imgcount)) self.progressBar.setValue(imgdlper) self.label_failed_num.setText(str(imgdlfailed)) itemcount = self.listWidget_downloadinfo.count() #logging.info("item count = %d" % itemcount) if imgdlstatus == "download start": item = QtWidgets.QListWidgetItem("downloading:" + imgurl) self.listWidget_downloadinfo.addItem(item) elif imgdlstatus == "download error": if itemcount >= 1: item = QtWidgets.QListWidgetItem( "download failed:" + imgurl) self.listWidget_downloadinfo.takeItem(itemcount - 1) self.listWidget_downloadinfo.addItem(item) self.listWidget_downloadinfo.item( itemcount - 1).setBackground(QColor("red")) elif imgdlstatus == "download ok": if itemcount >= 1: item = QtWidgets.QListWidgetItem("download ok:" + imgurl) self.listWidget_downloadinfo.takeItem(itemcount - 1) self.listWidget_downloadinfo.addItem(item) self.listWidget_downloadinfo.item( itemcount - 1).setBackground(QColor("gray")) if imgdlper == 100: self.progressBar.setValue(0) self.label_dl_num.setText("Download finish") if len(self.wait_download_list) != 0: url = self.wait_download_list.pop(0) self.logger.info("url:{} list:{}".format( url, self.wait_download_list)) self.gImage.start(url, self.rootdir) self.cur_download_url = url self.listWidget_wiatdownload.takeItem(0) else: self.download_flag = False elif msgjson["req"] == "compelete": self.progressBar.setValue(0) self.label_dl_num.setText("Download finish") if len(self.wait_download_list) != 0: url = self.wait_download_list.pop(0) self.logger.info("url:{} list:{}".format( url, self.wait_download_list)) self.gImage.start(url, self.rootdir) self.cur_download_url = url self.listWidget_wiatdownload.takeItem(0) else: self.download_flag = False elif msgjson["req"] == "waitdownload": item = QtWidgets.QListWidgetItem(msgjson['url']) self.listWidget_wiatdownload.addItem(item) elif msgjson["req"] == "error": self.logger.error("connect error,retry download") self.gImage.start(self.cur_download_url, self.rootdir) pass
class getimage(): win_queue = None def __init__(self, window_queue): self.queue = queue.Queue(5) self.win_queue = window_queue self.iJson = imageJson.imageJson() self.logger = LoggingProducer().get_default_logger() thread = threading.Thread(target=self.downloadThread, args=[]) thread.setDaemon(True) thread.start() def getHtml(self, url): self.logger.info("gethtml:%s" % url) headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0' } try: req = urllib.request.Request(url=url, headers=headers) page = urllib.request.urlopen(req) html = page.read() encodingtype = chardet.detect(html) return [encodingtype, html] except Exception as e: self.logger.error("getHtml error:{}".format(e)) for val in e.args: if val == "timed out": self.win_queue.put( self.iJson.generateErrorJson("open url timeout")) return [] def start(self, html, saveimagepath): try: self.logger.info("html={} savepath={}".format(html, saveimagepath)) if not self.queue.full(): self.queue.put([html, saveimagepath]) except Exception as e: self.logger.error("start error:{}".format(e)) #因为这个网站一个页面就一张大图片,所以每次都需要打开下一个页面,获取下一个图片地址 def findImageUrl(self, htmlstr): #reg = r'<img class="img-fluid" src.*?="([.*\S]*?\.(?:jpg|png|jpeg|gif))" />' reg = r'src.*?="(http[.*\S]*?\.(?:jpg|png|jpeg|gif))"' imgre = re.compile(reg) imgurllist = re.findall(imgre, htmlstr) self.logger.info("find image url:{}".format(imgurllist)) return imgurllist def getImageTitle(self, htmlstr): res = '' reg = r'<title>(.*)</title>' imgre = re.compile(reg) imglist = re.findall(imgre, htmlstr) res = str(imglist[0]) self.logger.info("res={}".format(res)) res = re.sub(r'[?*<>"|\\/:]*', '', res) self.logger.info("title={}".format(res)) res = res.replace(' ', '') self.logger.info("title={}".format(res)) if len(res) > 40: res = res[:40] return res def downloadThread(self): while True: try: time.sleep(0.2) if not self.queue.empty(): item_list = self.queue.get() imageUrl = item_list[0] savedir = item_list[1] self.logger.info("imageUrl : {}".format(imageUrl)) #先读取页面,得到页面内容和编码信息 listres = self.getHtml(imageUrl) if len(listres) != 2: self.logger.error("get html error") self.win_queue.put( self.iJson.generateErrorJson("get html error")) continue html = listres[1] encodemsg = listres[0] if not html: self.logger.error("cant open html") self.win_queue.put( self.iJson.generateErrorJson("can not open html")) continue self.logger.info("the web coding: %s" % listres[0]) html = html.decode(encodemsg["encoding"]) #self.logger.info(html) #通过网页内容获取文件夹名字,并检测文件创建文件夹 imgGroupTitle = self.getImageTitle(html) curImageSaveDir = "{}/{}".format(savedir, imgGroupTitle) self.logger.info("self.saveDir : {}".format(savedir)) self.logger.info( "curImageSaveDir : {}".format(curImageSaveDir)) if not os.path.exists(curImageSaveDir): os.mkdir(curImageSaveDir) self.logger.info("save in:{}".format(curImageSaveDir)) #从html页面内容中搜索满足条件的url image_url_list = self.findImageUrl(html) if not image_url_list: self.logger.error("cant find image") continue imgNo = 0 imgTotal = len(image_url_list) headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0' } #向主窗口发送等待下载图片的数量 self.win_queue.put( self.iJson.generateStartJson(None, imgTotal)) for imgurl in image_url_list: imgtype = imgurl.split('.')[-1] self.logger.info("download:url={} type={}".format( imgurl, imgtype)) self.win_queue.put( self.iJson.generateDownloadJson( imgurl, imgNo, int(imgNo * 100 / imgTotal), 0, "download start")) timeoutCount = 0 filename = "{}//{}.{}".format(curImageSaveDir, imgNo, imgtype) if os.path.exists(filename) == False: while True: req = urllib.request.Request(url=imgurl, headers=headers) with open(filename, 'wb') as f: try: #self.logger.info("image url request urlopen") res = urllib.request.urlopen( req, timeout=10) if res: #self.logger.info("image url request urlopen success, start save") data = res.read() f.write(data) #self.logger.info("save success!!!") imgNo += 1 self.win_queue.put( self.iJson. generateDownloadJson( imgurl, imgNo, int(imgNo * 100 / imgTotal), 0, "download ok")) break else: self.logger.error( "image url request urlopen failed" ) except Exception as e: self.logger.error( "download image error:{}".format( e)) for val in e.args: if val == 'timed out': timeoutCount = timeoutCount + 1 if timeoutCount > 5: self.curPageFailed = self.curPageFailed + 1 self.win_queue.put( self.iJson. generateDownloadJson( imgurl, self. ImageDLOKCount, int(imgNo * 100 / imgTotal), self.curPageFailed, "download error")) break else: self.logger.info("file:{} exists".format(filename)) imgNo += 1 self.win_queue.put( self.iJson.generateDownloadJson( imgurl, imgNo, int(imgNo * 100 / imgTotal), 0, "download ok")) time.sleep(random.randint(1, 3)) except Exception as e: self.logger.error("error:{}".format(e))
def __init__(self): # 创建主窗口,用于容纳其它组件 try: #初始化log接口 self.logger = LoggingProducer().get_default_logger() #初始化数据库接口 self.db = warehouse() #初始化显示接口 self.root = tk.Tk() # 给主窗口设置标题内容 self.root.update() root_width = self.root.winfo_screenwidth() root_height = self.root.winfo_screenheight() global_variable.main_window['screen']['w'] = root_width global_variable.main_window['screen']['h'] = root_height percent = int(global_variable.main_window['percent']) if percent < 50: percent = 50 global_variable.main_window['percent'] = 50 main_widht = int(root_width * percent / 100) main_height = int(root_height * percent / 100) main_xoffset = int((root_width - main_widht) / 2) main_yoffset = int((root_height - main_height) / 2) global_variable.main_window['size']['w'] = main_widht global_variable.main_window['size']['h'] = main_height global_variable.main_window['size']['x'] = main_xoffset global_variable.main_window['size']['y'] = main_yoffset self.root.title("收货记账小工具") self.root.geometry("{}x{}+{}+{}".format(main_widht, main_height, main_xoffset, main_yoffset)) self.root.resizable(width=False, height=False) self.toplevel_id = 0 # 查询是否有今日的表,如果没有就创建今日表 self.db.create_db() self.update_queue = queue.Queue(4) self.msgbox = msgbox(self.root, self.logger) self.check_input = check_input.check_input(self.root, self.msgbox, self.logger) self.window_putinstorage = window_put_in_storage(self.root, self.db, self.check_input, self.msgbox, self.update_queue, self.logger) self.windos_sellgoods = windos_sell_goods(self.root, self.db, self.check_input, self.msgbox, self.update_queue, self.logger) #每个按钮的大小 w = int(int(global_variable.main_window['size']['w']) / 10) h = int(int(global_variable.main_window['size']['h']) / 10) #按钮的起始位置 x = int(w / 10) y = x #s表示连个按钮上下之间的距离 s = x font_size = int(w / 6) self.sell_button = tk.Button(self.root, command=self.FuncSell, text="售出", bd=10, bg='white', font=("黑体", font_size)) self.input_button = tk.Button(self.root, command=self.FuncInput, text="入库", bd=10, bg='white', font=("黑体", font_size)) self.tongji_day_button = tk.Button(self.root, command=self.FuncTJDay, text="当日", bd=10, bg='white',font=("黑体", font_size)) self.tongji_month_button = tk.Button(self.root, command=self.FuncTJMonth, text="当月", bd=10, bg='white',font=("黑体", font_size)) self.sell_button.place(x=x, y=y, width=w, height=h) y = y + h + s self.input_button.place(x=x, y=y, width=w, height=h) y = y + h + s self.tongji_day_button.place(x=x, y=y, width=w, height=h) y = y + h + s self.tongji_month_button.place(x=x, y=y, width=w, height=h) #计算主窗口显示商品信息窗口的长宽高 display_start_x = x + w + s display_start_y = x # 两侧留出 x 大小的空余空间 display_width = int(global_variable.main_window['size']['w']) - display_start_x - x # 底部留出 x 大小的空余空间 display_height = int(global_variable.main_window['size']['h']) - display_start_y - x # 参考自https://cloud.tencent.com/developer/ask/130543 # 参考自https://www.cnblogs.com/qwangxiao/p/9940972.html clos = ('编号', '商品名称', '入库数量', '已卖数量', '库存剩余', '总成本', '总收入') self.display_info = ttk.Treeview(self.root, columns=clos, show='headings') for col in clos: self.display_info.heading(col, text=col) self.display_info.grid(row=1, column=0, columnspan=2) # 设置列的宽度和对齐方式 w = int(display_width / 10) self.display_info.column('0', width=w, anchor='center') self.display_info.column('1', width=w*2, anchor='center') self.display_info.column('2', width=w, anchor='center') self.display_info.column('3', width=w, anchor='center') self.display_info.column('4', width=w, anchor='center') self.display_info.column('5', width=w*2, anchor='center') self.display_info.column('6', width=w*2, anchor='center') self.display_info.place(x=display_start_x, y=display_start_y, width=display_width, height=display_height) # 创建刷新显示的线程 t1 = threading.Thread(target=self.ThreadUpdateDisplay, args=()) t1.setDaemon(True) t1.start() except Exception as e: self.logger.error("class init error:{}".format(e))
class FindLocation(object): def __init__(self): # 创建主窗口,用于容纳其它组件 try: #初始化log接口 self.logger = LoggingProducer().get_default_logger() #初始化数据库接口 self.db = warehouse() #初始化显示接口 self.root = tk.Tk() # 给主窗口设置标题内容 self.root.update() root_width = self.root.winfo_screenwidth() root_height = self.root.winfo_screenheight() global_variable.main_window['screen']['w'] = root_width global_variable.main_window['screen']['h'] = root_height percent = int(global_variable.main_window['percent']) if percent < 50: percent = 50 global_variable.main_window['percent'] = 50 main_widht = int(root_width * percent / 100) main_height = int(root_height * percent / 100) main_xoffset = int((root_width - main_widht) / 2) main_yoffset = int((root_height - main_height) / 2) global_variable.main_window['size']['w'] = main_widht global_variable.main_window['size']['h'] = main_height global_variable.main_window['size']['x'] = main_xoffset global_variable.main_window['size']['y'] = main_yoffset self.root.title("收货记账小工具") self.root.geometry("{}x{}+{}+{}".format(main_widht, main_height, main_xoffset, main_yoffset)) self.root.resizable(width=False, height=False) self.toplevel_id = 0 # 查询是否有今日的表,如果没有就创建今日表 self.db.create_db() self.update_queue = queue.Queue(4) self.msgbox = msgbox(self.root, self.logger) self.check_input = check_input.check_input(self.root, self.msgbox, self.logger) self.window_putinstorage = window_put_in_storage(self.root, self.db, self.check_input, self.msgbox, self.update_queue, self.logger) self.windos_sellgoods = windos_sell_goods(self.root, self.db, self.check_input, self.msgbox, self.update_queue, self.logger) #每个按钮的大小 w = int(int(global_variable.main_window['size']['w']) / 10) h = int(int(global_variable.main_window['size']['h']) / 10) #按钮的起始位置 x = int(w / 10) y = x #s表示连个按钮上下之间的距离 s = x font_size = int(w / 6) self.sell_button = tk.Button(self.root, command=self.FuncSell, text="售出", bd=10, bg='white', font=("黑体", font_size)) self.input_button = tk.Button(self.root, command=self.FuncInput, text="入库", bd=10, bg='white', font=("黑体", font_size)) self.tongji_day_button = tk.Button(self.root, command=self.FuncTJDay, text="当日", bd=10, bg='white',font=("黑体", font_size)) self.tongji_month_button = tk.Button(self.root, command=self.FuncTJMonth, text="当月", bd=10, bg='white',font=("黑体", font_size)) self.sell_button.place(x=x, y=y, width=w, height=h) y = y + h + s self.input_button.place(x=x, y=y, width=w, height=h) y = y + h + s self.tongji_day_button.place(x=x, y=y, width=w, height=h) y = y + h + s self.tongji_month_button.place(x=x, y=y, width=w, height=h) #计算主窗口显示商品信息窗口的长宽高 display_start_x = x + w + s display_start_y = x # 两侧留出 x 大小的空余空间 display_width = int(global_variable.main_window['size']['w']) - display_start_x - x # 底部留出 x 大小的空余空间 display_height = int(global_variable.main_window['size']['h']) - display_start_y - x # 参考自https://cloud.tencent.com/developer/ask/130543 # 参考自https://www.cnblogs.com/qwangxiao/p/9940972.html clos = ('编号', '商品名称', '入库数量', '已卖数量', '库存剩余', '总成本', '总收入') self.display_info = ttk.Treeview(self.root, columns=clos, show='headings') for col in clos: self.display_info.heading(col, text=col) self.display_info.grid(row=1, column=0, columnspan=2) # 设置列的宽度和对齐方式 w = int(display_width / 10) self.display_info.column('0', width=w, anchor='center') self.display_info.column('1', width=w*2, anchor='center') self.display_info.column('2', width=w, anchor='center') self.display_info.column('3', width=w, anchor='center') self.display_info.column('4', width=w, anchor='center') self.display_info.column('5', width=w*2, anchor='center') self.display_info.column('6', width=w*2, anchor='center') self.display_info.place(x=display_start_x, y=display_start_y, width=display_width, height=display_height) # 创建刷新显示的线程 t1 = threading.Thread(target=self.ThreadUpdateDisplay, args=()) t1.setDaemon(True) t1.start() except Exception as e: self.logger.error("class init error:{}".format(e)) def ThreadUpdateDisplay(self): while True: try: if not self.update_queue.empty(): msg = self.update_queue.get() dbmsg_list = self.db.getall() dbmsg_list.sort(key=lambda e: e[0], reverse=False) alreadyExitsItem = self.display_info.get_children() for dbitem in dbmsg_list: in_display = False for displayitem in alreadyExitsItem: displayitem_text = self.display_info.item(displayitem, "values") if dbitem[0] == int(displayitem_text[0]): in_display = True #更新总库存数量显示 if dbitem[3] != int(displayitem_text[2]): self.display_info.set(displayitem, 2, dbitem[3]) #更新已售出数量显示 if dbitem[4] != int(displayitem_text[3]): self.display_info.set(displayitem, 3, dbitem[4]) #更新总成本显示 if dbitem[5] != float(displayitem_text[5]): self.display_info.set(displayitem, 5, dbitem[5]) #更新总收入显示 if dbitem[6] != float(displayitem_text[6]): self.display_info.set(displayitem, 6, dbitem[6]) #更新剩余库存数量显示 self.display_info.set(displayitem, 4, dbitem[3] - dbitem[4]) break if in_display is False: #id, 商品名, 商品名拼音, 总库存, 总售出数量, 库存剩余, 总成本, 总收入 item = [dbitem[0], dbitem[1], dbitem[3], dbitem[4], dbitem[3] - dbitem[4], dbitem[5], dbitem[6]] self.display_info.insert("", "end", values=item) global_variable.goods_list.append([dbitem[0], dbitem[1], dbitem[2]]) except Exception as e: self.logger.error("ThreadUpdateDisplay error:{}".format(e)) def FuncSell(self): self.windos_sellgoods.show(0.75, 0.65) def FuncInput(self): self.window_putinstorage.show(0.3, 0.1) def FuncTJDay(self): ''' self.inputtop = tk.Toplevel(self.root) self.inputtop.geometry(size) self.inputtop.resizable(width=False, height=False) # 设置右上角的X功能 self.inputtop.protocol("WM_DELETE_WINDOW", lambda arg=self.inputtop: self.FuncButtonCancel(arg)) # 设置窗口始终在最上层 self.inputtop.wm_attributes("-topmost", 1) self.inputtop.title('入库信息输入框') # self.inputtop.overrideredirect(True) #隐藏边框标题 # self.inputtop.positionfrom(who="user") self.toplevel_id = self.inputtop ''' tkm.showinfo('警告','已存在总金额信息') def FuncTJMonth(self): self.logger.info(' FuncTJMonth') def FuncSetting(self): self.logger.info(' FuncSetting') def FuncHelp(self): self.logger.info(' FuncHelp') def FuncVersion(self): self.logger.info(' FuncVersion') def FuncUserRegister(self): self.logger.info(' FuncUserRegister') def FuncUserLogin(self): self.logger.info(' FuncUserLogin') def FuncUserQuit(self): self.logger.info(' FuncUserQuit') # 完成布局 def gui_arrang(self): menu = tk.Menu(self.root) # mb0 = Menubutton(self.root, text="用户xxx") cascade0 = tk.Menu(menu, tearoff=False) cascade0.add_command(label="注册", command=self.FuncUserRegister) cascade0.add_separator() cascade0.add_command(label="登陆", command=self.FuncUserLogin) cascade0.add_separator() cascade0.add_command(label="退出", command=self.FuncUserQuit) menu.add_cascade(label="用户", menu=cascade0) menu.add_command(label='设置', command=self.FuncSetting) menu.add_command(label='帮助', command=self.FuncHelp) cascade1 = tk.Menu(menu, tearoff=False) cascade1.add_command(label='版本信息', command=self.FuncVersion) cascade1.add_separator() cascade1.add_checkbutton(label='试用30天') cascade1.add_separator() cascade1.add_radiobutton(label='七七八八') cascade1.add_radiobutton(label='不三不四') menu.add_cascade(label='About', menu=cascade1) self.root['menu'] = menu #初始化完成后,主动刷新显示区域 self.update_queue.put('update')