摸鱼神器——python命令行小说阅读器实现
文章目錄
- 一、摸魚思路
- 二、閱讀器實(shí)現(xiàn)思路
- 三、實(shí)現(xiàn)
- 1、拆分章節(jié)
- 2、翻頁
- 3、閱讀主邏輯
- 4、完整代碼
- 四、效果展示 & 源碼(測試數(shù)據(jù)——詭秘之主)獲取
一、摸魚思路
在命令行中進(jìn)行小說閱讀,可以通過我們IDE編碼界面做掩護(hù),通過IDE開啟一個(gè)小的終端以命令行的方式進(jìn)行閱讀,這樣可以表現(xiàn)得正在努力調(diào)試代碼的樣子。
二、閱讀器實(shí)現(xiàn)思路
- 準(zhǔn)備好測試數(shù)據(jù)(小說的txt文件)
- 將小說的源文檔按章節(jié)進(jìn)行拆分
– 按章節(jié)閱讀,上下章翻頁 - 每次打開時(shí)能緊接著上次閱讀的內(nèi)容
三、實(shí)現(xiàn)
基于上述的思路,我們的這個(gè)類就初始化出來了
class Reader:def __init__(self, book_name, txt_path):self.book_name = book_name self.txt_path = txt_pathself.db = DbConfig(self.book_name, "./{}.sqlite3".format(self.book_name))# 該方法見文章底部self.db.initial_table() # 初始化數(shù)據(jù)庫,用來存放閱讀歷史self.contents = [] # 章節(jié)名稱self.book = self.split_book_chapter() # 拆分后的章節(jié)字典1、拆分章節(jié)
拆分章節(jié)我們可以直接使用re.split()通過正在表達(dá)式作為分隔符進(jìn)行拆分。
一般小說每一章的結(jié)構(gòu)為 第***章 XXXXXX,基于此,我們可以通過兩種正則表達(dá)式進(jìn)行拆分
一個(gè)是re.split('第,*章',mybook),
另一個(gè)是 re.split('\n第',mybook)
實(shí)現(xiàn)如下
劃分完成后存入字典(PS:python3.6以后的字典都變成了有序字典,所以在上述倒數(shù)第二行代碼的位置,直接取字典的keys作為文本的目錄。如果是python3.6以下的版本記得使用OrderDict進(jìn)行操作)
2、翻頁
翻頁則是根據(jù)當(dāng)前閱讀的章節(jié)名稱,從目錄中獲取當(dāng)前章節(jié)前一章與后一章的名稱
def get_index(self, key_name):"""根據(jù)書的章節(jié)名稱,獲取前一章與后一章:param key_name::return:"""this_index = self.contents.index(key_name)last_chapter = self.contents[this_index - 1]next_chapter = self.contents[this_index + 1]return last_chapter, next_chapter3、閱讀主邏輯
這里閱讀的主邏輯,當(dāng)每次開始閱讀時(shí),從數(shù)據(jù)庫中獲取歷史記錄(上一次退出腳本時(shí),看到的章節(jié)),如果沒有記錄,則從第一章開始。
注意:python的版本需要達(dá)到3.6以及以上,因?yàn)?.6以后的字典為有序字典,低于這個(gè)版本的,需要把字典修改為OrderDict。
每次監(jiān)聽到翻頁命令時(shí),則對當(dāng)前的章節(jié)名稱進(jìn)行存儲(chǔ)。
4、完整代碼
操作sqlite的工具類db.utils.py
import sqlite3 import tracebackclass DbConfig:"""從數(shù)據(jù)庫中獲取小說的相關(guān)章節(jié)"""def __init__(self, table, db_path):self.table = tableself.db_path = db_pathdef initial_table(self):"""初始化數(shù)據(jù)以及庫表:return:"""conn = sqlite3.connect(self.db_path, check_same_thread=False)cursor = conn.cursor()cursor.execute("""create table if not exists gmzz(chapter_name text,chapter_content text,last_chapter text,update_time bigint);""")conn.commit()conn.close()def get_params(self, *params):"""自定義獲取參數(shù):param params:list: 想要獲取的字段:return:"""try:conn = sqlite3.connect(self.db_path, check_same_thread=False)cursor = conn.cursor()sql = "select {} from {} ".format(",".join(list(params[0])), self.table)rtn = cursor.execute(sql)result = list(rtn)conn.close()return resultexcept Exception as e:traceback.print_exc()def simple_query(self, sql):try:conn = sqlite3.connect(self.db_path, check_same_thread=False)cursor = conn.cursor()rtn = cursor.execute(sql)conn.close()return list(rtn)except Exception as e:traceback.print_exc()def add_one(self,fields, values):try:conn = sqlite3.connect(self.db_path, check_same_thread=False)cursor = conn.cursor()sql = "insert into {} ({}) values ('{}')".format(self.table, ",".join(fields), ",".join(values))print(sql)rtn = cursor.execute(sql)conn.commit()conn.close()return rtnexcept Exception as e:traceback.print_exc()def update_one(self, field_name, update_value):"""更新某個(gè)字段:param field_name: 字段名稱:param update_value: 跟新值:return:"""try:sql = "update {table} set {field_name} = '{update_value}'".format(table=self.table,field_name=field_name,update_value=update_value)conn = sqlite3.connect(self.db_path, check_same_thread=False)cursor = conn.cursor()cursor.execute(sql)conn.commit()conn.close()except Exception as e:traceback.print_exc()腳本主程序
# -*- coding: utf-8 -*- import codecs import os import re import sys import platformfrom db_utils import DbConfigclass Reader:def __init__(self, book_name, txt_path):self.book_name = book_nameself.txt_path = txt_pathself.db = DbConfig(self.book_name, "./{}.sqlite3".format(self.book_name))self.db.initial_table() # 初始化數(shù)據(jù)庫,用來存放閱讀歷史self.contents = [] # 章節(jié)名稱self.book = self.split_book_chapter()def split_book_chapter(self):"""讀取文本文件,并將文本按章節(jié)劃分:param txt_path::return:"""book_content = {}with codecs.open(self.txt_path, "r", encoding="gbk") as f:text = f.read().strip()chapters = re.split("\n第", text)for chapter in chapters:text = chapter.split("\n")title = text[0]text = "\n".join(text)book_content[title] = textself.contents = list(book_content.keys())return book_contentdef get_index(self, key_name):"""根據(jù)書的章節(jié)名稱,獲取前一章與后一章:param key_name::return:"""this_index = self.contents.index(key_name)last_chapter = self.contents[this_index - 1]next_chapter = self.contents[this_index + 1]return last_chapter, next_chapterdef start_read(self, chapter_name=None):"""開始閱讀, 章節(jié)名稱為空,且數(shù)據(jù)庫中沒有歷史記錄時(shí),從第一章開始:param chapter_name: 章節(jié)名稱:return:"""last_chapter = self.db.get_params(["last_chapter"])# 如果沒有歷史記錄或者指定章節(jié),則是第一次閱讀,在數(shù)據(jù)庫中新增if not last_chapter:self.db.add_one(["last_chapter"], [self.contents[0]])if not chapter_name:chapter_name = last_chapter[0] if last_chapter else self.contents[0]chapter_name = chapter_name[0] if isinstance(chapter_name, tuple) else chapter_nameread_content = "".join(self.book.get(chapter_name,"當(dāng)前章節(jié)不存在"))print(read_content)forward = ""while forward not in ["n", "b", "q"]:forward = input("""n、下一章\nb、上一章\nq、退出""")last_chapter_name, next_chapter_name = self.get_index(chapter_name)if forward == "q":sys.exit(0)# 根據(jù)命令選擇上一章或者下一章,并更新歷史記錄if forward == "n":self.db.update_one("last_chapter", next_chapter_name)return next_chapter_nameif forward == "b":self.db.update_one("last_chapter", last_chapter_name)return last_chapter_nameif __name__ == '__main__':mybook = Reader("gmzz", "test.txt")chapter_name = Nonewhile True:if platform.system().lower() == "windows":os.system('cls')if platform.system().lower() == "linux":os.system('clear')chapter_name = mybook.start_read(chapter_name)四、效果展示 & 源碼(測試數(shù)據(jù)——詭秘之主)獲取
最后運(yùn)行的效果就如下圖所示
源碼+測試數(shù)據(jù)獲取,關(guān)注以下公眾號(hào),回復(fù)0070獲取
總結(jié)
以上是生活随笔為你收集整理的摸鱼神器——python命令行小说阅读器实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【文献翻译】LSD: A Fast Li
- 下一篇: python sklearn NMF人脸