游戏辅助工具(python3+pyqt4)
有个游戏,杀星很麻烦. 星的信息是从谣言频道发出的,但是谣言频道信息太多,需要提取. 星是有时效的,所以只显示最近的几十项就好.
本来不想做界面的,可是cmd实在是太丑了,而且占桌面空间,本来屏幕就小.
使用工具: python3+pyqt4
实际运行图是这样的.
游戏窗口是1024*768居中屏幕, 必须偏移一下辅助程序窗口,所以辅助程序窗口没有了右边框.
要读取的聊天记录样例
#W12:47:18#n #[#image<0>#]#W听闻#Y#<シ淡味ˇby#>#n在通天塔中大展雄风,成功完成了通天塔的所有挑战,真是实力超群啊! #W12:47:20#n #[#image<0>#]#W听闻在#R钱塘观潮五线#n,#Y地猛星#n#R(84级)#n将在#R三分钟后#n下凡云游到#Z五龙窟四层#Z,期间星君将挑选幸运的道友进行指点,各位道友快去该地图等候吧! #W12:47:22#n #[#image<0>#]#W财神巡游,在低等级练功区地图留下了一些宝箱,来帮助50级以下的新手玩家,大家快去拣吧! #W12:47:22#n #[#image<0>#]#W听闻在#R钱塘观潮六线#n,#Y地猛星#n#R(84级)#n将在#R三分钟后#n下凡云游到#Z五龙窟四层#Z,期间星君将挑选幸运的道友进行指点,各位道友快去该地图等候吧! #W12:47:24#n #[#image<0>#]#W#Y地煞星#n#R(63级)#n已经出现在#Z乾元山#Z,各位道友若有实力,可前往挑战! #W12:47:33#n #[#image<0>#]#W听闻在#R钱塘观潮二线#n,#Y地猛星#n#R(84级)#n将在#R三分钟后#n下凡云游到#Z五龙窟三层#Z,期间星君将挑选幸运的道友进行指点,各位道友快去该地图等候吧!
程序源码
写了两个版本, 第一版本使用QTableWidget, 第二版使用QTableView
QTableWidget
#!/usr/bin/env python3 import os import sys import re import stat import datetime from collections import OrderedDict from itertools import islice from PyQt4 import QtGui class Table(QtGui.QDialog): def __init__(self, parent=None): super(Table, self).__init__(parent) self.setGeometry(1075, 85, 320, 640) self.setWindowIcon(QtGui.QIcon('.\\qt.ico')) layout = QtGui.QGridLayout() #self.led = QtGui.QLineEdit("Sample") self.searchboxLayout = QtGui.QGridLayout() self.label1 = QtGui.QLabel("等级: 从") self.searchboxLayout.addWidget(self.label1, 0, 0) self.lineEdit_start = QtGui.QLineEdit() self.lineEdit_start.setText("30") self.searchboxLayout.addWidget(self.lineEdit_start, 0, 1) self.label = QtGui.QLabel("到") self.searchboxLayout.addWidget(self.label, 0, 2) self.lineEdit_end = QtGui.QLineEdit() self.lineEdit_end.setText("105") self.searchboxLayout.addWidget(self.lineEdit_end, 0, 3) self.btn = QtGui.QPushButton("刷新") self.searchboxLayout.addWidget(self.btn, 0, 4) layout.addLayout(self.searchboxLayout, 0, 0, 1, 1) self.table = QtGui.QTableWidget() self.table.setColumnCount(5) #layout.addWidget(self.led, 0, 0) #layout.addWidget(self.btn, 0, 0) #layout.addWidget(self.table, 1, 0) layout.addWidget(self.table, 1, 0, 1, 1) self.table.setHorizontalHeaderLabels(["时间","星名","等级","地点","线"]) self.table.setColumnWidth(0, 56) self.table.setColumnWidth(1, 48) self.table.setColumnWidth(2, 30) self.table.setColumnWidth(3, 70) self.table.setColumnWidth(4, 52) self.show_data() self.btn.clicked.connect(self.show_data) self.setLayout(layout) QtGui.QShortcut(QtGui.QKeySequence("Ctrl+R"), self, self.get_data) def show_data(self): level_start = int(self.lineEdit_start.text()) if not level_start: level_start = 35 level_end = int(self.lineEdit_end.text()) if not level_end: level_end= 200 if level_start > level_end: level_start, level_end = level_end, level_start print(level_start, level_end) self.ct, self.server, self.myfile, self.foo = self.get_data() self.bar = list(filter(lambda x: level_start <= int(x[2]) <= level_end, self.foo.values())) self.table.setRowCount(len(self.bar)) n = 0 for i in self.bar: self.table.setItem(n, 0, QtGui.QTableWidgetItem(i[0])) self.table.setItem(n, 1, QtGui.QTableWidgetItem(i[1])) self.table.setItem(n, 2, QtGui.QTableWidgetItem(i[2])) self.table.setItem(n, 3, QtGui.QTableWidgetItem(i[3])) self.table.setItem(n, 4, QtGui.QTableWidgetItem(i[4])) self.table.setRowHeight(n, 21) n += 1 item = self.table.item(n, 0) #self.table.scrollToItem(item, QtGui.QAbstractItemView.PositionAtCenter) #self.table.selectRow(n) print(n, self.ct, self.myfile, len(self.foo)) self.setWindowTitle("%s %s" % (self.server, self.ct)) def get_data(self): return main_h() def fun(x): return re.findall('#W(.{2}:.{2}:.{2})#n.*image.*#W听闻在#R.{3,4}.{1,3}线#n,#Y[天地].星#n#R(\d+级)#n.*云游到#Z.*#Z', x) def reader(myfile): with open(myfile, 'rb') as f: buf = f.read() ubuf = buf.decode('cp936', 'ignore') stars = list(filter(fun, ubuf.split('\n'))) if len(stars) <= 60: last = 0 else: last = -60 return stars[last:] def get_info(orig): return re.findall('#W(.{2}:.{2}:.{2})#n.*image.*#W听闻在#R(.{3,4})(.{1,3}线)#n,#Y([天地].星)#n#R((\d+)级)#n.*云游到#Z(.*)#Z', orig)[0] def main_h(): path = r'D:\Program Files (x86)\asktao\chat' stars = OrderedDict() for myfile in map(lambda x: os.path.join(path, x), os.listdir(path)[-1:]): for m, orig in enumerate(reader(myfile)[::-1]): t, server, line, name, level, position = get_info(orig) if len(position) < 4: position += " " #if int(level.replace('级', '')) < 105: stars[str(m)] = [t, name, level, position, line] #for k, v in stars.items(): #print("\t".join(v)) ct = os.stat(myfile).st_mtime + 8*3600 ct = datetime.datetime.utcfromtimestamp(ct).strftime("%Y-%m-%d %H:%M:%S") return (ct, server, myfile, stars) def main(): import sys app = QtGui.QApplication(sys.argv) t = Table() t.show() sys.exit(app.exec_()) if __name__ == '__main__': main()
QTableView
#!/usr/bin/env python3 #coding=gbk import os import sys import re import stat import datetime from collections import OrderedDict from itertools import islice from PyQt4 import QtCore, QtGui,QtSql class Table(QtGui.QWidget): def __init__(self, parent=None): super(Table, self).__init__(parent) self.db = self.conn() self.ct, self.server, self.myfile, self.foo = "", "", "", "" self.query = "" self.setGeometry(1070, 85, 320, 640) self.setWindowIcon(QtGui.QIcon('.\\qt.ico')) self.layout = QtGui.QGridLayout() self.searchboxLayout = QtGui.QGridLayout() self.label1 = QtGui.QLabel("等级: 从") self.searchboxLayout.addWidget(self.label1, 0, 0) self.lineEdit_start = QtGui.QLineEdit() self.lineEdit_start.setText("30") self.searchboxLayout.addWidget(self.lineEdit_start, 0, 1) self.label = QtGui.QLabel("到") self.searchboxLayout.addWidget(self.label, 0, 2) self.lineEdit_end = QtGui.QLineEdit() self.lineEdit_end.setText("105") self.searchboxLayout.addWidget(self.lineEdit_end, 0, 3) self.btn = QtGui.QPushButton("刷新") self.searchboxLayout.addWidget(self.btn, 0, 4) self.labelnote = QtGui.QLabel("<strong>提示:</strong>") self.searchboxLayout.addWidget(self.labelnote, 1, 0) self.labelnote1 = QtGui.QLabel("先保存再刷新") self.searchboxLayout.addWidget(self.labelnote1, 1, 1) self.layout.addLayout(self.searchboxLayout, 0, 0, 1, 1) self.table = QtGui.QTableView() self.layout.addWidget(self.table, 1, 0, 1, 1) self.show_data() self.btn.clicked.connect(self.show_data) QtGui.QShortcut(QtGui.QKeySequence("Ctrl+R"), self, self.show_data) self.setLayout(self.layout) def conn(self): db = QtSql.QSqlDatabase.addDatabase("QSQLITE"); db.setDatabaseName(":memory:") #db.setDatabaseName("test.db3") db.open() self.ddl(db) return db def ddl(self, db): self.query = QtSql.QSqlQuery(db) self.query.exec_("create table foo1(a1 char(255),\ a2 char(255), a3 int, a4 char(255),\ a5 char(255), a6 text unique)") def insert(self): self.ct, self.server, self.myfile, self.foo = self.get_data() self.query = QtSql.QSqlQuery(self.db) for k, v in self.foo.items(): sql = "insert into foo1 values\ ('%s', '%s', '%s', '%s', '%s',\ '%s %s')" % (v[0], v[1], v[2], v[3],\ v[4], self.server, " ".join(v)) self.query.exec(sql) self.db.commit() def select(self): model = QtSql.QSqlQueryModel() level_start = int(self.lineEdit_start.text()) if not level_start: level_start = 35 level_end = int(self.lineEdit_end.text()) if not level_end: level_end= 200 if level_start > level_end: level_start, level_end = level_end, level_start sql = """ select a1,a2,a3,a4,a5 from foo1 where a3 >= %s and a3 <= %s order by a1 desc limit 30""" % (level_start, level_end) model.setQuery(sql, self.db) title = ("时间","星名","等级","地点","线") for n, s in enumerate(title): model.setHeaderData(n, QtCore.Qt.Horizontal, s) return model def show_data(self): self.insert() model = self.select() self.table.setModel(model) width = (56, 48, 30, 70, 52) for n, w in enumerate(width): self.table.setColumnWidth(n, w) for i in range(40): self.table.setRowHeight(i, 21) r = len(self.foo) self.table.selectRow(r) self.setWindowTitle("%s %s" % (self.server, self.ct)) print(self.ct, self.myfile, r) def get_data(self): return main_h() def fun(x): return re.findall('#W(.{2}:.{2}:.{2})#n.*image.*#W听闻在#R.{3,4}.{1,3}线#n,#Y[天地].星#n#R(\d+级)#n.*云游到#Z.*#Z', x) def reader(myfile): with open(myfile, 'rb') as f: buf = f.read() ubuf = buf.decode('cp936', 'ignore') stars = list(filter(fun, ubuf.split('\n'))) if len(stars) <= 60: last = 0 else: last = -60 return stars[last:] def get_info(orig): return re.findall('#W(.{2}:.{2}:.{2})#n.*image.*#W听闻在#R(.{3,4})(.{1,3}线)#n,#Y([天地].星)#n#R((\d+)级)#n.*云游到#Z(.*)#Z', orig)[0] def main_h(): path = r'D:\Program Files (x86)\asktao\chat' stars = OrderedDict() files = os.listdir(path) keeper = lambda x: os.path.join(path, x) if x is files[-1] else\ os.unlink(os.path.join(path, x)) for myfile in filter(lambda x: x, map(keeper, files)): for m, orig in enumerate(reader(myfile)): t, server, line, name, level, position = get_info(orig) if len(position) < 4: position += " " stars[str(m)] = [t, name, level, position, line] for k, v in stars.items(): print("\t".join(v)) ct = os.stat(myfile).st_mtime + 8*3600 ct = datetime.datetime.utcfromtimestamp(ct).strftime("%Y-%m-%d %H:%M:%S") return (ct, server, myfile, stars) def main(): import sys app = QtGui.QApplication(sys.argv) t = Table() t.show() sys.exit(app.exec_()) if __name__ == '__main__': main()
文本筛选,关键就是正则了, 正则能写得出来,其它都是小事了.
有些东西不想改了.像时间这种 ct = os.stat(myfile).st_mtime + 8*3600 , 一直记不住用哪个类里的方法来获取.
最近更新了wine, 那个游戏终于比较流畅地在运行了, 不过,fcitx无法输入文字, 如果是从clipboard复制, 得到的是类似"\x243"这种, 源编码呃.所以,还是windows下玩比较好了.