用Python做一个小说下载器,从获取数据到编写GUI界面

对于广大书虫而言,没有小说看是最痛苦的,你身边有这样的人吗?

今天咱们分享一个小说下载器代码,打包成exe后,发给你的小伙伴也能直接使用…

用Python做一个小说下载器,从获取数据到编写GUI界面

思路流程

什么是爬虫?

按照一定的规则, 去采集互联网上面数据

爬虫可以做什么?

  • 采集数据: 定制化采集数据
  • 自动化脚本:自动点赞/评论/刷票/商品抢购脚本/自动发送弹幕

爬虫基本实现思路?

一、数据来源分析

  1. 明确需求:
    - 采集的网站是什么?
    https://www.biqudu.net/1_1631/3047505.html
    - 采集的数据是什么?
    标题/内容
  2. 分析 标题/内容 是从哪里来的
    通过浏览器自带工具: 开发者工具抓包分析
    - 打开开发者工具: F12 / 鼠标右键点击检查选择network
    - 刷新网页
    - 搜索数据, 找到数据包
    https://www.biqudu.net/1_1631/3047505.html

二. 代码实现步骤

  1. 发送请求, 模拟浏览器对于url地址发送请求
    请求链接: https://www.biqudu.net/1_1631/3047505.html
  2. 获取数据, 获取服务器返回响应数据内容
    开发者工具: response
  3. 解析数据, 提取我们想要的数据内容
    标题/内容
  4. 保存数据, 把数据保存本地文件

代码实现

在开始之前,为了防止大家代码看不懂,我特地录制了一套详细教程,教程和代码,直接加这个裙 708525271 自取就好了

 

用Python做一个小说下载器,从获取数据到编写GUI界面

 

一、单张小说下载

发送请求, 模拟浏览器对于url地址发送请求
获取数据, 获取服务器返回响应数据内容

import requests
# 请求链接
url = 'https://www.biqudu.net/1_1631/3047505.html'
# 模拟浏览器 headers 请求头
headers = {
    # user-agent 用户代理 表示浏览器基本身份信息
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}
# 发送请求
response = requests.get(url=url, headers=headers)
# <Response [200]> 响应对象, 表示请求成功
print(response)

print(response.text)

 

解析数据,提取我们想要的数据内容。

import requests  # 数据请求
import re  # 正则
import parsel # 数据解析

# 请求链接
url = 'https://www.biqudu.net/1_1631/3047505.html'
# 模拟浏览器 headers 请求头
headers = {
    # user-agent 用户代理 表示浏览器基本身份信息
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}
# 发送请求
response = requests.get(url=url, headers=headers)
# <Response [200]> 响应对象, 表示请求成功
print(response)

# 获取下来response.text <html字符串数据>, 转成可解析对象
selector = parsel.Selector(response.text)
# 提取标题
title = selector.xpath('//*[@class="bookname"]/h1/text()').get()
# 提取内容
content = '\n'.join(selector.xpath('//*[@id="content"]/text()').getall())
print(title)
print(content)

 

保存数据

# 数据请求模块 
import requests
# 正则表达式模块
import re
# 数据解析模块
import parsel
 
# 请求链接
url = 'https://www.biqudu.net/1_1631/3047505.html'
# 模拟浏览器 headers 请求头
headers = {
    # user-agent 用户代理 表示浏览器基本身份信息
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}
# 发送请求
response = requests.get(url=url, headers=headers)
# <Response [200]> 响应对象, 表示请求成功
print(response)

# 获取下来response.text <html字符串数据>, 转成可解析对象
selector = parsel.Selector(response.text)
# 提取标题
title = selector.xpath('//*[@class="bookname"]/h1/text()').get()
# 提取内容
content = '\n'.join(selector.xpath('//*[@id="content"]/text()').getall())
print(title)
print(content)
# title <文件名> '.txt' 文件格式  a 追加保存 encoding 编码格式 as 重命名
with open(title + '.txt', mode='a', encoding='utf-8') as f:

    # 写入内容
    f.write(title)
    f.write('\n')
    f.write(content)
    f.write('\n')

 

二、整本小说下载

# 数据请求模块
import requests
# 正则表达式模块
import re
# 数据解析模块
import parsel
# 文件操作模块
import os
 
# 请求链接: 小说目录页
list_url = 'https://www.biqudu.net/1_1631/'
# 模拟浏览器 headers 请求头
headers = {
    # user-agent 用户代理 表示浏览器基本身份信息
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}
# 发送请求
html_data = requests.get(url=list_url, headers=headers).text
# 提取小说名字
name = re.findall('<h1>(.*?)</h1>', html_data)[0]
# 自动创建一个文件夹
file = f'{name}\\'
if not os.path.exists(file):
    os.mkdir(file)
 
# 提取章节url
url_list = re.findall('<dd> <a style="" href="(.*?)">', html_data)
# for循环遍历
for url in url_list:
    index_url = 'https://www.biqudu.net' + url
    print(index_url)

    headers = {
        # user-agent 用户代理 表示浏览器基本身份信息
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
    }
    # 发送请求
    response = requests.get(url=index_url, headers=headers)
    # <Response [200]> 响应对象, 表示请求成功
    print(response)

    # 获取下来response.text <html字符串数据>, 转成可解析对象
    selector = parsel.Selector(response.text)
    # 提取标题
    title = selector.xpath('//*[@class="bookname"]/h1/text()').get()
    # 提取内容
    content = '\n'.join(selector.xpath('//*[@id="content"]/text()').getall())
    print(title)
    # print(content)
    # title <文件名> '.txt' 文件格式  a 追加保存 encoding 编码格式 as 重命名
    with open(file + title + '.txt', mode='a', encoding='utf-8') as f:

        # 写入内容
        f.write(title)
        f.write('\n')
        f.write(content)
        f.write('\n')

 

三、多线程采集

# 数据请求模块
import requests
# 正则表达式模块
import re
# 数据解析模块
import parsel
# 文件操作模块
import os
# 线程池
import concurrent.futures
 
 
def get_response(html_url):
    """
    发送请求函数
    :param html_url: 请求链接
    :return: response响应对象
    """
    # 模拟浏览器 headers 请求头
    headers = {
        # user-agent 用户代理 表示浏览器基本身份信息
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
    }
    response = requests.get(url=html_url, headers=headers)
    return response
 
 
def get_list_url(html_url):
    """
    获取章节url/小说名
    :param html_url: 小说目录页
    :return:
    """
    # 调用发送请求函数
    html_data = get_response(html_url).text
    # 提取小说名字
    name = re.findall('<h1>(.*?)</h1>', html_data)[0]
    # 提取章节url
    url_list = re.findall('<dd> <a style="" href="(.*?)">', html_data)
    return name, url_list
 
 
def get_content(html_url):
    """
    获取小说内容/小说标题
    :param html_url: 小说章节url
    :return:
    """
    # 调用发送请求函数
    html_data = get_response(html_url).text
    # 提取标题
    title = re.findall('<h1>(.*?)</h1>', html_data)[0]
    # 提取内容
    content = re.findall('<div id="content">(.*?)<p>', html_data, re.S)[0].replace('<br/><br/>', '\n')
    return title, content
 
 
def save(name, title, content):
    """
    保存数据函数
    :param name: 小说名
    :param title: 章节名
    :param content: 内容
    :return:
    """
    # 自动创建一个文件夹
    file = f'{name}\\'
    if not os.path.exists(file):
        os.mkdir(file)
    with open(file + title + '.txt', mode='a', encoding='utf-8') as f:
        """
        第一章 标题
            小说内容
        第二章 标题
            小说内容
        """
        # 写入内容
        f.write(title)
        f.write('\n')
        f.write(content)
        f.write('\n')
    print(title, '已经保存')
 
 
def main(home_url):
    # index_url = 'https://www.biqudu.net' + url
    title, content = get_content(html_url=home_url)
    save(name, title, content)
 
 
if __name__ == '__main__':
    url = 'https://www.biqudu.net/1_1631/'
    name, url_list = get_list_url(html_url=url)
    exe = concurrent.futures.ThreadPoolExecutor(max_workers=7)
    for url in url_list:
        index_url = 'https://www.biqudu.net' + url
        exe.submit(main, index_url)
    exe.shutdown()

 

四、采集排行榜所有小说

# 数据请求模块
import requests
# 正则表达式模块
import re
# 数据解析模块
import parsel
# 文件操作模块
import os
 
 
 
def get_response(html_url):
    """
    发送请求函数
    :param html_url: 请求链接
    :return: response响应对象
    """
    # 模拟浏览器 headers 请求头
    headers = {
        # user-agent 用户代理 表示浏览器基本身份信息
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
    }
    response = requests.get(url=html_url, headers=headers)
    return response
 
 
def get_list_url(html_url):
    """
    获取章节url/小说名
    :param html_url: 小说目录页
    :return:
    """
    # 调用发送请求函数
    html_data = get_response(html_url).text
    # 提取小说名字
    name = re.findall('<h1>(.*?)</h1>', html_data)[0]
    # 提取章节url
    url_list = re.findall('<dd> <a style="" href="(.*?)">', html_data)
    return name, url_list
 
 
def get_content(html_url):
    """
    获取小说内容/小说标题
    :param html_url: 小说章节url
    :return:
    """
    # 调用发送请求函数
    html_data = get_response(html_url).text
    # 提取标题
    title = re.findall('<h1>(.*?)</h1>', html_data)[0]
    # 提取内容
    content = re.findall('<div id="content">(.*?)<p>', html_data, re.S)[0].replace('<br/><br/>', '\n')
    return title, content
 
 
def save(name, title, content):
    """
    保存数据函数
    :param name: 小说名
    :param title: 章节名
    :param content: 内容
    :return:
    """
    # 自动创建一个文件夹
    file = f'{name}\\'
    if not os.path.exists(file):
        os.mkdir(file)
    with open(file + title + '.txt', mode='a', encoding='utf-8') as f:
        """
        第一章 标题
            小说内容
        第二章 标题
            小说内容
        """
        # 写入内容
        f.write(title)
        f.write('\n')
        f.write(content)
        f.write('\n')
    print(title, '已经保存')
 
def get_novel_id(html_url):
    """
    获取小说ID
    :param html_url: 某分类的链接
    :return:
    """
    # 调用发送请求函数
    novel_data = get_response(html_url=html_url).text
    selector = parsel.Selector(novel_data)
    href = selector.css('.l .s2 a::attr(href)').getall()
    href = [i.replace('/', '') for i in href]
    return href
 
 
def main(home_url):
    href = get_novel_id(html_url=home_url)
    for novel_id in href:
        novel_url = f'https://www.biqudu.net/{novel_id}/'
        name, url_list = get_list_url(html_url=novel_url)
        print(name, url_list)
        for url in url_list:
            index_url = 'https://www.biqudu.net' + url
            title, content = get_content(html_url=index_url)
            save(name, title, content)
        break
 
 
if __name__ == '__main__':
    html_url = 'https://www.biqudu.net/biquge_1/'
    main(html_url)

 

五、搜索小说功能

模块

# 导入数据请求模块
import requests
# 导入正则表达式模块
import re
# 导入数据解析模块
import parsel
# 导入文件操作模块
import os
# 导入漂亮的表格
import prettytable as pt

 

发送请求函数

def get_response(html_url):
    # 模拟浏览器 headers 请求头
    headers = {
        # user-agent 用户代理 表示浏览器基本身份信息
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
    }
    response = requests.get(url=html_url, headers=headers)
    return response

 

获取章节url/小说名

def get_list_url(html_url):
    # 调用发送请求函数
    html_data = get_response(html_url).text
    # 提取小说名字
    name = re.findall('<h1>(.*?)</h1>', html_data)[0]
    # 提取章节url
    url_list = re.findall('<dd> <a style="" href="(.*?)">', html_data)
    return name, url_list

 

获取小说内容/小说标题

def get_content(html_url):
    # 调用发送请求函数
    html_data = get_response(html_url).text
    # 提取标题
    title = re.findall('<h1>(.*?)</h1>', html_data)[0]
    # 提取内容
    content = re.findall('<div id="content">(.*?)<p>', html_data, re.S)[0].replace('<br/><br/>', '\n')
    return title, content

 

保存数据函数

def save(name, title, content):
    # 自动创建一个文件夹
    file = f'{name}\\'
    if not os.path.exists(file):
        os.mkdir(file)
    with open(file + name + '.txt', mode='a', encoding='utf-8') as f:
        # 写入内容
        f.write(title)
        f.write('\n')
        f.write(content)
        f.write('\n')
    print(title, '已经保存')

 

获取小说ID

def get_novel_id(html_url):
    # 调用发送请求函数
    novel_data = get_response(html_url=html_url).text
    selector = parsel.Selector(novel_data)
    href = selector.css('.l .s2 a::attr(href)').getall()
    href = [i.replace('/', '') for i in href]
    return href

 

搜索功能

def search(word):
    search_url = f'https://www.biqudu.net/searchbook.php?keyword={word}'
    # 发送请求
    search_data = get_response(html_url=search_url).text
    # 解析数据, 提取小说名字/作者/小说ID
    selector = parsel.Selector(search_data)
    lis = selector.css('.novelslist2 li')
    novel_info = []
    tb = pt.PrettyTable()
    tb.field_names = ['序号', '书名', '作者', '书ID']
    num = 0
    for li in lis[1:]:
        # 小说名字
        name = li.css('.s2 a::text').get()
        novel_id = li.css('.s2 a::attr(href)').get().replace('/', '')
        writer = li.css('.s4::text').get()
        dit = {
            'name': name,
            'writer': writer,
            'novel_id': novel_id,
        }
        tb.add_row([num, name, writer, novel_id])
        num += 1
        novel_info.append(dit)
    print('你搜索的结果如下:')
    print(tb)
    novel_num = input('请输入你想要下载的小说序号: ')
    novel_id = novel_info[int(novel_num)]['novel_id']
    return novel_id

 

主函数

def main(word):
    novel_id = search(word)
    novel_url = f'https://www.biqudu.net/{novel_id}/'
    name, url_list = get_list_url(html_url=novel_url)
    print(name, url_list)
    for url in url_list:
        index_url = 'https://www.biqudu.net' + url
        title, content = get_content(html_url=index_url)
        save(name, title, content)
        
if __name__ == '__main__':
    word = input('请输入你搜索小说名: ')
    main(word)

 

效果展示
用Python做一个小说下载器,从获取数据到编写GUI界面

六、GUI界面

import tkinter as tk
from tkinter import ttk
 
 
 
def show():
    name = name_va.get()
    print('输入的名字是:', name)
 
def download():
    name = num_va.get()
    print('输入的序号:', name)
 
 
# 创建界面
root = tk.Tk()
# 设置标题
root.title('完整代码添加VX:pytho8987')
# 设置界面大小
root.geometry('500x500+200+200')
# 设置可变变量
name_va = tk.StringVar()
# 设置标签
search_frame = tk.Frame(root)
search_frame.pack(pady=10)
# 设置文本
tk.Label(search_frame, text='书名 作者', font=('微软雅黑', 15)).pack(side=tk.LEFT, padx=10)
# 设置输入框
tk.Entry(search_frame, relief='flat', textvariable=name_va).pack(side=tk.LEFT)
 
# 序号获取
num_va = tk.StringVar()
# 查询下载输入框
download_frame = tk.Frame(root)
download_frame.pack(pady=10)
# 设置文本
tk.Label(download_frame, text='小说 序号', font=('微软雅黑', 15)).pack(side=tk.LEFT, padx=10)
# 设置输入框
tk.Entry(download_frame, relief='flat', textvariable=num_va).pack(side=tk.LEFT)
 
# 按钮设置
button_frame = tk.Frame(root)
button_frame.pack(pady=10)
 
# 设置查询按钮
tk.Button(button_frame, text='查询', font=('微软雅黑', 10), relief='flat', bg='#88e2d6', width=10, command=show).pack(side=tk.LEFT, padx=10)
# 设置下载按钮
tk.Button(button_frame, text='下载', font=('微软雅黑', 10), relief='flat', bg='#88e2d6', width=10, command=download).pack(side=tk.LEFT, padx=10)
 
# 提前设置标签名字和中文显示内容
columns = ('num', 'writer', 'name', 'novel_id')
columns_value = ('序号', '作者', '书名', '书ID')
tree_view = ttk.Treeview(root, height=18, show='headings', columns=columns)
# 设置列名
# 设置列名
tree_view.column('num', width=40, anchor='center')
tree_view.column('writer', width=40, anchor='center')
tree_view.column('name', width=40, anchor='center')
tree_view.column('novel_id', width=40, anchor='center')
# 给列名设置显示的名字
tree_view.heading('num', text='序号')
tree_view.heading('writer', text='作者')
tree_view.heading('name', text='书名')
tree_view.heading('novel_id', text='书ID')
tree_view.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# 展示界面
root.mainloop()

 

效果展示

用Python做一个小说下载器,从获取数据到编写GUI界面

最后

全部实现以后,我们可以使用 Pyinstaller 模块将代码打包为exe可执行软件,这样的话,就能分享给不会的小伙伴去使用了。

好了,今天的分享就到这里结束了,欢迎大家品鉴!下次见!

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:用Python做一个小说下载器,从获取数据到编写GUI界面 - Python技术站

(0)
上一篇 2023年3月31日 下午9:01
下一篇 2023年3月31日

相关文章

  • 【Python】Flask + MySQL 实现用户注册,登录和登出

    今天用Flask + MySQL 实现用户注册,登录和登出。 一、实战场景 Flask 框架实现用户的注册,登录和登出。 二、主要知识点 flask_login 插件使用 SQLAlchemy 基础操作 用户基础类设计 Flask 读取配置文件 蓝图注册与使用 wtforms 表单提交数据 wtforms 表单验证 Bootstrap 集成 Jinjia2 …

    Python开发 2023年4月2日
    00
  • 奶奶常说,黑白照片看的不清晰,还好我会Python,分分钟给她变成彩色的~

    咳咳~ 其实是奶奶常说,艾欧尼亚昂扬不灭,正义将指引着我们!   好吧,并不是奶奶说,只是最近回家发现一些黑白老照片,看着不够清晰,然后实验了一波用Python把老照片变成彩色的。 代码展示 import requests # Python学习交流资料源码获取群 279199867 r = requests.post( “https://api.deepai…

    2023年4月2日
    00
  • Python做一个英汉翻译小字典

    每天一句小诗词 阳明四句:无善无恶心之体,有善有恶意之动,知善知恶是良知,为善去恶是格物。 今天教大家用Python做一个英汉翻译小字典,输入英文,返回对应中文。 二、知识点 文件读写 基础语法 异常处理 循环语句 字符串处理 三、代码展示 导入模块 import platform # 我还给大家准备了这些资料:Python视频教程、100本Python电子…

    Python开发 2023年4月2日
    00
  • 为了防止这个公众号被封,我连夜用Python爬取了它所有图片~

    哈喽兄弟们,今天来试试批量获取公众号文章,emmm…     虽然名义上是文章,单其实它是一篇纯图片文,至于为什么不是文字,小姐姐不比文字香?     事前准备     我们需要用到 Fiddler Everywhere 这个软件,Crack是本次要使用到的文件,以及要安装微信PC版客户端,我专门录了一个安装 及使用的教程。 本次使用的是Python3.8 …

    2023年4月2日
    00
  • Python遇上SQL,于是一个好用的Python第三方库出现了

    1. 演示数据 本文的所有演示数据,均是基于下方的四张表。下面这四张表大家应该不陌生,这就是网传50道经典MySQL面试题中使用到的几张原表。关于下方各表之间的关联关系,我就不给大家说明了,仔细观察字段名,应该就可以发现。 2. pandasql的使用 1)简介 pandas中的DataFrame是一个二维表格,数据库中的表也是一个二维表格,因此在panda…

    Python开发 2023年4月2日
    00
  • 聊天尬住了?教你用Python一键获取斗图表情包,从此摇身变海王

    很多兄弟在聊天上没有下太多的功夫,导致自己聊天的时候很容易尬住,然后就不知道聊啥了,这时候合适表情包分分钟就能救场,但是一看自己收藏的表情包,好家伙,两只手都数得过来。 所以今天来给兄弟们分享一下爬取表情包的代码,再也不用尬聊了! 给大家看看我朋友的尬聊场面     本次目标 网站:发表情 网不好 ,没加载出来,表弟又在当老六,看不该看的抢我网速!!! 使用…

    Python开发 2023年3月31日
    00
  • 利用Python自动生成请假条

    哈喽兄弟们,今天咱们来实现用Python来批量生成请假条,这回既学了东西又做了事情,两不误~ 本文就将基于一个真实的办公案例进行讲解如何提取Excel内容并创建Word 主要将涉及以下三个知识点 openpyxl 读取 Excel 文件 python-docx 写入 Word 文件 python-docx 各类样式的设计和调整 需求描述 你是公司的底层小虾米…

    Python开发 2023年4月2日
    00
  • 使用Python探索四大名著【红楼梦】人物之间的关系,简直帅呆了

        《红楼梦》作为我国四大名著之一,古典小说的巅峰之作,粉丝量极其庞大,而红学也经久不衰。所以我们今天通过 Python 来探索下红楼梦里那千丝万缕的人物关系,话不多说,开始整活! 一、准备工作 红楼梦txt格式电子书一份 金陵十二钗+贾宝玉人物名称列表 宝玉 nr 黛玉 nr 宝钗 nr 湘云 nr 凤姐 nr 李纨 nr 元春 nr 迎春 nr 探春…

    2023年4月2日
    00
合作推广
合作推广
分享本页
返回顶部