一、现象及原理
1.现象:在网上下载小说时,偶尔会遇到小说章节顺序错乱,或章节重复的情况,现编写代码实现小说的排序重组
2.原理:
①提取章节序号存入列表s
②提取各个章节内容存入列表m
③对列表s进行数据转换(中文序号转换为阿拉伯数字,eg:一百二十五---->125)
④将s和m组成dict
⑤将dict按照key进行排序
⑥输出新文件
⑦用pyqt5编写界面实现交互
⑧另:路径、文件检查;文件的读写
二、源码
1.排序实现,有详细注释
'''
author:Kilter.wang
time:2019/4/25
'''
class Fiction_Sort(object):
def __init__(self,path):
self.__path=path
self.__common_used_numerals = {'零': 0, '一': 1, '二': 2, '两': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9,
'十': 10, '百': 100, '千': 1000, '万': 10000, '亿': 100000000}
self.__error=""
self.new_path=""
#检验文件
def judge_format(self):
# 检验路径是否真实存在
if not os.path.exists(self.__path):
self.__error="路径不存在,请重新输入。。。"
#检验给出的路径是否是一个文件
elif not os.path.isfile(self.__path):
self.__error="该路径下没有发现文件,请确认路径是否正确"
#检验是否是txt
elif not os.path.splitext(os.path.split(self.__path)[1])[1] == ".txt":
self.__error="该文件不是txt,不符合要求"
else:
self.__error=self.sorted()
return self.__error
def sorted(self):
try:
fr = open(self.__path, 'r', encoding="utf-8")
txts = fr.readlines()
# 暂时存放每一章节内容的列表
l = []
# 存放章节序号的列表
s = []
# 列表元素为各个章节内容
m = []
# num :判断一章节内容读取完毕标志
# str_ :过渡的字符串
for x in txts:
if "第" and "章" in x and x[0] == "第":
num = True
l.append(x)
# 获取章节号
s.append(x.split("第")[1].split("章")[0])
else:
num = False
l.append(x)
if num:
# 对暂存的内容进行处理,得到各个章节内容
str_ = ""
for x in l[:-1]:
str_ += x
l[0] = l[-1]
l = l[0:1]
m.append(str_)
# 由于处理算法原因,导致最后一章节无法获取,故加此条件进行处理,存储最后一章节
elif x == txts[-1]:
str_ = ""
for x in l:
str_ += x
m.append(str_)
# 对章节编号为汉字的进行处理 转换为数字
i = 0
while i < len(s):
s[i] = self.chinese2digits(s[i])
i += 1
# 由于最初读取第一章时,进入了处理算法,而其章节内容此时为空,故列表s新增一位才可与m生成相对应的dict
s.insert(0, "0")
# 生成dict,s为key,m为value 由于字典key的唯一性,再进行dict生成时自动剔除了重复的章节
d = dict(zip(s, m))
# 对dict安装key进行排序,reverse:排序规则,bool值(默认为升序排列(False))
# item[0]表示按键排序,item[1]则表示按值排序 而单独使用item[0],测试发现排序逻辑和期望不符,故此使用int(item[0])
# 返回值为元组列表的形式 eg:[('no', 2), ('ok', 1)]
by_key = sorted(d.items(), key=lambda item: int(item[0]), reverse=False)
# 返回一个路径的目录名和文件名
p = os.path.split(self.__path)
# 新建排序完成的txt文件(在提供的该目录下-->文件名_新.txt)
self.new_path = p[0] + "\\" + os.path.splitext(p[1])[0] + '_新.txt'
# 写入文件
fw = open(self.new_path, 'w', encoding="utf-8")
for x in by_key:
#print(x[0])
fw.write(x[1])
finally:
fr.close()
fw.close()
reg="重组成功"
return reg
#将中文章节表达转换为阿拉伯数字表达
def chinese2digits(self,uchars_chinese):
total = 0
r = 1 # 表示单位:个十百千...
if uchars_chinese.isdigit():
total = uchars_chinese
else:
for i in range(len(uchars_chinese) - 1, -1, -1):
val = self.__common_used_numerals.get(uchars_chinese[i])
if val >= 10 and i == 0: # 应对 十三 十四 十*之类
if val > r:
r = val
total = total + val
else:
r = r * val
elif val >= 10:
if val > r:
r = val
else:
r = r * val
else:
total = total + r * val
return total
三、交互界面
1.使用pyqt5编写界面,基本操作见https://blog.csdn.net/a549742320/article/details/89482960
2.为控件添加背景色和修改字体颜色
选中控件---->右侧属性栏中找到styleSheet(图1)--->点击...跳转(图2)进行设置--->Add Color----->分别设置color(字体颜色)
\background-color(背景色)----->选择颜色(图3)------>ok
图1
图2
图3
3.为按钮添加点击事件
点击Edit Signals/Slots(图1)---->点击选中控件,鼠标不放拖到左侧控件栏任意处,弹窗(图2)--->点击Edit--->输入点击方法名
pushButton_click()(可任意写)----->点击"+"号----->ok---------->成功后如图4
图1
图2
图3
图4
4.将pyqt5的界面和python进行交互
4.1.将.ui转化为.py,具体见https://blog.csdn.net/a549742320/article/details/89482960
4.2 Fiction_Form.py ----->生成的该.py要进行处理,不然会报错---->
#MainWindow.setCentralWidget(self.centralwidget)
#MainWindow.setMenuBar(self.menubar)
#MainWindow.setStatusBar(self.statusbar)---->将这三行注释
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'Fiction_Form.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 570)
font = QtGui.QFont()
font.setPointSize(9)
MainWindow.setFont(font)
MainWindow.setStyleSheet("background-color: rgb(170, 255, 255);")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(320, 20, 191, 71))
font = QtGui.QFont()
font.setPointSize(23)
self.label.setFont(font)
self.label.setStyleSheet("color: rgb(255, 0, 0);\n"
"background-color: rgb(0, 170, 255);")
self.label.setTextFormat(QtCore.Qt.AutoText)
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(50, 130, 131, 41))
font = QtGui.QFont()
font.setPointSize(20)
self.label_2.setFont(font)
self.label_2.setObjectName("label_2")
self.txt_fpath = QtWidgets.QTextEdit(self.centralwidget)
self.txt_fpath.setGeometry(QtCore.QRect(180, 130, 601, 41))
font = QtGui.QFont()
font.setPointSize(14)
self.txt_fpath.setFont(font)
self.txt_fpath.setObjectName("txt_fpath")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(350, 310, 121, 51))
font = QtGui.QFont()
font.setFamily("微软雅黑")
font.setPointSize(16)
self.pushButton.setFont(font)
self.pushButton.setStyleSheet("color: rgb(255, 0, 0);\n"
"background-color: rgb(85, 170, 255);")
self.pushButton.setObjectName("pushButton")
self.lbl_Error = QtWidgets.QLabel(self.centralwidget)
self.lbl_Error.setGeometry(QtCore.QRect(10, 480, 401, 31))
font = QtGui.QFont()
font.setPointSize(10)
self.lbl_Error.setFont(font)
self.lbl_Error.setStyleSheet("background-color: rgb(0, 170, 255);\n"
"color: rgb(255, 0, 0);")
self.lbl_Error.setText("")
self.lbl_Error.setObjectName("lbl_Error")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(420, 480, 361, 31))
font = QtGui.QFont()
font.setPointSize(9)
self.label_4.setFont(font)
self.label_4.setTextFormat(QtCore.Qt.AutoText)
self.label_4.setObjectName("label_4")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(20, 210, 151, 41))
font = QtGui.QFont()
font.setPointSize(20)
self.label_3.setFont(font)
self.label_3.setObjectName("label_3")
self.lbl_new_path = QtWidgets.QLabel(self.centralwidget)
self.lbl_new_path.setGeometry(QtCore.QRect(180, 210, 601, 41))
font = QtGui.QFont()
font.setPointSize(14)
self.lbl_new_path.setFont(font)
self.lbl_new_path.setStyleSheet("background-color: rgb(0, 170, 255);\n"
"color: rgb(255, 0, 0);")
self.lbl_new_path.setText("")
self.lbl_new_path.setScaledContents(False)
self.lbl_new_path.setObjectName("lbl_new_path")
#MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
self.menubar.setObjectName("menubar")
#MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
#MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.pushButton.clicked.connect(MainWindow.pushButton_click)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Fiction_Sort"))
self.label.setText(_translate("MainWindow", "小说排序重组"))
self.label_2.setText(_translate("MainWindow", "小说路径:"))
self.pushButton.setText(_translate("MainWindow", "重组"))
self.label_4.setText(_translate("MainWindow", "tips:小说章节顺序错乱或者章节有重复,可以进行重组(txt格式)"))
self.label_3.setText(_translate("MainWindow", "重组后路径:"))
4.3 算法处理部分加入界面代码
导入界面生成的.py(Ui_MainWindow)---->初始化(__init__)---->编写按钮点击事件(pushButton_click())--->
show窗体()
import os
import sys
from PyQt5 import QtWidgets
from Fiction_Form import Ui_MainWindow
class Fiction_Sort_Form(QtWidgets.QWidget,Ui_MainWindow):
def __init__(self):
super(Fiction_Sort_Form, self).__init__()
self.setupUi(self)
def pushButton_click(self):
fpath=self.txt_fpath.toPlainText()
fiction_sort=Fiction_Sort(fpath)
reg=fiction_sort.judge_format()
self.lbl_Error.setText(reg)
self.lbl_new_path.setText(fiction_sort.new_path)
'''''''
if __name__ =="__main__":
app=QtWidgets.QApplication(sys.argv)
fiction_sort_form=Fiction_Sort_Form()
fiction_sort_form.show()
sys.exit(app.exec_())
四、生成.exe
1.代码编写完成后,可生成.exe方便使用,在cmd下--->.py所在的目录---->pyinstaller -F 文件名.py --noconsole------>
成功后会生成一个dist文件夹----->该文件夹下即为.exe
2.运行结果
上传项目到github:https://github.com/KilterW/Fiction-sort-and-reorganization.git