基于PyQt5和requests的小说在线阅读器(小说爬虫)
效果:
- 绝对布局
- 无章节预加载
- 在不关闭的情况下再次搜索存在bug
代码:
python部分:
import sys
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *import random
import requests
from lxml import etree
from bs4 import BeautifulSoup
from urllib.parse import quotedef dataGet(url):"""网页源代码获取"""user_agent_list = ['Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ''Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3','Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50','Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)','Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)','Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1','Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11','Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)','Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0','Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',]user_agent = random.choice(user_agent_list)headers = {'User-Agent': user_agent}i = 0while i < 4: # 4s超时, 4次重试try:response = requests.get(url, headers, timeout=4)response.encoding = 'gbk'return response.textexcept requests.exceptions.RequestException:i += 1def novelSearch(data):"""在小说搜索网页获取小说信息"""soup = BeautifulSoup(data, features='lxml')lis = soup.find_all('li')novelList = []novelInfoList = []linkList = []for li in lis:html = etree.HTML(str(li))class_ = html.xpath('//span[@class="s1"]/text()')name = html.xpath('//span[@class="s2"]/a/text()')link = html.xpath('//span[@class="s2"]/a/@href')new = html.xpath('//span[@class="s3"]/a/text()')author = html.xpath('//span[@class="s4"]/text()')time = html.xpath('//span[@class="s5"]/text()')now = html.xpath('//span[@class="s7"]/text()')if class_ and now and new:novelList.append(name[0])novelInfoList.append([class_[0], name[0], link[0], new[0], author[0], time[0], now[0]])linkList.append(link[0])return [novelList, novelInfoList, linkList]def chapterGet(data, link):"""在目录界面获取小说章节"""html = etree.HTML(data)chapters_name = html.xpath('//dl/dd/a/text()')chapters_link = html.xpath('//dl/dd/a/@href')chapters = []for i, j in zip(chapters_name, chapters_link):chapters.append([i, link + j])return chaptersdef contentGet(data):"""获取小说内容"""string = data.replace('<br />', '').replace('<br>', '')html = etree.HTML(string)title = html.xpath('//div[@class="bookname"]/h1/text()')content = html.xpath('//div[@id="content"]/text()')return [title[0], content[0]]def Del_line(string):"""删除文本空行"""res = [x for x in string if x.split()]string = "".join(res)return stringclass SearchThread(QThread):"""搜索线程"""_signal1 = pyqtSignal(list)_signal2 = pyqtSignal(list)_signal3 = pyqtSignal()def __init__(self):super(SearchThread, self).__init__()def __del__(self):self.destroyed()def set_name(self, string):self.novelName = stringdef run(self):searchURL = 'https://www.52bqg.com/modules/article/search.php?searchkey=' + self.novelNameurl = quote(searchURL, safe=";/?:@&=+$,", encoding="gbk")data = dataGet(url)lists = novelSearch(data)if lists[0]:self._signal1.emit(lists[0])self._signal2.emit(lists[1])else:self._signal3.emit()class ChapterThread(QThread):"""搜索线程"""_signal1 = pyqtSignal(list)def __init__(self):super(ChapterThread, self).__init__()def __del__(self):self.destroyed()def set_link(self, string):self.link = stringdef run(self):data = dataGet(self.link)chapters = chapterGet(data, self.link)self._signal1.emit(chapters)class ReadThread(QThread):"""搜索线程"""_signal1 = pyqtSignal(list)def __init__(self):super(ReadThread, self).__init__()def __del__(self):self.destroyed()def set_link(self, string):self.link = stringdef run(self):data = dataGet(self.link)content = contentGet(data)self._signal1.emit(content)class MainWin(QWidget):novelList = []novelInfoList = []chapterList = []def __init__(self):super().__init__()self.setFixedSize(1500, 900)self.setWindowTitle('小说在线阅读器')self.setWindowIcon(QIcon('./static/images/web.png'))self.label = QLabel('小说名称:', self)self.label.move(20, 30)self.input = QLineEdit(self)self.input.setPlaceholderText('输入小说名称')self.input.move(120, 20)self.btu = QPushButton('搜索', self)self.btu.move(340, 20)self.label_1 = QLabel('搜索结果', self)self.label_1.setObjectName('search_header')self.label_1.move(20, 80)self.list = QListWidget(self)self.list.clicked.connect(self.choice)self.list.resize(372, 300)self.list.move(20, 121)self.label_2 = QLabel('章节列表', self)self.label_2.setObjectName('search_header')self.label_2.move(20, 430)self.list_1 = QListWidget(self)self.list_1.clicked.connect(self.chapterChoice)self.list_1.resize(372, 400)self.list_1.move(20, 470)self.label_3 = QLabel('章节内容', self)self.label_3.setObjectName('reader')self.label_3.move(430, 20)self.reader = QTextEdit(self)self.reader.setReadOnly(True)self.reader.resize(1052, 750)self.reader.move(430, 61)self.btu_1 = QPushButton('上一章', self)self.btu_1.setObjectName('chapter')self.btu_1.move(830, 820)self.btu_2 = QPushButton('下一章', self)self.btu_2.setObjectName('chapter')self.btu_2.move(970, 820)self.btu.clicked.connect(self.search)self.btu_1.clicked.connect(self.previousChapter)self.btu_2.clicked.connect(self.nextChapter)self.thread = SearchThread()self.thread._signal1.connect(self.callback_1)self.thread._signal2.connect(self.callback_2)self.thread._signal3.connect(self.nothing)self.thread_1 = ChapterThread()self.thread_1._signal1.connect(self.callback_3)self.thread_2 = ReadThread()self.thread_2._signal1.connect(self.callback_4)file = QFile('./static/qss/win.css')file.open(QFile.ReadOnly)qss = str(file.readAll(), encoding='utf-8')file.close()self.setStyleSheet(qss)self.show()def search(self):self.list.clear()self.list_1.clear()self.reader.clear()name = self.input.text()if name == '':QMessageBox.information(self, "提示", "请输入关键字", QMessageBox.Ok, QMessageBox.Ok)returnself.thread.set_name(name)self.thread.start()def addNovel(self):for i in self.novelList:n = self.novelList.index(i)self.list.addItem(i)QApplication.processEvents()def addChapter(self):for i in self.chapterList:n = self.chapterList.index(i)self.list_1.addItem(i[0])QApplication.processEvents()def callback_1(self, msg):self.novelList = msgself.addNovel()def callback_2(self, msg):self.linList = []for i in msg:self.linList.append(i[2])i[0] = '小说分类:' + i[0]i[1] = '小说名称:' + i[1]i[2] = '小说链接:' + i[2]i[3] = '最新章节:' + i[3]i[4] = '小说作者:' + i[4]i[5] = '最近更新时间:' + i[5]i[6] = '更新状态:' + i[6]self.novelInfoList.append([i[0], i[1], i[2], i[3], i[4], i[5], i[6]])def nothing(self):QMessageBox.information(self, "提示", "未搜索到任何结果", QMessageBox.Ok, QMessageBox.Ok)def choice(self, index):r = index.row()string = '\n'.join(self.novelInfoList[r])box = QMessageBox.information(self, "详细信息", string, QMessageBox.No | QMessageBox.Yes, QMessageBox.Yes)if box == QMessageBox.Yes:self.link = self.linList[r]self.thread_1.set_link(self.link)self.thread_1.start()def callback_3(self, msg):self.chapterList = msgself.addChapter()def chapterChoice(self, index):self.r = index.row()chapterLink = self.chapterList[self.r][1]self.thread_2.set_link(chapterLink)self.thread_2.start()def callback_4(self, msg):title = msg[0]content = msg[1]string = title + '\n' + contentself.reader.setText(string)QApplication.processEvents()def nextChapter(self):self.r += 1chapterLink = self.chapterList[self.r][1]self.thread_2.set_link(chapterLink)self.thread_2.start()self.list_1.setFocus()self.list_1.setCurrentRow(self.r)def previousChapter(self):self.r -= 1chapterLink = self.chapterList[self.r][1]self.thread_2.set_link(chapterLink)self.thread_2.start()if __name__ == "__main__":app = QApplication(sys.argv)win = MainWin()sys.exit(app.exec_())
qss部分:
QLabel {font-size: 20px;
}QLabel#search_header {font-size: 20px;border-top-left-radius: 10px;border-top-right-radius: 10px;border: 1px groove gray;width: 100px;padding: 10px;padding-left: 140px;padding-right: 140px;
}QLabel#reader {font-size: 20px;border-top-left-radius: 10px;border-top-right-radius: 10px;border: 1px groove gray;width: 100px;padding: 10px;padding-left: 480px;padding-right: 480px;
}QLineEdit {font-family: "Microsoft YaHei UI";border-radius: 7px;min-height: 30px;max-height: 30px;padding: 2px 4px;width: 200px;border: 1px groove gray;
}QLineEdit:hover {background-color: #F7F7F7;
}QTextEdit {font-family: "华文楷体";font-size: 25px;border-bottom-left-radius: 10px;border-bottom-right-radius: 10px;padding: 2px 4px;border: 1px groove gray;
}QPushButton {font-family: "宋体";min-height: 30px;max-height: 30px;font-size: 20px;background-color: #EEEEEE;border-radius: 5px;width: 41px;border: 1px groove gray;padding: 2px 4px;transition:background-color 2000ms;
}QPushButton:hover {background-color: #DDDDDD;
}QPushButton:pressed {background-color: #C4C4C4;
}QListWidget {border: 1px groove gray;border-bottom-left-radius: 10px;border-bottom-right-radius: 10px;padding: 2px 4px;font-size: 20px;
}QPushButton#chapter {font-family: "Microsoft YaHei UI";min-height: 30px;max-height: 30px;font-size: 20px;background-color: #EEEEEE;border-radius: 5px;width: 70px;border: 1px groove gray;padding: 2px 4px;transition:background-color 2000ms;
}QPushButton#chapter:hover {background-color: #DDDDDD;
}QPushButton#chapter:pressed {background-color: #C4C4C4;
}
基于PyQt5和requests的小说在线阅读器(小说爬虫)相关推荐
- Aardio做的一个小说在线阅读器
这是一片没有diao用的文章,没有任何技术含量. 看小说,因为太多广告,不过路由器拦截了大部分广告,其实体验也还好,不过还是想着自己做一个在线阅读器. 在线阅读器采用的是web.form.以及jq取文 ...
- 基于Android的小说在线阅读器软件APP
在我国,有很多人在业余时间喜欢看小说,因为小说独特性,可以通过书籍.手机甚至在电脑上进行阅读.当然,根据不同的人阅读的习惯不一样,一部分的喜欢书籍阅读,一部分喜欢在手机上阅读.两者都有其优势,前者不易 ...
- UWP_小说在线阅读器:功能要求与技术要求
注:2017年2月23日正式提上日程 学了WP开发也有一年了,也没做过什么软件的.17年进发UWP,锻炼自己一下.做一个开源的小说阅读器吧. 既然开发一个软件.所以要设计一下吧. 功能要求: 可能要用 ...
- python +pyqt 小说下载阅读器 转语音合成 ,基于PyQt5生成图形页面(已打成exe可直接下载使用)
最近在学习python,写了一款简单的小说下载器,基本功能都已经实现,废话不多说 直接上效果 简单说下功能把 1.支持在线阅读,翻页 键盘快捷键上下(阅读) 左右(翻页).可以导出TXT到本地,默认是 ...
- java微信小程序文学小说在线阅读销售网站 uniapp 小程序
在网络发表小说不管对读者还是对小说作者都是有直接好处的,对于读者来说不光在网络上迅速得到作者最新发表的小说,而对于小说读者来说把作品发表在网络上他能以最快的速度获得到读者对作品的意见.这样作者可以最快 ...
- asp.net925-小型小说在线阅读网站系统
项目编号:asp.net925-小型小说在线阅读网站系统 运行环境:VS+SQL 开发工具:VS2010及以上版本 数据库:SQL2008及以上版本 使用技术:HTML+JS+HTML 开发语言:C# ...
- 爬取漫画网址的并生产一个在线阅读器
文章目录 爬取漫画网址的并生产一个在线阅读器 代码分析 实现代码 爬取漫画网址的并生产一个在线阅读器 代码分析 如果要做一个爬虫的话,一定要会看网页的源代码,看有没有自己想要的数据, http://m ...
- Reabble – 出色的 Kindle RSS 在线阅读器
简介:Reabble 是一款专门为 Kindle 浏览器优化的 RSS 阅读器,基于在线阅读器 Inoreader 服务,可以让你在Kindle 上每日阅读新鲜内容. 买kindle有一段时间了,经常 ...
- 基于Core Text实现的TXT电子书阅读器
本篇文章的项目地址基于Core Text实现的TXT电子书阅读器. 最近花了一点时间学习了iOS的底层文字处理的框架Core Text.在网上也参考很多资料,具体的资料在文章最后列了出来,有兴趣的可参 ...
最新文章
- 最早接触到的计算机编程语言——c语言
- 基于Guava实现的文件复制
- 使用条件卷积进行实例和全景分割
- tomcat https ssl测试
- 获取网络状态ConnectivityManager
- java多线程通信基础(面向厕所编程)
- 华为模拟器 ENSP 教程
- uniapp 公众号 微信授权登录
- BZOJ3505 CQOI2014数三角形(组合数学)
- 为什么JBX写的代码在编译时,总是少字符呢?
- #Excel公式应用#从数据透视表进一步汇总文本信息
- npm 中 --save 与 --save-dev 的区别
- LINKERD 2.11 中文实战手册
- 计算机毕业设计Java某银行OA系统某银行OA系统演示2021(源代码+数据库+系统+lw文档)
- 超链接 a标签 虚线框 虚线 去除虚线框
- 【BZOJ3503】【Cqoi2014】和谐矩阵 高斯消元,解异或方程组
- 同步,异步,全双工,半双工区别!
- 转:青年教师科研方向规划
- 动态域名解析--每步动态域名解析
- matlab app设计步骤_1.1数学建模与MATLAB–MATLAB入门