打开压缩包会看到四个文件。
使用说明已经简单交代了软件的用法。
templete.xls 和 data.txt 文件可以先忽视,后续会交代这两个文件的作用。
先打开 pyYouthExcel-ver2.0.exe
初次打开软件会看到两个窗口。
左边黑乎乎的窗口是控制台
当程序出错或者无响应的时候,可以通过控制台看到反馈的信息。
右边的窗口就是程序的主界面。
这个界面就是软件主界面
最上面是数据获取设置,清除掉输入框中的文本可以看到输入提示。
没错,这里获取的就是文件夹中的两个文件信息。
当然也可以自己创建相关的文件,点击选择可以选到相关的路径中
获取完之后,界面会出现完整的路径
这个路径和之前的 data.txt 路径有什么不同效果吗?
其实两个路径都实现了相同的功能。
路径很长的称之为绝对路径,从盘符开始索引。
路径很对的称之为相对路径,从当前程序所在的目录开始索引。
下面就是 输入网页URL 的区域了
这里可以将青年之声的提问链接输入进去
当然也可以输入多条链接,链接之间用回车分行即可
再下面就是选择文件保存路径
基本操作相信也不用说明了,直接输入文件名称则以相对路径保存到当前程序启动目录中。
确认输入无误之后,点击一键统计。
执行完毕之后可以在目录中看到多了两个文件
其实只是多出了生成文件, qt.conf 文件在打开程序之后自动生成,不影响使用。
下面打开 test.xls 文件
所有的统计操作都通过程序完成了。
程序操作讲解完毕,重点来看看配置文件都是什么吧
data.txt 存储的是同学的相关信息
另外有一个快捷的操作,务必使用此方法。
在Excel上复制同学们的信息
可以直接粘贴到txt文档中
代码背后会识别这个间隔,输入正确才能让程序正确运行。
手动输入这个间隔 不是按空格 而是按键盘 Tab 键
!!! 这里输入的姓名是指 青年之声用户名 !!!
如果用户名与真实姓名不一致 请输入 青年之声用户名 !!!
程序会根据 输入的用户名进行匹配 !!!
输入不匹配就不会输出 合格 !!!
请务必检查清楚 !!!
最后就是 templete.xls 了
其实这个文件只是获取它的基础板式
如果不想要这个基础板式,可以去掉配置文件的索引。
这样子生成的就是配置文件部分的 Excel 文档
代码分析,源代码
这个部分与软件使用无关,只是个人总结一下代码编写的过程。
下面贴出软件的源码
from PyQt4.QtCore import *from PyQt4.QtGui import *import sysimport reimport xlwtimport xlrdimport xlutils.copyimport requestsimport timeimport osimport tracebackclass Downloader(QDialog): def __init__(self): QDialog.__init__(self) # 创建窗口 self.resize(750,300) layout = QGridLayout() self.infoTitle = QLabel('<center><b>数据获取设置</b></center>') self.title = QLabel('<center><b>输入网页URL</b></center>') self.url = QPlainTextEdit() self.save_location = QLineEdit() self.DB_location = QLineEdit() self.templete_location = QLineEdit() self.progress = QProgressBar() download = QPushButton('一键统计') browse = QPushButton('选择') DB_browse = QPushButton('选择') templete_browse = QPushButton('选择') self.save_location.setPlaceholderText('文件保存路径') self.DB_location.setPlaceholderText('青年之声用户名信息存储文本') self.templete_location.setPlaceholderText('Excel模板文件') self.progress.setValue(0) self.progress.setAlignment(Qt.AlignHCenter) num = 1 layout.addWidget(self.infoTitle,num-1,0,1,4) layout.addWidget(self.DB_location,num,0,1,3) layout.addWidget(DB_browse,num,3,1,1) layout.addWidget(self.templete_location,num 1,0,1,3) layout.addWidget(templete_browse,num 1,3,1,1) layout.addWidget(self.title,num 2,0,1,4) layout.addWidget(self.url,num 3,0,1,4) layout.addWidget(self.save_location,num 4,0,1,3) layout.addWidget(browse,num 4,3,1,1) layout.addWidget(self.progress,num 5,0,1,4) layout.addWidget(download,num 6,0,1,4) self.setLayout(layout) self.setWindowTitle('青年之声统计神器 - 制作者:16级数字媒体技术2班梁伟添') self.DB_location.setText('data.txt') self.templete_location.setText('templete.xls') self.setFocus() download.clicked.connect(self.download) browse.clicked.connect(self.browse_file) DB_browse.clicked.connect(self.browse_DB) templete_browse.clicked.connect(self.browse_templete) def browse_file(self): save_file = QFileDialog.getSaveFileName(self, caption='保存文件到', directory='.',filter='Excel (*.xls)') self.save_location.setText(QDir.toNativeSeparators(save_file)) def browse_DB(self): DB_file = QFileDialog.getOpenFileNames(self, caption='获取青年之声用户名信息', directory='.',filter='txt (*.txt)') # 空数组处理 if not DB_file: return self.DB_location.setText(QDir.toNativeSeparators(DB_file[0])) def browse_templete(self): templete_file = QFileDialog.getOpenFileNames(self, caption='获取模板Excel文件', directory='.',filter='Excel (*.xls)') # 空数组处理 if not templete_file: return self.templete_location.setText(QDir.toNativeSeparators(templete_file[0])) def download(self): url = self.url.toPlainText() save_location = self.save_location.text() DB_location = self.DB_location.text() templete_location = self.templete_location.text() print('开始写入') if DB_location == '': QMessageBox.warning(self, 'Warning', '用户数据不能为空') return try: with open(DB_location,'r') as f: info = f.read() except Exception: QMessageBox.warning(self, 'Warning', '青年之声用户名信息获取失败\n检查文件路径是否正确') return reg = r'(.*)' studentReg = re.compile(reg) self.studentName = re.findall(studentReg,info) # 清除空字符串 self.studentName = [x for x in self.studentName if x != ''] # 遍历获取 url 输入框中的所有链接 reg = r'(http.*)' urldReg = re.compile(reg) urlList = re.findall(urldReg,url) # 创建 excel 对象 和 excel 表 if templete_location != '': try: rb = xlrd.open_workbook(templete_location,formatting_info=True) book = xlutils.copy.copy(rb) sheet = book.get_sheet(0) except Exception: QMessageBox.warning(self, 'Warning', 'Excel模板获取失败\n检查文件路径是否正确') return else: book = xlwt.Workbook(encoding='utf-8', style_compression=0) sheet = book.add_sheet('青年之声统计', cell_overwrite_ok=True) # 设置字体样式 font0 = xlwt.Font() font0.name = '微软雅黑' alignment = xlwt.Alignment() alignment.horz = xlwt.Alignment.HORZ_CENTER alignment.vert = xlwt.Alignment.VERT_CENTER style0 = xlwt.XFStyle() style0.font = font0 style0.alignment = alignment try: az = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' column = 4 r = 0 for name in self.studentName: userClass = name.split('\t')[0] userNum = name.split('\t')[1] userName = name.split('\t')[2] sheet.write(r 2, 0, r 1 ,style0) sheet.write(r 2, 1, userClass ,style0) sheet.write(r 2, 2, userNum ,style0) sheet.write(r 2, 3, userName ,style0) r = 1 # 分离处理 url 链接 for originUrl in urlList: # 获取url reg = r'quId=(.*?)&' quIdReg = re.compile(reg) quId = re.findall(quIdReg,originUrl)[0] url = 'https://api.12355.net/pc/service/getReplysByQuestionId?quId=%s&page=1&rows=500' % quId askUrl = 'https://api.12355.net/pc/service/getQuesDetail?quId=%s' % quId try: # 获取html页面 response = requests.get(url) html = response.text response = requests.get(askUrl) askHtml = response.text except Exception: traceback.print_exc() QMessageBox.warning(self, 'Warning', '网络连接失败') return if html == '': break # 获取提问时间 reg = r''askTime':'(.*?)'' askReg = re.compile(reg) askList = re.findall(askReg,askHtml) # 获取用户名 reg = r''creatorName':'(.*?)'' nameReg = re.compile(reg) nameList = re.findall(nameReg,html) # 获取回复信息 reg = r''replyContent':'(.*?)'' contentReg = re.compile(reg) contentList = re.findall(contentReg,html) # 获取回复时间 reg = r''replyTime':'(.*?)'' timeReg = re.compile(reg) timeList = re.findall(timeReg,html) row = 0 # 批量生成超链接 sheet.write(1, column, xlwt.Formula('HYPERLINK('%s';'问题%s')' % (originUrl,column-3)),style0) for name in self.studentName: index = 0 # 检测回复是否符合条件 for creatorName in nameList: # 检测回复是否匹配 用户名 if name.split('\t')[2] == creatorName: # 检测是否是问题当天的时间进行回复 if askList[0].split(' ')[0] == timeList[index].split(' ')[0]: # 去除标点 检测回复是否超过5个字 reg = r'(?u)\w' textReg = re.compile(reg) textList = re.findall(textReg,contentList[index]) if len(textList) >= 5: sheet.write(row 2, column , '合格' ,style0) break index = 1 row = 1 # 进度条加载 percent = (column-3) * 100 / len(urlList) self.progress.setValue(int(percent)) print(str(int(percent)) '%') # 纵向求和 判断数组是否越界的情况 if column < 26: sheet.write(row 2, column , xlwt.Formula('COUNTIF(%s3:%s%s,\'合格\')' % (az[column],az[column],row 2)) ,style0) else: letter = '%s%s' % (az[int(column/26-1)],az[column%26]) sheet.write(row 2, column , xlwt.Formula('COUNTIF(%s3:%s%s,\'合格\')' % (letter,letter,row 2)) ,style0) column = 1 # 横向求和 r = 0 column -= 1 sheet.write(r 1, column 1 , '合计' ,style0) # 判断数组是否越界的情况 if column < 26: for name in self.studentName: sheet.write(r 2, column 1 , xlwt.Formula('COUNTIF(%s%s:%s%s,\'合格\')' % (az[4],r 3,az[column],r 3)) ,style0) r = 1 sheet.write(r 2, column 1 , xlwt.Formula('SUM(%s%s:%s%s)' % (az[4],r 3,az[column],r 3)) ,style0) else: letter = '%s%s' % (az[int(column/26-1)],az[column%26]) for name in self.studentName: sheet.write(r 2, column 1 , xlwt.Formula('COUNTIF(%s%s:%s%s,\'合格\')' % (az[4],r 3,letter,r 3)) ,style0) r = 1 sheet.write(r 2, column 1 , xlwt.Formula('SUM(%s%s:%s%s)' % (az[4],r 3,letter,r 3)) ,style0) book.save(save_location) except Exception: traceback.print_exc() QMessageBox.warning(self, 'Warning', '数据写入失败') return print('完成写入') QMessageBox.information(self, 'Information', '数据写入完成') self.progress.setValue(0) # # 清空输入 # self.url.setText('') # self.save_location.setText('')app = QApplication(sys.argv)dl = Downloader()dl.show()app.exec_()
总结
Python开发比起C 简单很多,想起C 的MFC框架就很难受。