最近制作了一个从笔趣阁下载小说的小工具,写篇博客记录下这个工具的制作方法:
工具的功能:从笔趣阁网站上下载一个小说到电脑中,方面像我这样的书虫简单愉快的看小说(无黄页、无广告、一次下载、本地阅读~~)。

一、开发环境:

我的项目是在win10、python3.6开发的。当然并不要求完全和我的开发环境一致,python3应该是都可用的;

二、编程实现:

废话少说,直接开干!

2.1、进入笔趣阁主页,点击进入任何一本小说。比如在“最新入库小说”下随便找一本小说《飞天神皇》,进入其主页(https://www.biquge5200.cc/96_96609/),按F12查看调试信息。

2.2、创建类BQG:
创建类,并创建几个变量:
self.bookName ——– 用于保存小说名
self.file ——– 用于创建小说的保存文件
self.agentIP ——– 用于保存代理IP(防止被笔趣阁禁封IP)
selt.tool ——– 用于替代趴取到的页面中的一些符号

class BQG:def __init__(self):self.agentIP = AgentIp()#''  # 代理IP网址self.file = None    # 用于保存下载的小说--txt格式self.bookName = None   # 小说名

2.3、创建一个通过代理趴网站的函数:
创建函数getPage_proxy()并调用它,将小说主页(https://www.biquge5200.cc/96_96609/)上的内容全部趴下来,通过pageCode输出

def getPage_proxy(self, url):proxy = {'http':self.agentIP} #self.agentIP中保存的是代理ipproxy_support = urllib.request.ProxyHandler(proxy)opener = urllib.request.build_opener(proxy_support)opener.addheaders = [('User-agent','Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36')] urllib.request.install_opener(opener)response = urllib.request.urlopen(url)#需要添加‘ignore’参数,因为笔趣阁有的小说主页中的编码既有gbk又有utf-8,而笔趣阁header中charset=gbk,所以选择gbk并忽略utf-8pageCode = response.read().decode("gbk", 'ignore')         return pageCode

2.4、获取小说名:
调试窗口搜索小说名“飞天神皇”,能找到条目”飞天神皇”,此条及小说的名,通过如下代码获取小说名:(此函数中的pageCode即上一条中趴取的内容)

    def getBookName(self, pageCode):pattern = re.compile('<h1>(.*?)</h1>', re.S)bookName = re.search(pattern, pageCode) #匹配小说名,bookName[1]即小说名if bookName:print("\n\n准备下载小说:\t%s\n"%(bookName[1]))self.bookName = bookName[1]

2.5、获取所有章节的网站链接
观察各章节内容的规律,创建正则表达式获取章节名即网站链接,具体代码如下:

    def getChapters(self, pageCode):pattern = re.compile('<dd><a href="(.*?)">(.*?)</a></dd>', re.S)chapters = re.findall(pattern, pageCode)if chapters:filename = self.bookName + ".txt"print("创建小说文件:\t%s"%filename) # 创建小说文件 飞天神皇.txtfile = open(filename, 'r+') #打开此文件(文件不存在则创建)if file:print("\n=================== 依次下载各章节内容 ===================\n")for chapter in chapters: # 依次获取各章节内容print("获取章节:\t%s"%(chapter[1]))#chapter[0]--章节url链接 chapter[1]--章节名file.write(chapter[1])text = self.getOneChapterContent(chapter[0]) # 获取该章节内容file.write(text) # 写入章节内容到文件中file.close()else:print("文件创建or打开失败")

2.6、获取章节内容:
依次打开上一节中的各章网站链接,用F12查看调试信息,根据内容格式写正则表达式。趴取网页中所有内容,再通过正则表达式获取并该章小说内容。代码如下:

    def getOneChapterContent(self, chapterurl): # chapterurl即某章网站链接pageCode = self.getPage_proxy(chapterurl.strip()) # 通过代理ip趴取网站的内容if pageCode == None:return Nonepattern = re.compile('<div id="content".*?>(.*?)</div>', re.S) #创建正则表达式content = re.findall(pattern, pageCode) # 获取小说该章内容if content:pp = re.compile('<p>|</p>')text = re.sub(pp, "\n", content[0]) # 替换掉其中换行符return text #text中保存的即是该章节的内容return None

2.7、制作一个弹出框,用于输入网址链接
为了让软件能方便重用,制作一个输入框让程序每次运行起来的时候先弹出一个输入框,用户可用在此输入框中输入小说的主页网址,点击“确定”即可一键获取小说具体代码如下:

def pop_up_box():       #弹出并获取输入框def getBookUrl(): # 创建一个按键消息处理函数,按下确定安静,及获取输入框中的内容nonlocal book_urltry:book_url = str(var.get().strip())root.destroy()  #输入后直接关闭窗口except:book_url = 'Not a valid url.'book_url = Noneroot = tkinter.Tk(className='提示:请输入小说主页的网址')  # 弹出框框名root.geometry('400x80')     # 设置弹出框的大小 w x hroot.resizable(width=False, height=False) # 固定弹出框的大小label = tkinter.Label(root,text='yxrsh声明:\n本工具完全基于兴趣制作,完全免费,且禁止任何形式的商业用途\nQQ:1744058358') # 制作一个简单的声明标签(其实是小广告~~)label.pack(side = 'bottom')   # 将输入框放到弹出框靠左侧位置var = tkinter.StringVar()   # 输入框中的内容edit = tkinter.Entry(root, textvariable=var, width = '50')  # 设置"文本变量"为varedit.pack(side = 'left')   # 将输入框放到弹出框靠左侧位置bt = tkinter.Button(root, text='确定', command=getBookUrl)     # 按下此按钮(Input), 触发inputint函数bt.pack(side='right')   # 将输入按键框放到弹出框靠右侧位置root.mainloop() # 弹出弹出框return book_url # 返回获取到的小说主页链接

2.8、调用类BQG
整个工程到此基本完成了所有的小块,接下来就是组合起来,让程序跑起来了。上述程序有一些依赖库,需要导入到工程中

import urllib.request #趴网站需要
import re   #正则表达式需要
import tkinter    # 输入框需要

调用以下代码即可跑起程序了。。。

url = pop_up_box()  #获取小说主页网址(章节目录页)
if url:spider = BQG()spider.start(url)
else:print("请输入合理的网址")

2.9 改进
百度发现笔趣阁居然有新(https://www.biquge5200.cc/#)、旧(http://www.biquge.com.tw/)之分,前期调试软件都是基于新笔趣阁测试的,本工具无法获取旧笔趣阁中的小说。没办法,改呗!

a) 用当前工具获取旧笔趣阁小说时,根本获取不到网站,提示错误:
“urllib.error.URLError: urlopen error [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。”
也就是说使用代理还连不上网站了,那我试试不使用代理,结果尼玛还挺OK,好吧,不软原因怎么样,先取消代理吧。新建一个不用代理的获取网站信息的函数,将程序中调用的getPage_proxy()函数都换成getPage()函数。

    # 不使用代理的话,将程序中getPage_proxy()函数替代成getPage()函数def getPage(self, url):user_agent='Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36'header = {'User-Agent': user_agent}request = urllib.request.Request(url, headers = header)response = urllib.request.urlopen(request)pageCode = response.read().decode("gbk", "ignore")return pageCode

b) 完成上一步后能获取到各章节地址了,但是调用第一章就失败了,查看下获取到的第一章网站链接(/18_18698/8526643.html),居然和新笔趣阁不一样,不是一个完整的网址链接。从网站上点击进去其第一章网页(https://www.biquge.com.tw/18_18698/8526643.html),对比小说主页(https://www.biquge.com.tw/18_18698/),发现了还是有一定联系的:章节真实网址=主页+获取到的链接地址 - 连接处相同内容。ok,那我们创建一个这样的函数

def urlcat(head, tail):cnt = len(head) # 获取头部长度index = 0flag = Truewhile flag:if head.rfind(tail[0:index]) != -1: #查看相同部分的大小index += 1else:flag = Falseif index >= cnt:flag = False#返回链接后的地址       if index > 0:return (head + tail[index-1::])else:return head + tail

然后修改getChapters()函数,

file.write(chapter[1])real_url = chapter[0].strip() # 获取到的地址if real_url[0] == '/': # 如果地址以'/'开头,则将其与主页地址进行拼接real_url = urlcat(self.mainurl, real_url) text = self.getOneChapterContent(real_url)

c) 修改后,现在可以正常获取旧笔趣阁的小说啦,测试下最新的代码能否获取新笔趣阁小说,发现居然也很正常。好吧,我前期多此一举加了代理ip。不过还有点小缺陷,调试时发现,有时复制网页时没有复制进来”http://”部分,而是”www”开头的网址,这样urllib.request.Request()是没法识别的,刚好前面制作了一个网页链接的小函数,这里也可用用上

if url: # 从输入框获取到小说主页网址后,判断其是否为“www”开头,是的话给其添加头部"http://"if url[0:3] == "www":url = urlcat("https://", url)

三、制作exe工具

找到python安装路径,在子子目录scripts下有pip.exe工具(我用的是pip3.6.exe),将其拖入到cmd窗口,后面添加相应的按键命令(如:C:\Users\test\AppData\Local\Programs\Python\Python36-32\Scripts\pip3.6 install pywin32),回车安装软件
1、下载 pywin32:    pip install pywin32
2、下载 pyinstaller: pip install pyinstaller。
3、使用pyinstaller工具打包: pyinstaller -F -w -c  app.py,即可生成exe文件;
生成的exe文件路径在命令行中可以看到(如下图红框所示),之后就可以将此exe文件共享给基友使用啦~~
![这里写图片描述](https://img-blog.csdn.net/2018051515544767?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l4cnNobGps/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

四、跑起来看看

进入笔趣阁网站,搜索一本经典的小说----紫川,进入紫川小说主页,复制其地址(https://www.biquge5200.cc/59_59557/);
双击"bqg.exe",在弹出的窗口中输入复制的地址,点击“确定”,接下来就耐心等候小说下载了,下载完成后会关闭窗口。然后你会发现,在当前路径下已经躺好了一本"紫川.txt"静静等候你的临幸。

附录:以下为完整的源程序bqg.py:


# -*- coding: utf-8 -*-import urllib
import urllib.request
import re
import tkinter    # 输入输出框def pop_up_box():       #弹出并获取输入框def getBookUrl():nonlocal book_urltry:book_url = str(var.get().strip())root.destroy()  #输入后直接关闭窗口except:book_url = 'Not a valid url.'book_url = Noneroot = tkinter.Tk(className='提示:请输入小说主页的网址')  # 弹出框框名root.geometry('400x80')     # 设置弹出框的大小 w x hroot.resizable(width=False, height=False) #宽不可变, 高可变,默认为Truelabel = tkinter.Label(root,text='yxrsh声明:\n本工具完全基于兴趣制作,完全免费,且禁止任何形式的商业用途\nQQ:1744058358') #生成标签label.pack(side = 'bottom')   # 将输入框放到弹出框靠左侧位置var = tkinter.StringVar()   # 输入框中的内容edit = tkinter.Entry(root, textvariable=var, width = '50')  # 设置"文本变量"为varedit.pack(side = 'left')   # 将输入框放到弹出框靠左侧位置bt = tkinter.Button(root, text='确定', command=getBookUrl)     # 按下此按钮(Input), 触发inputint函数bt.pack(side='right')   # 将输入按键框放到弹出框靠右侧位置root.mainloop() # 弹出弹出框return book_urldef AgentIp():agent_url = 'http://www.xicidaili.com/'   #在此网站中可查找许多代理网站user_agent='Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36'header = {'User-Agent': user_agent}request = urllib.request.Request(agent_url, headers = header)response = urllib.request.urlopen(request)pageCode = response.read().decode('utf-8')pattern = re.compile('<td class="country"><img.*?/></td>.*?<td>(.*?)</td>.*?>高匿</td>', re.S)ip = re.search(pattern, pageCode)   #只获取一个匿名IP做代理if ip:print(ip[0])return ip[1]return Nonedef urlcat(head, tail):cnt = len(head) # 获取头部长度index = 0flag = Truewhile flag:if head.rfind(tail[0:index]) != -1: #查看相同部分的大小index += 1else:flag = Falseif index >= cnt:flag = False#返回链接后的地址       if index > 0:return (head + tail[index-1::])else:return head + tailclass BQG:def __init__(self):self.agentIP = "113.118.94.140"#AgentIp()#''  # 代理IP网址self.file = None    # 用于保存下载的小说--txt格式self.bookName = 'test'   # 小说名self.mainurl = ''def openFile(self, filename):file = open(filename, 'r+')if file:return filereturn None# 不使用代理的话,将程序中getPage_proxy()函数替代成getPage()函数def getPage(self, url):user_agent='Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36'header = {'User-Agent': user_agent}request = urllib.request.Request(url, headers = header)response = urllib.request.urlopen(request)pageCode = response.read().decode("gbk", "ignore")return pageCodedef getPage_proxy(self, url):proxy = {'http':self.agentIP}proxy_support = urllib.request.ProxyHandler(proxy)opener = urllib.request.build_opener(proxy_support)opener.addheaders = [('User-agent','Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36')]urllib.request.install_opener(opener)response = urllib.request.urlopen(url)pageCode = response.read().decode("gbk", 'ignore')return pageCodedef getBookName(self, pageCode):pattern = re.compile('<h1>(.*?)</h1>', re.S)bookName = re.search(pattern, pageCode)if bookName:print("\n\n准备下载小说:\t%s\n"%(bookName[1].strip()))self.bookName = bookName[1].strip()def getOneChapterContent(self, chapterurl):pageCode = self.getPage(chapterurl.strip()) # getPage_proxy(chapterurl.strip())if pageCode == None:return Nonepattern = re.compile('<div id="content".*?>(.*?)</div>', re.S)content = re.findall(pattern, pageCode)if content:pp = re.compile('<p>|</p>')text = re.sub(pp, "\n", content[0])return textprint("none")return ''def getChapters(self, pageCode):pattern = re.compile('<dd><a href="(.*?)">(.*?)</a></dd>', re.S)chapters = re.findall(pattern, pageCode)if chapters:filename = self.bookName + ".txt"print("创建小说文件:\t%s"%filename)file = open(filename, 'w')if file:print("\n=================== 依次下载各章节内容 ===================\n")for chapter in chapters:print("获取章节:\t%s"%(chapter[1]))#chapter[0]--章节链接 chapter[1]--章节名file.write(chapter[1])real_url = chapter[0].strip()if real_url[0] == '/':real_url = urlcat(self.mainurl, real_url) text = self.getOneChapterContent(real_url)file.write(text)file.close()else:print("文件创建or打开失败")def start(self, bqg_url):self.mainurl = bqg_urlpageCode = self.getPage(bqg_url) #getPage_proxy(bqg_url)self.getBookName(pageCode)self.getChapters(pageCode)print("\n已下载完成,退出!\n")url = pop_up_box()  #获取小说主页网址(章节目录页)
if url: # 从输入框获取到小说主页网址后,判断其是否为“www”开头,是的话给其添加头部"http://"if url[0:3] == "www":url = urlcat("https://", url)spider = BQG()spider.start(url)else:print("请输入合理的网址")

使用python3开发趴小说的小工具相关推荐

  1. Vue团队核心成员开发的39行小工具 install-pkg 安装包,值得一学!

    1. 前言 大家好,我是若川.最近组织了源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步.同时极力推荐订阅我写的<学习源码整体架构 ...

  2. Python3下Web下载媒体小工具(常用来下B站视频)

    Python3下Web下载媒体小工具(常用来下B站视频) 项目地址:https://github.com/soimort/you-get 使用条件 需要以下依赖项: Python 3.2或以上 FFm ...

  3. matlab软件中GUI界面开发学习——双色球选择小工具

    matlab软件中GUI界面开发学习--双色球选择小工具 先上一张界面截图: 特别说明:只是最近对双色球比较感兴趣,所以找了一个实际的项目依据帮助我学习GUI工具,小工具的相关条件仅代表个人想法,选择 ...

  4. 工具-eclipse-hibernate关于快速生成*.hbm.xml文件,与bean文件的操作,不使用hibernate tool解决办法之一,主要为了快速开发,写的小工具

    实现思想:就是java对目标表的字符串的处理,以及基础的sql语句 不能使用hibernate tool ,解决办法 为了记录,以后也许还会用的小工具 **工具优点:比手打生成快,能加快hiberna ...

  5. JavaFX之Scene Builder的使用(开发一款GUI小工具原来这么简单)

    文章目录 一.前言 二.JavaFX与Scene Builder下载 三.Scene Builder的使用 四.详细教学(示例) 4.1 环境配置 4.2 创建fxml文件以及Controller类文 ...

  6. python日志分析工具_基于Python3的Web日志分析小工具

    PyWebLog 网站日志分析小工具 环境 Python3.5 Mysql 预览 安装 pip install pymysql pip install flask 导入日志 python Log.py ...

  7. 多人在线编辑文档 开发_十个在线小工具,科研amp;工作必备神器!

    有的时候,做一些网页小工具比软件客户端要好用,客户端有时候出现问题,罢工不能用,而且有的软件还非常占用内存,安装起来可能要好几个小时,所以,小编今天给大家推荐了这些在线版的小工具,非常实用,想用就打开 ...

  8. 使用python+ffmpeg开发的wav分割小工具

    工具分享: 最近项目有接触到音频神经网络训练,但是准备训练数据实在是太难受了,所以用python+ffmpeg写了个自动分割wav文件的小工具,使用前需要配置ffmpeg环境哦 工具代码 需要引入三个 ...

  9. 用Python开发截图识别OCR小工具

    图片来源于网络 文/GitPython 你一定用过那种"OCR神器",可以把图片中的文字提取出来,极大的提高工作效率. 今天,我们就来做一款实时截图识别的小工具.顾名思义,运行程序 ...

  10. python 爬虫开发之抖音小工具

    前言: 有没有感觉网络不好的时候一个小视频要等半天才能看,而且等了这么久还不定能下载完成.特别是在外出差的交通工具上的时候,那时候网络真叫一个差字啊!想看抖影音打发时间都没网络.最近突然想到了可以用P ...

最新文章

  1. Python 还能实现哪些 AI 游戏?附上代码一起来一把!
  2. PrestaShop 网站漏洞修复办法
  3. 互联网协议 — DNS 缓存机制
  4. android中SELINUX规则分析和语法简介
  5. 简单爬虫,查博客浏览量
  6. 牛客网(剑指offer) 第三题 输入一个链表,从尾到头打印链表每个节点的值。
  7. 浅析若干Java序列化工具
  8. 大数据 -- kafka学习笔记:知识点整理(部分转载)
  9. fread 和 read的区别
  10. select a method for export 选项
  11. 【华为云技术分享】【DevCloud · 敏捷智库】如何利用核心概念解决估算常见问题
  12. 【C语言】Find The Single Dog(标志变量的使用)
  13. 从零实现Vue的组件库(零)- 基本结构以及构建工具
  14. 通过DBlink获取不同数据库数据
  15. 解决在使用pip进行安装时的Could not install packages due to an EnvironmentError的问题
  16. python命令行参数作用_python中命令行参数和os模块常用函数
  17. Python学习总结(九)正则表达式
  18. 关于无线网络中几个名词WPS,PSK,WPA,WPA2等名词的解释以及WPA的破解
  19. Abaqus Ncode振动疲劳分析教程
  20. 酒店客房管理系统(JAVA,JSP,SERVLET,MYSQL)

热门文章

  1. idea调试代码错误_通过调试进行指导:如何将代码错误转化为学习经验
  2. react-native >0.69版本 链接@ant-design/icons-react-native
  3. 053试题 - 320/321/322/323/324/326/330/332/544/553/585/586/587/588/589/592/596/597/598/599 rman backup
  4. bios error 装系统acpi_重装系统遇到bios acpi错误。
  5. 调色板的原理和调色板显示模式
  6. String的spilt()方法
  7. 【微信小程序】获取Bmob后端云数据库某一数据表的所有记录
  8. html 制作魔方源代码,CSS3 3d环境实现立体 魔方效果代码
  9. Ubuntu环境下XAMP安装PHP的rabbitmq扩展
  10. WePhone手机软件已下架 疑因资金问题导致无法使用