對于廣大書蟲而言,沒有小說看是最痛苦的,你身邊有這樣的人嗎?
今天咱們分享一個小說下載器代碼,打包成exe后,發給你的小伙伴也能直接使用…

思路流程
什么是爬蟲?
按照一定的規則, 去采集互聯網上面資料
爬蟲可以做什么?
- 采集資料: 定制化采集資料
- 自動化腳本:自動點贊/評論/刷票/商品搶購腳本/自動發送彈幕
爬蟲基本實作思路?
一、資料來源分析
- 明確需求:
- 采集的網站是什么?
https://www.biqudu.net/1_1631/3047505.html
- 采集的資料是什么?
標題/內容 - 分析 標題/內容 是從哪里來的
通過瀏覽器自帶工具: 開發者工具抓包分析
- 打開開發者工具: F12 / 滑鼠右鍵點擊檢查選擇network
- 重繪網頁
- 搜索資料, 找到資料包
https://www.biqudu.net/1_1631/3047505.html
二. 代碼實作步驟
- 發送請求, 模擬瀏覽器對于url地址發送請求
請求鏈接: https://www.biqudu.net/1_1631/3047505.html - 獲取資料, 獲取服務器回傳回應資料內容
開發者工具: response - 決議資料, 提取我們想要的資料內容
標題/內容 - 保存資料, 把資料保存本地檔案
代碼實作
在開始之前,為了防止大家代碼看不懂,我特地錄制了一套詳細教程,教程和代碼,直接加這個裙 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('//*[@]/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('//*[@]/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 = https://www.cnblogs.com/hahaa/p/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="https://www.cnblogs.com/hahaa/p/(.*?)">', 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('//*[@]/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 =https://www.cnblogs.com/hahaa/p/ get_response(html_url).text # 提取小說名字 name = re.findall('<h1>(.*?)</h1>', html_data)[0] # 提取章節url url_list = re.findall('<dd> <a style="" href="https://www.cnblogs.com/hahaa/p/(.*?)">', html_data) return name, url_list def get_content(html_url): """ 獲取小說內容/小說標題 :param html_url: 小說章節url :return: """ # 呼叫發送請求函式 html_data =https://www.cnblogs.com/hahaa/p/ 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 =https://www.cnblogs.com/hahaa/p/ get_response(html_url).text # 提取小說名字 name = re.findall('<h1>(.*?)</h1>', html_data)[0] # 提取章節url url_list = re.findall('<dd> <a style="" href="https://www.cnblogs.com/hahaa/p/(.*?)">', html_data) return name, url_list def get_content(html_url): """ 獲取小說內容/小說標題 :param html_url: 小說章節url :return: """ # 呼叫發送請求函式 html_data =https://www.cnblogs.com/hahaa/p/ 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 = https://www.cnblogs.com/hahaa/p/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 =https://www.cnblogs.com/hahaa/p/ get_response(html_url).text # 提取小說名字 name = re.findall('<h1>(.*?)</h1>', html_data)[0] # 提取章節url url_list = re.findall('<dd> <a style="" href="https://www.cnblogs.com/hahaa/p/(.*?)">', html_data) return name, url_list
獲取小說內容/小說標題
def get_content(html_url): # 呼叫發送請求函式 html_data =https://www.cnblogs.com/hahaa/p/ 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 = https://www.cnblogs.com/hahaa/p/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 = https://www.cnblogs.com/hahaa/p/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, 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()
效果展示

最后
全部實作以后,我們可以使用 Pyinstaller 模塊將代碼打包為exe可執行軟體,這樣的話,就能分享給不會的小伙伴去使用了,
好了,今天的分享就到這里結束了,歡迎大家品鑒!下次見!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/544178.html
標籤:Python
