美文网首页
用Python做一个下载器,从获取数据到编写GUI界面

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

作者: 颜狗一只 | 来源:发表于2023-06-16 18:59 被阅读0次

    前言

    嗨喽,大家好呀~这里是爱看美女的茜茜呐

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

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

    案例基本实现思路?

    一、数据来源分析

    明确需求:

    • 采集的网站是什么?

    • 采集的数据是什么?

      标题/内容

      分析 标题/内容 是从哪里来的

      通过浏览器自带工具: 开发者工具抓包分析

    • 打开开发者工具: F12 / 鼠标右键点击检查选择network

    • 刷新网页

    • 搜索数据, 找到数据包

    二. 代码实现步骤

    1. 发送请求, 模拟浏览器对于url地址发送请求
    1. 请求链接: https://www.***.net/1_1631/3047505.html

    2. 获取数据, 获取服务器返回响应数据内容

      开发者工具: response

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

      标题/内容

    4. 保存数据, 把数据保存本地文件

    代码实现

    在开始之前,为了防止大家代码看不懂,我特地录制了一套详细教程

    一、单张小说下载

    发送请求, 模拟浏览器对于url地址发送请求

    获取数据, 获取服务器返回响应数据内容

    import requests
    # 请求链接
    url = 'https://www.****.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.****.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.****.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.****.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.****.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.////.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.****.net' + url
            title, content = get_content(html_url=index_url)
            save(name, title, content)
            
    if __name__ == '__main__':
        word = input('请输入你搜索小说名: ')
        main(word)
    

    六、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('有什么问题可以跟我打招呼哦')
    # 设置界面大小
    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)
    # 设置下载按钮
    完整源码、解答、教程皆+VX:pytho8987获取,记得验证备注“777”
    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界面

          本文链接:https://www.haomeiwen.com/subject/obwrydtx.html