Python:爬虫基础《爬取红楼梦》

小说爬虫项目说明文档

用于爬取诗词名句网上小说内容的Python爬虫项目。本项目以《红楼梦》为例,演示如何爬取完整的小说内容。

项目功能

  • 爬取小说的所有章节名称
  • 获取每个章节的URL链接
  • 下载并保存每个章节的内容到独立的文本文件
  • 自动创建存储目录
  • 包含基本的错误处理和请求延迟

环境要求

  • Python 3.x
  • 依赖包:
    • requests
    • beautifulsoup4
    • logging

安装依赖

pip install requests beautifulsoup4

项目结构说明

项目主要包含以下几个核心函数:

  1. extract_chapter_names(source): 提取所有章节名称
  2. extract_list_url(source, domain): 提取所有章节的URL
  3. extract_chapter_content(url_list, chapter_names, headers, folder_name): 下载并保存章节内容

实现步骤

1. 基础设置

import os
import requests
import logging
import time
from bs4 import BeautifulSoup# 设置请求头
headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36"
}

2. 提取章节名称

extract_chapter_names 函数实现以下功能:

  • 查找包含章节列表的div元素
  • 提取所有章节的名称
  • 返回章节名称列表

extract_chapter_names 函数详细说明

函数概述

extract_chapter_names 函数用于从网页源代码中提取所有小说章节的名称。这个函数接收一个 BeautifulSoup 对象作为参数,返回一个包含所有章节名称的列表。

函数定义

def extract_chapter_names(source):page_list = source.find("div", class_="ContL")list_chapter = page_list.find("div", "list")a_list = list_chapter.findAll("a")chapter_names = []for a in a_list:print(a.get_text())chapter_names.append(a.get_text())return chapter_names

详细实现步骤

1. 定位主要内容区域

page_list = source.find("div", class_="ContL")
  • 使用 find() 方法查找类名为 “ContL” 的 div 元素
  • 这个 div 包含了小说的所有章节列表
  • class_="ContL" 是指定要查找的 CSS 类名

2. 定位章节列表区域

list_chapter = page_list.find("div", "list")
  • 在主要内容区域中查找类名为 “list” 的 div 元素
  • 这个 div 直接包含了所有章节的链接

3. 获取所有章节链接

a_list = list_chapter.findAll("a")
  • 使用 findAll() 方法获取所有的 <a> 标签
  • 每个 <a> 标签代表一个章节链接
  • 返回的是一个包含所有匹配元素的列表

4. 提取章节名称

chapter_names = []
for a in a_list:print(a.get_text())chapter_names.append(a.get_text())
  • 创建空列表 chapter_names 存储章节名称
  • 遍历每个 <a> 标签
  • 使用 get_text() 方法获取链接文本,即章节名称
  • 打印章节名称用于调试和进度显示
  • 将章节名称添加到列表中

5. 返回结果

return chapter_names
  • 返回包含所有章节名称的列表

示例输出

函数返回的列表格式如下:

["第一回 甄士隐梦幻识通灵 贾雨村风尘怀闺秀","第二回 贾夫人仙逝扬州城 冷子兴演说荣国府",# ... 更多章节名称
]

注意事项

  1. 函数依赖于网页的特定 HTML 结构,如果网站改版可能需要更新代码
  2. 确保传入的 source 参数是有效的 BeautifulSoup 对象
  3. 网页编码应该正确设置为 UTF-8,否则可能出现乱码
  4. 打印输出有助于监控爬取进度和调试

可能的改进

  1. 添加错误处理机制,处理元素不存在的情况
  2. 添加数据清洗功能,去除不必要的空白字符
  3. 可以添加章节编号提取功能
  4. 可以添加进度条显示替代简单的打印输出

3. 提取章节URL

extract_list_url 函数实现以下功能:

  • 查找所有章节的链接元素
  • 组合完整的URL地址
  • 返回URL列表

extract_list_url 函数详细说明

函数概述

extract_list_url 函数用于从网页源代码中提取所有章节的URL链接。这个函数接收两个参数:

  • source: BeautifulSoup 对象,包含解析后的网页内容
  • domain: 网站的域名,用于构建完整的URL

函数定义

def extract_list_url(source, domain):page_list = source.find("div", class_="ContL")list_chapter = page_list.find("div", "list")a_list = list_chapter.findAll("a")href_list = []for a in a_list:href = a.get("href")everyUrl = domain + hrefhref_list.append(everyUrl)return href_list

详细实现步骤

1. 定位主要内容区域

page_list = source.find("div", class_="ContL")
  • 使用 find() 方法查找类名为 “ContL” 的 div 元素
  • 这个 div 是包含所有章节链接的容器
  • 与 extract_chapter_names 函数使用相同的定位方式

2. 定位章节列表区域

list_chapter = page_list.find("div", "list")
  • 在主要内容区域中查找类名为 “list” 的 div 元素
  • 这个 div 包含了所有章节的链接信息

3. 获取所有链接元素

a_list = list_chapter.findAll("a")
  • 使用 findAll() 方法获取所有的 <a> 标签
  • 每个 <a> 标签包含了章节的相对URL

4. 提取和组合URL

href_list = []
for a in a_list:href = a.get("href")everyUrl = domain + hrefhref_list.append(everyUrl)
  • 创建空列表 href_list 存储完整URL
  • 遍历每个 <a> 标签
  • 使用 get("href") 获取链接的相对路径
  • 将域名和相对路径组合成完整的URL
  • 将完整URL添加到列表中

5. 返回结果

return href_list
  • 返回包含所有章节完整URL的列表

示例输出

函数返回的列表格式如下:

["https://www.shicimingju.com/book/hongloumeng/1.html","https://www.shicimingju.com/book/hongloumeng/2.html",# ... 更多章节URL
]

URL 结构说明

完整URL的构成:

  • 域名:https://www.shicimingju.com
  • 相对路径:/book/hongloumeng/章节序号.html
  • 组合后:https://www.shicimingju.com/book/hongloumeng/章节序号.html

注意事项

  1. 确保传入的 domain 参数末尾没有多余的斜杠,避免URL重复
  2. 函数依赖于网站的特定HTML结构,网站改版时需要更新代码
  3. 确保传入的 source 是有效的 BeautifulSoup 对象
  4. URL 组合时要注意路径的正确性

可能的改进

  1. 添加URL有效性验证
  2. 添加错误处理机制
  3. 可以添加URL格式检查
  4. 可以添加并行获取功能提高效率
  5. 添加URL去重机制
  6. 可以添加URL规范化处理
  7. 添加日志记录功能,方便调试和监控

4. 下载章节内容

extract_chapter_content 函数实现以下功能:

  • 创建保存小说的文件夹
  • 遍历所有章节URL
  • 下载并解析章节内容
  • 保存到独立的文本文件
  • 包含5秒延迟,避免请求过于频繁

extract_chapter_content 函数详细说明

函数概述

extract_chapter_content 函数是整个爬虫项目的核心函数,负责下载和保存小说内容。这个函数接收四个参数:

  • url_list: 所有章节的URL列表
  • chapter_names: 对应的章节名称列表
  • headers: HTTP请求头
  • folder_name: 保存小说内容的文件夹名称

函数定义

def extract_chapter_content(url_list, chapter_names, headers, folder_name):if not os.path.exists(folder_name):os.makedirs(folder_name)for i, url in enumerate(url_list):response = session.get(url, headers=headers)if response.status_code != 200:logging.error(f"请求失败,状态码: {response.status_code}")else:response.encoding = "utf-8"soup = BeautifulSoup(response.text, "html.parser")a = soup.find("div", class_="ContL")b = a.find("div", class_="contbox textinfor")c = b.find("div", class_="text p_pad")p_list = c.findAll("p")seen_texts = set()chapter_content = []for p in p_list:text = p.getText().replace('\xa0', ' ')if text not in seen_texts:print(text)chapter_content.append(text)seen_texts.add(text)chapter_name = chapter_names[i]file_path = os.path.join(folder_name, f"{chapter_name}.txt")with open(file_path, "w+", encoding="utf-8") as file:file.write("\n".join(chapter_content))print(f"{chapter_name}章节的内容获取完毕")time.sleep(5)print(f"{i}章节的内容获取完毕")

详细实现步骤

1. 创建保存目录

if not os.path.exists(folder_name):os.makedirs(folder_name)
  • 检查保存目录是否存在
  • 如果目录不存在,则创建新目录
  • 使用 os.makedirs() 可以创建多层目录结构

2. 遍历章节URL

for i, url in enumerate(url_list):
  • 使用 enumerate() 同时获取索引和URL
  • 索引用于匹配章节名称
  • URL用于下载具体内容

3. 发送HTTP请求

response = session.get(url, headers=headers)
if response.status_code != 200:logging.error(f"请求失败,状态码: {response.status_code}")
  • 使用 session 发送GET请求
  • 检查响应状态码
  • 记录错误日志(如果请求失败)

4. 解析章节内容

response.encoding = "utf-8"
soup = BeautifulSoup(response.text, "html.parser")
a = soup.find("div", class_="ContL")
b = a.find("div", class_="contbox textinfor")
c = b.find("div", class_="text p_pad")
p_list = c.findAll("p")
  • 设置正确的字符编码
  • 使用BeautifulSoup解析HTML
  • 逐层定位到具体内容区域
  • 获取所有段落内容

5. 内容去重和清理

seen_texts = set()
chapter_content = []
for p in p_list:text = p.getText().replace('\xa0', ' ')if text not in seen_texts:print(text)chapter_content.append(text)seen_texts.add(text)
  • 使用集合去除重复内容
  • 清理特殊字符(如\xa0)
  • 保存清理后的文本
  • 打印内容用于调试

6. 保存章节内容

chapter_name = chapter_names[i]
file_path = os.path.join(folder_name, f"{chapter_name}.txt")
with open(file_path, "w+", encoding="utf-8") as file:file.write("\n".join(chapter_content))
  • 获取对应的章节名称
  • 构建文件保存路径
  • 使用UTF-8编码保存文件
  • 用换行符连接各段落

7. 延迟处理

time.sleep(5)
print(f"{i}章节的内容获取完毕")
  • 添加5秒延迟避免请求过快
  • 打印进度信息

文件保存格式

每个章节保存为独立的文本文件:

  • 文件名:章节名.txt
  • 编码:UTF-8
  • 内容格式:段落间用换行符分隔

注意事项

  1. 确保网络连接稳定
  2. 注意请求频率限制
  3. 保持足够的磁盘空间
  4. 正确处理文件编码
  5. 注意错误处理和日志记录

可能的改进

  1. 添加断点续传功能
  2. 实现多线程下载
  3. 添加重试机制
  4. 增加进度条显示
  5. 支持自定义延迟时间
  6. 添加内容验证机制
  7. 支持不同的文本格式(如EPUB、PDF)
  8. 添加内容备份机制
  9. 实现错误自动恢复

使用方法

  1. 确保已安装所有依赖包
  2. 运行脚本:
python your_script.py

注意事项

  1. 请遵守网站的爬虫规则
  2. 代码中包含5秒的延迟,避免对目标网站造成压力
  3. 建议添加错误处理和日志记录
  4. 确保有足够的存储空间保存小说内容

输出结果

程序会在当前目录下创建一个"红楼梦"文件夹,其中包含所有章节的文本文件。每个文件以章节名命名,包含该章节的完整内容。

可能的改进

  1. 添加命令行参数支持不同小说的爬取
  2. 增加断点续传功能
  3. 添加更完善的错误处理
  4. 支持多线程下载
  5. 添加进度条显示
  6. 支持导出不同格式(如PDF、EPUB等)

完整代码示例


"""完成的代码如下所示"""
import os
import requests
import logging
import time
from bs4 import BeautifulSoupdef extract_chapter_names(source):page_list = source.find("div", class_="ContL")list_chapter = page_list.find("div", "list")a_list = list_chapter.findAll("a")chapter_names = []for a in a_list:print(a.get_text())chapter_names.append(a.get_text())return chapter_names  # 返回章节的名称列表def extract_list_url(source, domain):# 抓取每一个章节的urlpage_list = source.find("div", class_="ContL")list_chapter = page_list.find("div", "list")a_list = list_chapter.findAll("a")href_list = []for a in a_list:href = a.get("href")everyUrl = domain + hrefhref_list.append(everyUrl)return href_list  # 返回每一个章节对应的url# 抓取单个小说的章节内容
def extract_chapter_content(url_list, chapter_names, headers, folder_name):if not os.path.exists(folder_name):os.makedirs(folder_name)for i, url in enumerate(url_list):response = session.get(url, headers=headers)if response.status_code != 200:logging.error(f"请求失败,状态码: {response.status_code}")else:response.encoding = "utf-8"soup = BeautifulSoup(response.text, "html.parser")a = soup.find("div", class_="ContL")b = a.find("div", class_="contbox textinfor")c = b.find("div", class_="text p_pad")p_list = c.findAll("p")seen_texts = set()chapter_content = []for p in p_list:text = p.getText().replace('\xa0', ' ')  # 处理NBSPif text not in seen_texts:print(text)chapter_content.append(text)seen_texts.add(text)chapter_name = chapter_names[i]file_path = os.path.join(folder_name, f"{chapter_name}.txt")with open(file_path, "w+", encoding="utf-8") as file:file.write("\n".join(chapter_content))print(f"{chapter_name}章节的内容获取完毕")time.sleep(5)print(f"{i}章节的内容获取完毕")print("整个小说爬取完毕")if __name__ == '__main__':url = "https://www.shicimingju.com/book/hongloumeng.html"headers = {"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/131.0.0.0 Mobile Safari/537.36 "}session = requests.session()page_source = session.get(url, headers=headers)# 检查请求是否成功if page_source.status_code != 200:logging.error(f"请求失败,状态码: {page_source.status_code}")else:page_source.encoding = "utf-8"domain = "https://www.shicimingju.com"soup = BeautifulSoup(page_source.text, "html.parser")chapter_names = extract_chapter_names(soup)list_url = extract_list_url(soup, domain)extract_chapter_content(list_url, chapter_names, headers, folder_name="./红楼梦") 

补充说明

可以使用多线程爬取或者携程爬取,当然多线程爬取就已经够用了,太快了不好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/65662.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTPS验证流程

http通常是直接和TCP进行通信的&#xff0c;而https中http是和SSL通信&#xff0c;再由SSL与TCP进行通信。SSL协议是一个介于应用层和传输层之间的一个安全协议。 1.对称加密与非对称加密 对称加密&#xff1a; 加密和解密方式都使用同一个私钥和公开的加密算法&#xff0c;优…

履约系统:应用层、领域层、集成关系设计

在这篇文章中&#xff0c;我们一起探讨订单履约系统的应用架构设计。 应用架构设计 我们前面讨论了系统的核心概念模型和拆单逻辑。接下来&#xff0c;让我们从应用架构的角度&#xff0c;深入了解系统的各个层次。这包括应用层、领域层&#xff0c;以及与其他系统的集成关系。…

python利用selenium实现大麦网抢票

大麦网&#xff08;damai.cn&#xff09;是中国领先的现场娱乐票务平台&#xff0c;涵盖演唱会、音乐会、话剧、歌剧、体育赛事等多种门票销售。由于其平台上经常会有热门演出&#xff0c;抢票成为许多用户关注的焦点。然而&#xff0c;由于票务资源的有限性&#xff0c;以及大…

神经网络-SENet

SENet是一种用于图像分类的卷积神经网络模型&#xff0c;由Jie Hu等人在2018年提出。SENet的全称是“Squeeze-and-Excitation Network”&#xff0c;其核心思想是通过自适应地调整每个通道的特征图权重&#xff0c;来增强卷积神经网络对于不同特征的感知能力。 SENet的设计灵感…

【spring】参数校验Validation

前言 在实际开发中&#xff0c;我们无法保证客户端传来的请求都是合法的。比如一些要求必传的参数没有传递&#xff0c;传来的参数长度不符合要求等&#xff0c;这种时候如果放任不管&#xff0c;继续执行后续业务逻辑&#xff0c;很有可能就会出现意想不到的bug。 有人可能会…

sentinel-请求限流、线程隔离、本地回调、熔断

请求限流&#xff1a;控制QPS来达到限流的目的 线程隔离&#xff1a;控制线程数量来达到限流的目录 本地回调&#xff1a;当线程被限流、隔离、熔断之后、就不会发起远程调用、而是使用本地已经准备好的回调去提醒用户 服务熔断&#xff1a;熔断也叫断路器&#xff0c;当失败、…

github提交不上去,网络超时问题解决

问题出现的原因&#xff1a; DNS服务器数据不同步&#xff0c;github的服务器发送迁移&#xff0c;在本地缓存的ip地址现在无效了。 解决方案&#xff1a; 1&#xff09;点击这里&#xff0c;查询github.com最新的ip地址 2.0&#xff09;编辑linux系统地址缓存文件&#x…

C++和OpenGL实现3D游戏编程【连载19】——着色器光照初步(平行光和光照贴图)(附源码)

1、本节要实现的内容 我们在前期的教程中,讨论了在即时渲染模式下的光照内容。但在我们后期使用着色器的核心模式下,会经常在着色器中使光照,我们这里就讨论一下着色器光照效果,以及光照贴图效果,同时这里知识会为后期的更多光照效果做一些铺垫。本节我们首先讨论冯氏光照…

如何恢复永久删除的PPT文件?查看数据恢复教程!

可以恢复永久删除的PPT文件吗&#xff1f; Microsoft PowerPoint应用程序是一种应用广泛的演示程序&#xff0c;在人们的日常生活中经常使用。商人、官员、学生等在学习和工作中会使用PowerPoint做报告和演示。PowerPoint在人们的学习和工作生活中占主导地位&#xff0c;每天都…

基于Spark的共享单车数据存储系统的设计与实现_springboot+vue

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

mysql高频面试题

1. mysql里的索引类型 2. 聚簇索引和非聚簇索引的区别 聚簇索引适合场景: 主键、唯一性要求高的字段。需要对数据进行范围查询时。对数据的读取频繁,并且数据行的插入和删除较少时。非聚簇索引适合场景: 较多的查询条件,或者需要基于某些非主键字段进行查询时。需要创建多个…

MySQL第二弹----CRUD

笔上得来终觉浅,绝知此事要躬行 &#x1f525; 个人主页&#xff1a;星云爱编程 &#x1f525; 所属专栏&#xff1a;MySQL &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ 一、修改表 使用ALTER …

c++解决常见内存泄漏问题——智能指针的使用及其原理

目录 前言&#xff1a; 1. 智能指针的使用及其原理 1. 1 智能指针的使用场景分析 1.2 RAII和智能指针的设计思路 1.3 C标准库智能指针的使用 1.3 1 auto_ptr 1.3 2 unique_ptr 1.3 3 shared_ptr(重&#xff09; 1.3 4 weak_ptr 1.3 5 模拟实现删除器 2.智能指针的原…

NVR管理平台EasyNVR设备通过ONVIF接入出现404访问错误是什么原因?

如今&#xff0c;视频监控在各行各业都得到了广泛应用&#xff0c;成为现代社会不可或缺的一部分。随着技术的不断进步&#xff0c;视频监控系统已经从传统的模拟监控发展到高清化、网络化和智能化阶段&#xff0c;其应用领域也从最初的安防扩展到智慧城市、智能家居、交通管理…

CANape 新建工程和连接

文章目录 简介1、新建工程1.1 打开 CANape1.2 新建工程1.3 新建 Device1.3.1 添加NEW DEVICE1.3.2 添加 NEW From Database1.4 配置 Memory Segment1.5 新建trace窗口和观测窗口 2、硬件连接2.1 更改与canape盒子通道一致的通道编号&#xff0c;选择驱动配置2.2 选择硬件配置 问…

[Qt] Qt介绍 | 搭建SDK

目录 1. Qt 简介 什么是 Qt&#xff1f; 1.1 引入 1.2 GUI 1.3 Qt 介绍 2. Qt 发展史 3. Qt 支持的平台 4. Qt 版本信息 5. Qt 的优点 6. Qt 应用场景 7. Qt 成功案例 8. Qt 发展前景及就业分析 二. Qt 开发环境搭建 1. 开发工具概述 2.Qt SDK 安装 3.使用 1. …

ES 磁盘使用率检查及处理方法

文章目录 1. 检查原因2. 检查方法3. 处理方法3.1 清理数据3.2 再次检查磁盘使用率 1. 检查原因 磁盘使用率在 85%以下&#xff0c;ES 可正常运行&#xff0c;达到 85%及以上会影响 PEIM 数据存储。 在 ES 磁盘分配分片控制策略中&#xff0c;为了保护数据节点的安全&#xff0…

NLP自然语言处理——使用飞桨实现基于LSTM的情感分析

任务说明&#xff1a; 通过对电影评论历史数据分析&#xff0c;构建深度学习分类模型&#xff0c;最终完成对新的数据样本的识别分类。 任务要求&#xff1a; 运用神经网络算法&#xff0c;创建、训练、评估模型&#xff0c;完成对电影评论的情感分类任务。 数据集说明&#xf…

LabVIEW条件配置对话框

条件配置对话框&#xff08;Configure Condition Dialog Box&#xff09; 要求&#xff1a;Base Development System 当右键单击**条件禁用结构&#xff08;Conditional Disable Structure&#xff09;**并选择以下选项时&#xff0c;会显示此对话框&#xff1a; Add Subdiagr…

为什么MoE推理效率更高:精简FFN

MoE全称是“混合专家”,它由多个专家网络和一个门控网络组成……整个MoE完全复用了Transformer的结构,只是将其中的FFN层替换成了MoE层。MoE层里的门控网络其实就是个专家分类器,每次根据输入Token生成专家的概率分布,然后选择排序靠前的K个专家进行Token处理,最后再将K个…