摸鱼神器——python命令行小说阅读器实现
文章目錄
- 一、摸魚思路
- 二、閱讀器實現思路
- 三、實現
- 1、拆分章節
- 2、翻頁
- 3、閱讀主邏輯
- 4、完整代碼
- 四、效果展示 & 源碼(測試數據——詭秘之主)獲取
一、摸魚思路
在命令行中進行小說閱讀,可以通過我們IDE編碼界面做掩護,通過IDE開啟一個小的終端以命令行的方式進行閱讀,這樣可以表現得正在努力調試代碼的樣子。
二、閱讀器實現思路
- 準備好測試數據(小說的txt文件)
- 將小說的源文檔按章節進行拆分
– 按章節閱讀,上下章翻頁 - 每次打開時能緊接著上次閱讀的內容
三、實現
基于上述的思路,我們的這個類就初始化出來了
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() # 初始化數據庫,用來存放閱讀歷史self.contents = [] # 章節名稱self.book = self.split_book_chapter() # 拆分后的章節字典1、拆分章節
拆分章節我們可以直接使用re.split()通過正在表達式作為分隔符進行拆分。
一般小說每一章的結構為 第***章 XXXXXX,基于此,我們可以通過兩種正則表達式進行拆分
一個是re.split('第,*章',mybook),
另一個是 re.split('\n第',mybook)
實現如下
劃分完成后存入字典(PS:python3.6以后的字典都變成了有序字典,所以在上述倒數第二行代碼的位置,直接取字典的keys作為文本的目錄。如果是python3.6以下的版本記得使用OrderDict進行操作)
2、翻頁
翻頁則是根據當前閱讀的章節名稱,從目錄中獲取當前章節前一章與后一章的名稱
def get_index(self, key_name):"""根據書的章節名稱,獲取前一章與后一章: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、閱讀主邏輯
這里閱讀的主邏輯,當每次開始閱讀時,從數據庫中獲取歷史記錄(上一次退出腳本時,看到的章節),如果沒有記錄,則從第一章開始。
注意:python的版本需要達到3.6以及以上,因為3.6以后的字典為有序字典,低于這個版本的,需要把字典修改為OrderDict。
每次監聽到翻頁命令時,則對當前的章節名稱進行存儲。
4、完整代碼
操作sqlite的工具類db.utils.py
import sqlite3 import tracebackclass DbConfig:"""從數據庫中獲取小說的相關章節"""def __init__(self, table, db_path):self.table = tableself.db_path = db_pathdef initial_table(self):"""初始化數據以及庫表: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):"""自定義獲取參數: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):"""更新某個字段: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() # 初始化數據庫,用來存放閱讀歷史self.contents = [] # 章節名稱self.book = self.split_book_chapter()def split_book_chapter(self):"""讀取文本文件,并將文本按章節劃分: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):"""根據書的章節名稱,獲取前一章與后一章: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):"""開始閱讀, 章節名稱為空,且數據庫中沒有歷史記錄時,從第一章開始:param chapter_name: 章節名稱:return:"""last_chapter = self.db.get_params(["last_chapter"])# 如果沒有歷史記錄或者指定章節,則是第一次閱讀,在數據庫中新增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,"當前章節不存在"))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)# 根據命令選擇上一章或者下一章,并更新歷史記錄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)四、效果展示 & 源碼(測試數據——詭秘之主)獲取
最后運行的效果就如下圖所示
源碼+測試數據獲取,關注以下公眾號,回復0070獲取
總結
以上是生活随笔為你收集整理的摸鱼神器——python命令行小说阅读器实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【文献翻译】LSD: A Fast Li
- 下一篇: hic超融合厂商路坦力nutanix之产