【PyQt6】小说下载DrissionPage及阅读PyQt6

2024-02-25 22:44

本文主要是介绍【PyQt6】小说下载DrissionPage及阅读PyQt6,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1 简介
  • 2 DrissionPage
    • demo
  • 3 阅读界面
    • 3.1 Qt Designer
  • 3.2 界面类
  • 总结
  • 2024年2月25日 更新

1 简介

看到一本小说 《无敌六皇子》 【https://www.xsobiquge.org/book/178299/】看小说简介觉得挺有意思的,想读一读。浏览器阅读 不能保存进度,就好烦。想着就爬下来,本地看。

看着挺简单的网站,requests 就只能爬个目录页,分章内容总是被拒,UA Refer Cookie 以及所有的请求头都加了,也没有效果,最终还是回到浏览器去,此时 DrissionPage 就用上了。

2 DrissionPage

DrissionPage 号称同时实现“写得快”和“跑得快”,试过以后还真是巨方便。
DrissionPage 的教程我就略过不谈了,网上有总结的,感谢哪些前辈们的分享。
我就直接分享一下 具体的爬虫代码吧, 代码量真的很少

demo

from DrissionPage import SessionPage
import os
import time
import random
import re# 创建页面对象
page = SessionPage()subpages = []reg = r"第(\d+)章.*"
pat = re.compile(reg)def formatTitle(title):match = pat.search(title)if match:idx = match.group(1)res = title.replace(idx, f'{idx:0>4}')return resreturn titledef download_catalog(url):page.get(start_url)# 根据 xpath 或 css selector 查找xpath = '//*[@id="list"]/dl/dd'lists = page.eles(f'xpath:{xpath}')for li in lists:a = li.ele('tag:a')href = a.attr('href')title = a.texttitle = formatTitle(title)# print(a.attr('href'), a.text)subpages.append({'href': href, 'title': title})print(f'{url} 下载完成')def download_chapter():for i in range(min_chapters-1, max_chapters):dic = subpages[i]time.sleep(random.random() * 2)ret = page.get(dic['href'])if not ret:print(ret)return# //*[@id="content"]xpath = '//*[@id="content"]'elem = page.ele(f'xpath:{xpath}')context = elem.textwith open(f"{dic['title']}.txt", 'w', encoding='utf-8') as f:lines = context.splitlines()for line in lines:line = line.strip()if line == '网页版章节内容慢,请下载爱阅小说app阅读最新内容':breakif line:f.write('\t'+line+'\n')print(f'{dic['title']} 下载完成')if __name__ == '__main__':book_name = "无敌六皇子"start_url = 'https://www.xsobiquge.org/book/178299/'min_chapters = 401max_chapters = 600if not os.path.exists(book_name):os.mkdir(book_name)download_catalog(start_url)os.chdir(book_name)download_chapter()

3 阅读界面

小说的分章终于保存到了本地,txt 格式,直接使用 VSC 看,那个阅读体验真的不好。于是就顺手写了一个阅读器,大体上就是用 QTextEdit 来阅读,调整一下字体大小,行高,宽度,上一章 下一章的功能,基本就能满足要求,阅读进度使用 json 保存
在这里插入图片描述

3.1 Qt Designer

用 Designer 简单写个界面,东西很少,看图就明白

加载页面使用 self.ui = load_ui.loadUi(“Novel.ui”, self)
这种方式有利于看界面效果,但没代码提示,写代码不友好
建议界面定型后,使用 pyuic6 把ui文件转成 py文件,再导入
在这里插入图片描述
在这里插入图片描述

3.2 界面类

界面类,这一部分也没啥东西,直接上代码看吧

from PyQt6.QtCore import QTimer, QSettings, Qt
from PyQt6.QtGui import QCloseEvent, QKeyEvent, QPalette, QColor
from PyQt6.QtWidgets import (QMainWindow,QWidget,QApplication,QFileDialog,QSplitter,QStyleFactory,
)
from PyQt6.uic import load_ui
import os
import jsonclass MainWindow(QMainWindow):# ================= 构造函数 =============================def __init__(self, parent: QWidget = None):super().__init__(parent)# --------------------------------- 加载界面 -------------------------------------------self.ui = load_ui.loadUi("Novel.ui", self)# --------------------------------- 设置属性 -------------------------------------------self.dir_path = Noneself.filename = Noneself.verBar = 0# --------------------------------- 设置 splitter -------------------------------------splitter = self.ui.splittersplitter.setStretchFactor(0, 1)splitter.setStretchFactor(1, 4)splitter.setHandleWidth(1)# --------------------------------- 设置 菜单项  -------------------------------------opd = self.ui.opendir_actopd.triggered.connect(self.opendir_act_triggered)# -- 设置 QListWidget 文件目录listw = self.ui.listWidgetlistw.currentTextChanged.connect(self.currentFileChanged)# -----------------设置 QPlainTextEdit 文件阅读区 -------------------------------------pte = self.ui.plainTextEditfont = pte.font()font.setFamily("楷体")font.setPointSize(30)pte.setFont(font)pte.setReadOnly(True)# pte.setViewportMargins(0, 10, 0, 10)# -- 导入设置数据       -------------------------------------------------------if not os.path.exists("data.txt"):returnwith open("data.txt", "r", encoding="utf-8") as f:dic = json.loads(f.read())self.dir_path = dic["path"]self.file = dic["file"]font.setPointSize(dic["pointSize"])pte.setFont(font)self.verBar = dic["verBar"]self.update_listWidget()# -- 链接信号# pte.cursorPositionChanged.connect(self.cursorPositionChanged)# pte.verticalScrollBar().valueChanged.connect(self.cursorPositionChanged)def cursorPositionChanged(self, value):pte = self.ui.plainTextEdit# pte.verticalScrollBar().blockSignals(True)max = pte.verticalScrollBar().maximum()if max - value > 50:value -= 50else:value = maxpte.verticalScrollBar().setValue(value)# def f():#     pte.verticalScrollBar().blockSignals(False)# QTimer.singleShot(100, f)passdef update_listWidget(self):listw = self.ui.listWidgetlistw.blockSignals(True)# 保存当前目录cur_dir = os.getcwd()os.chdir(self.dir_path)files = os.listdir(self.dir_path)if not files:returnlistw.clear()listw.addItems(files)# 切换回当前目录os.chdir(cur_dir)def f():listw.setCurrentItem(None)listw.blockSignals(False)idx = files.index(self.file)listw.setCurrentRow(idx)QTimer.singleShot(100, f)def opendir_act_triggered(self):self.dir_path = QFileDialog.getExistingDirectory()if self.dir_path:listw = self.ui.listWidgetlistw.blockSignals(True)# 保存当前目录cur_dir = os.getcwd()os.chdir(self.dir_path)files = os.listdir(self.dir_path)if not files:returnfiles = [file for file in files if os.path.isfile(file) and file != "data.txt"]listw.clear()listw.addItems(files)# 切换回当前目录os.chdir(cur_dir)def f():listw.setCurrentItem(None)listw.blockSignals(False)QTimer.singleShot(100, f)def currentFileChanged(self, file):self.setWindowTitle(file)self.filename = filepte = self.ui.plainTextEdit# 保存当前目录cur_dir = os.getcwd()os.chdir(self.dir_path)with open(file, "r", encoding="utf-8") as f:lines = f.readlines()os.chdir(cur_dir)# text_cursor = QTextCursor()pte.clear()text_cursor = pte.textCursor()width = pte.width()TextBlockFormat = text_cursor.blockFormat()TextBlockFormat.setLeftMargin(width * 0.1)TextBlockFormat.setRightMargin(width * 0.1)TextBlockFormat.setBottomMargin(50)TextBlockFormat.setLineHeight(150, 1)TextBlockFormat.setTextIndent(20 * 4)text_cursor.setBlockFormat(TextBlockFormat)for line in lines:text_cursor.insertText(line.strip() + "\n")pte.verticalScrollBar().setValue(self.verBar)def closeEvent(self, a0: QCloseEvent) -> None:pte = self.ui.plainTextEditif self.filename:pte = self.ui.plainTextEditfont = pte.font()dict = {"path": self.dir_path,"file": self.filename,"pointSize": font.pointSize(),"verBar": pte.verticalScrollBar().value(),}# os.chdir(self.dir_path)with open("data.txt", "w", encoding="utf-8") as f:f.write(json.dumps(dict, ensure_ascii=False))# 保存 self.ui.splitter 的状态splitter_saveState(self.ui.splitter)return super().closeEvent(a0)def keyReleaseEvent(self, a0: QKeyEvent) -> None:# print('*'*20)pte = self.ui.plainTextEditmatch a0.key():# 上一章case Qt.Key.Key_Left:nextrow = self.ui.listWidget.currentRow() - 1if nextrow > -1:self.ui.listWidget.setCurrentRow(nextrow)# self.verBar = 0pte.verticalScrollBar().setValue(0)a0.accept()# 下一章case Qt.Key.Key_Right:nextrow = self.ui.listWidget.currentRow() + 1if nextrow < self.ui.listWidget.count():self.ui.listWidget.setCurrentRow(nextrow)self.verBar = 0pte.verticalScrollBar().setValue(0)a0.accept()return super().keyReleaseEvent(a0)def splitter_restoreState(splitter: QSplitter):set = QSettings("splitterSizes", QSettings.Format.IniFormat)splitter.restoreState(set.value("splitterSizes"))def splitter_saveState(splitter: QSplitter):set = QSettings("splitterSizes", QSettings.Format.IniFormat)set.setValue("splitterSizes", splitter.saveState())if __name__ == "__main__":qApp = QApplication([])qApp.setStyle(QStyleFactory.create("fusion"))palette = qApp.palette()palette.setColor(QPalette.ColorRole.Base, QColor(31, 31, 31))palette.setColor(QPalette.ColorRole.Text, QColor(78, 201, 176))palette.setColor(QPalette.ColorRole.Window, QColor(43, 43, 43))palette.setColor(QPalette.ColorRole.Highlight, QColor(38, 79, 120))palette.setColor(QPalette.ColorRole.HighlightedText, QColor(255, 255, 255))palette.setColor(QPalette.ColorRole.ButtonText, QColor(204, 204, 204))qApp.setPalette(palette)mw = MainWindow()mw.showMaximized()splitter_restoreState(mw.ui.splitter)qApp.exec()

总结

到此这个阅读器也就能马马虎虎的使用了,翻页的时候不太友好,因为 QTextEdit 翻页的时候,默认翻的是viewport 的大小,对于文字来说,有时会卡半行,真想重写 QTextEdit 的空格键啊,有机会再说。
最后再说一句 Python 真的很方便啊,能随手写写小工具

2024年2月25日 更新

阅读器代码有了更新, QTextEdit 加了 事件过滤器, 重写了 空格键, 翻页的时候少移动 30像素, 另外如果页面到底自动下一章功能

我一直还在想 怎么把 QEvent类 转成 QKeyEvent , 结果完全没有必要, 只要事件类型是 keypress ,就直接当 QKeyEvent 用

代码就不发了, 发链接吧

小说爬虫

这篇关于【PyQt6】小说下载DrissionPage及阅读PyQt6的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/746936

相关文章

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

Python下载Pandas包的步骤

《Python下载Pandas包的步骤》:本文主要介绍Python下载Pandas包的步骤,在python中安装pandas库,我采取的方法是用PIP的方法在Python目标位置进行安装,本文给大... 目录安装步骤1、首先找到我们安装python的目录2、使用命令行到Python安装目录下3、我们回到Py

Python使用DrissionPage中ChromiumPage进行自动化网页操作

《Python使用DrissionPage中ChromiumPage进行自动化网页操作》DrissionPage作为一款轻量级且功能强大的浏览器自动化库,为开发者提供了丰富的功能支持,本文将使用Dri... 目录前言一、ChromiumPage基础操作1.初始化Drission 和 ChromiumPage

使用DrissionPage控制360浏览器的完美解决方案

《使用DrissionPage控制360浏览器的完美解决方案》在网页自动化领域,经常遇到需要保持登录状态、保留Cookie等场景,今天要分享的方案可以完美解决这个问题:使用DrissionPage直接... 目录完整代码引言为什么要使用已有用户数据?核心代码实现1. 导入必要模块2. 关键配置(重点!)3.

使用国内镜像源优化pip install下载的方法步骤

《使用国内镜像源优化pipinstall下载的方法步骤》在Python开发中,pip是一个不可或缺的工具,用于安装和管理Python包,然而,由于默认的PyPI服务器位于国外,国内用户在安装依赖时可... 目录引言1. 为什么需要国内镜像源?2. 常用的国内镜像源3. 临时使用国内镜像源4. 永久配置国内镜

Python如何快速下载依赖

《Python如何快速下载依赖》本文介绍了四种在Python中快速下载依赖的方法,包括使用国内镜像源、开启pip并发下载功能、使用pipreqs批量下载项目依赖以及使用conda管理依赖,通过这些方法... 目录python快速下载依赖1. 使用国内镜像源临时使用镜像源永久配置镜像源2. 使用 pip 的并

jdk21下载、安装详细教程(Windows、Linux、macOS)

《jdk21下载、安装详细教程(Windows、Linux、macOS)》本文介绍了OpenJDK21的下载地址和安装步骤,包括Windows、Linux和macOS平台,下载后解压并设置环境变量,最... 目录1、官网2、下载openjdk3、安装4、验证1、官网官网地址:OpenJDK下载地址:Ar

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

python 3.8 的anaconda下载方法

《python3.8的anaconda下载方法》本文详细介绍了如何下载和安装带有Python3.8的Anaconda发行版,包括Anaconda简介、下载步骤、安装指南以及验证安装结果,此外,还介... 目录python3.8 版本的 Anaconda 下载与安装指南一、Anaconda 简介二、下载 An

Java下载文件中文文件名乱码的解决方案(文件名包含很多%)

《Java下载文件中文文件名乱码的解决方案(文件名包含很多%)》Java下载文件时,文件名中文乱码问题通常是由于编码不正确导致的,使用`URLEncoder.encode(filepath,UTF-8... 目录Java下载文件中文文件名乱码问题一般情况下,大家都是这样为了解决这个问题最终解决总结Java下