如何使用 Python 爬取多章节小说并保存为文本文件

前言

网络爬虫是一个非常有趣且实用的技术,尤其是在我们需要从网站上自动获取数据时。在这篇博客中,我将分享如何使用 Python 的 requestslxml 库来编写一个简单的爬虫,从某个小说网站上爬取整本小说的章节内容,并将其保存为一个本地的文本文件。

我们将介绍逐行的代码解析、爬取流程,以及如何处理特殊情况,比如爬取到最后一章时终止程序。

使用的工具和库

在这次项目中,我们主要用到以下几个 Python 库:

  • requests:用于发送 HTTP 请求并获取网页的 HTML 内容。
  • lxml:用于解析 HTML 内容,帮助我们使用 XPath 定位并提取需要的数据。
  • timerandom:用于添加延迟和生成随机的等待时间,防止频繁请求被服务器封禁。

在开始之前,确保你已安装了这些库,可以通过以下命令安装:

pip install requests
pip install lxml

爬虫流程

这个爬虫的任务是逐章获取小说内容,并将每一章的内容保存到本地文件中。以下是主要的爬取步骤:

  1. 获取小说初始章节的 URL
  2. 发送 HTTP 请求,获取页面内容。
  3. 解析 HTML 页面,提取章节标题和正文内容。
  4. 将内容保存到本地文件
  5. 查找下一章的链接,并重复上述步骤。
  6. 当爬取到最后一章时,程序终止。

完整代码

import requests
import time
import random
from lxml import etree

# 初始页面URL和最终页面URL
url = 'https://dldl1.nsbuket.cc/xiaoshuo/douluodalu/1.html'
final_url = 'https://dldl1.nsbuket.cc/xiaoshuo/douluodalu/'

# 创建会话,便于维持长连接
session = requests.Session()
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0',
}

# 爬取小说
while url:
    try:
        # 添加随机延迟,防止过快爬取
        time.sleep(random.uniform(3, 5))

        # 发送GET请求获取页面内容
        resp = session.get(url, headers=headers)
        resp.encoding = 'utf-8'  # 确保处理中文字符

        # 解析页面HTML
        e = etree.HTML(resp.text)

        # 获取章节标题和正文
        info = '\n'.join(e.xpath('//div[@class="m-post"]/p/text()'))
        title = e.xpath('//h1/text()')[0]

        # 将章节内容写入文件
        with open('斗罗大陆.txt', 'a', encoding='utf-8') as f:
            f.write(title + '\n\n' + info + '\n\n')

        print(f"已保存: {title}")

        # 获取下一章链接
        next_link = e.xpath("//tr/td[2]/a/@href")
        if next_link:
            next_url = f'https://dldl1.nsbuket.cc{next_link[0]}'
            if next_url == final_url:
                print("已到达最后一章,爬取结束。")
                break
            else:
                url = next_url
        else:
            print("没有找到下一章的链接,爬取结束。")
            break

    except requests.exceptions.RequestException as e:
        print(f"请求出现错误: {e}")
        time.sleep(5)  # 出现错误时等待5秒再重试
    except Exception as ex:
        print(f"发生错误: {ex}")
        break

定义初始和结束 URL

url = 'https://dldl1.nsbuket.cc/xiaoshuo/douluodalu/1.html'
final_url = 'https://dldl1.nsbuket.cc/xiaoshuo/douluodalu/'
  • url: 小说第一章的 URL,是程序爬取的起点。
  • final_url: 定义最后一章的 URL,当爬虫遇到这个 URL 时会停止。

创建会话和请求头

session = requests.Session()
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0',
}
  • session: requests.Session() 用于创建会话,这样可以在多个请求之间共享 cookies 和其他参数,提高效率。
  • headers: 设置 User-Agent 模拟浏览器访问,避免网站因为识别到爬虫而拒绝请求。

爬取循环

while url:
    try:
        time.sleep(random.uniform(3, 5))  # 添加随机延迟,防止被封
        resp = session.get(url, headers=headers)
        resp.encoding = 'utf-8'
        e = etree.HTML(resp.text)
  • 循环结构: while url 只要有下一章的 URL,程序就会继续循环爬取。
  • 延迟请求: time.sleep(random.uniform(3, 5)) 生成 3 到 5 秒之间的随机延迟,模拟正常的访问行为。
  • 发送请求: resp = session.get(url, headers=headers) 向服务器发送请求,获取章节页面。
  • 设置编码: resp.encoding = 'utf-8' 确保可以正确处理中文字符。
  • 解析 HTML: etree.HTML(resp.text) 将获取到的 HTML 转换成可供 XPath 操作的树状结构。

提取内容和保存

        info = '\n'.join(e.xpath('//div[@class="m-post"]/p/text()'))
        title = e.xpath('//h1/text()')[0]
        with open('斗罗大陆.txt', 'a', encoding='utf-8') as f:
            f.write(title + '\n\n' + info + '\n\n')
        print(f"已保存: {title}")
  • 提取正文: e.xpath('//div[@class="m-post"]/p/text()') 用 XPath 提取小说正文,每一段文本用换行符 '\n'.join() 拼接在一起。
  • 提取标题: e.xpath('//h1/text()')[0] 提取章节标题。
  • 保存内容: 打开或创建一个名为 斗罗大陆.txt 的文件,并将章节标题和正文内容按顺序追加写入文件中。
  • 打印信息: print(f"已保存: {title}") 输出保存的章节标题,帮助我们实时监控爬取进度。

查找下一章

        next_link = e.xpath("//tr/td[2]/a/@href")
        if next_link:
            next_url = f'https://dldl1.nsbuket.cc{next_link[0]}'
            if next_url == final_url:
                print("已到达最后一章,爬取结束。")
                break
            else:
                url = next_url
        else:
            print("没有找到下一章的链接,爬取结束。")
            break
  • 查找下一章链接: e.xpath("//tr/td[2]/a/@href") 使用 XPath 找到下一章的链接。如果有链接,程序会将其与主域名拼接成完整的 URL。
  • 结束条件: 如果下一章的 URL 是我们设定的 final_url,说明已经爬取到最后一章,程序终止爬取。
  • 没有找到下一章: 如果没有找到下一章的链接,爬虫会输出信息并终止爬取。

异常处理

    except requests.exceptions.RequestException as e:
        print(f"请求出现错误: {e}")
        time.sleep(5)
    except Exception as ex:
        print(f"发生错误: {ex}")
        break
  • 异常捕获: 如果在请求过程中发生网络错误,程序不会崩溃,而是等待 5 秒后重试。其他异常将终止爬取并输出错误信息。

小结

通过这篇博客,我们构建了一个简单但功能强大的爬虫。它能够自动抓取小说的多章节内容,并将它们按顺序保存到本地文件。我们实现了以下功能:

  • 随机延迟防止爬虫被封禁。
  • 处理章节内容和链接的提取。
  • 保存每章内容到文件。
  • 到达最后一章时结束爬取。

这只是爬虫的一个基础示例,针对不同网站的结构,爬虫可以进一步扩展。希望这篇文章能够为你提供一些启发,让你在爬虫的世界里更进一步!

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值