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

今天咱们分享一个小说下载器代码,打包成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)

# 响应对象, 表示请求成功

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)

# 响应对象, 表示请求成功

print(response)

# 获取下来response.text , 转成可解析对象

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)

# 响应对象, 表示请求成功

print(response)

# 获取下来response.text , 转成可解析对象

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('

(.*?)

', html_data)[0]

# 自动创建一个文件夹

file = f'{name}\\'

if not os.path.exists(file):

os.mkdir(file)

# 提取章节url

url_list = re.findall('

', 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)

# 响应对象, 表示请求成功

print(response)

# 获取下来response.text , 转成可解析对象

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('

(.*?)

', html_data)[0]

# 提取章节url

url_list = re.findall('

', 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('

(.*?)

', html_data)[0]

# 提取内容

content = re.findall('

(.*?)

', html_data, re.S)[0].replace('

', '\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('

(.*?)

', html_data)[0]

# 提取章节url

url_list = re.findall('

', 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('

(.*?)

', html_data)[0]

# 提取内容

content = re.findall('

(.*?)

', html_data, re.S)[0].replace('

', '\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('

(.*?)

', html_data)[0]

# 提取章节url

url_list = re.findall('

', html_data)

return name, url_list

 

获取小说内容/小说标题

def get_content(html_url):

# 调用发送请求函数

html_data = get_response(html_url).text

# 提取标题

title = re.findall('

(.*?)

', html_data)[0]

# 提取内容

content = re.findall('

(.*?)

', html_data, re.S)[0].replace('

', '\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, 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可执行软件,这样的话,就能分享给不会的小伙伴去使用了。

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

查看原文