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