用Python做一個小說下載器,從獲取數據到編寫GUI界面

来源:https://www.cnblogs.com/hahaa/archive/2023/02/17/17131626.html
-Advertisement-
Play Games

對於廣大書蟲而言,沒有小說看是最痛苦的,你身邊有這樣的人嗎? 今天咱們分享一個小說下載器代碼,打包成exe後,發給你的小伙伴也能直接使用… 思路流程 什麼是爬蟲? 按照一定的規則, 去採集互聯網上面數據 爬蟲可以做什麼? 採集數據: 定製化採集數據 自動化腳本:自動點贊/評論/刷票/商品搶購腳本/自 ...


對於廣大書蟲而言,沒有小說看是最痛苦的,你身邊有這樣的人嗎?

今天咱們分享一個小說下載器代碼,打包成exe後,發給你的小伙伴也能直接使用…

思路流程

什麼是爬蟲?

按照一定的規則, 去採集互聯網上面數據

爬蟲可以做什麼?

  • 採集數據: 定製化採集數據
  • 自動化腳本:自動點贊/評論/刷票/商品搶購腳本/自動發送彈幕

爬蟲基本實現思路?

一、數據來源分析

  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 自取就好了

 


 

一、單張小說下載

發送請求, 模擬瀏覽器對於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)

 

效果展示

六、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, h

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 創建前端項目 npm install create-react-app -g create-react-app my-app-client create-react-app 是創建單頁面程式的腳手架 前端目錄結構 創建好項目之後,刪掉 src 目錄下的文件,按照以下結構創建目錄,根據具體項目情況進行 ...
  • 前言:用於展示生產線數據相關信息 在車輛生產線的小屏幕上【西門子的,比1980*1080的要小一圈,比pad要大一圈,專門給生產線做的】展示數據。數據用的flex佈局,很簡單的解決了自適應的問題。效果很好。 但,image展示的圖片的寬高不勻稱,比例不同。 這是開始的代碼,只摘取了關鍵部分: <bo ...
  • defineExpose要在變數和方法聲明定義之後再使用,否則瀏覽器的控制台會輸出很多警告,並且最終將該頁面卡死。 ...
  • 今天,有個群友在群里提問,使用 CSS 能否實現下述這個圖形: emmm,中間這個酷似三次貝塞爾曲線的造型,使用 CSS 不太好實現。我的建議是切圖實現,然而群友要求一定要用 CSS 實現。 雖然麻煩,但是這個圖形勉強也是能用 CSS 實現的。本文就將探討一下上述圖形的純 CSS 實現方式,並且從中 ...
  • 在分散式系統中, 什麼是拜占庭將軍問題?產生的場景和解決方案是什麼?什麼是 Raft 共識演算法?Raft 演算法是如何解決拜占庭將軍問題的?其核心原理和演算法邏輯是什麼?除了 Raft,還有哪些共識演算法?共識問題作為分散式系統的一大難點和痛點,本文主要介紹了其產生的背景、原因,以及通用的 Raft 演算法... ...
  • 談到java中的併發,我們就避不開線程之間的同步和協作問題,談到線程同步和協作我們就不能不談談jdk中提供的AbstractQueuedSynchronizer(翻譯過來就是抽象的隊列同步器)機制; (一)、AQS中的state和Node含義: AQS中提供了一個int volatile state ...
  • 題目來源:https://www.acwing.com/problem/content/description/789/ 題目描述 給定你一個長度為 n 的整數數列。 請你使用歸併排序對這個數列按照從小到大進行排序。 並將排好序的數列按順序輸出。 輸入格式 輸入共兩行,第一行包含整數 n。 第二行包 ...
  • SpringMVC文件上傳 1.基本介紹 SpringMVC 為文件上傳提供了直接的支持,這種支持是通過即插即用的 MultipartResolver 實現的。spring 用 Jacarta Commons FileUpload 技術實現了一個 MultipartResolver 的實現類:Com ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...