python +pyqt5实现小说章节错乱重组排序

一、现象及原理

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.运行结果

上传项目到githubhttps://github.com/KilterW/Fiction-sort-and-reorganization.git

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值