|
对于广大书虫而言,没有小说看是最痛苦的,你身边有这样的人吗?
今天咱们分享一个小说下载器代码,打包成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 = 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 target="_blank" href="https://www.cnblogs.com/(.*?)">', 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 = get_response(html_url).text
- # 提取小说名字
- name = re.findall('<h1>(.*?)</h1>', html_data)[0]
- # 提取章节url
- url_list = re.findall('<dd> <a target="_blank" href="https://www.cnblogs.com/(.*?)">', 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('(.*?)<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 target="_blank" href="https://www.cnblogs.com/(.*?)">', 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('(.*?)<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 target="_blank" href="https://www.cnblogs.com/(.*?)">', 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('(.*?)<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, 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.cnblogs.com/hahaa/p/17131626.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|