网络爬虫是一个非常有趣且实用的技术,尤其是在我们需要从网站上自动获取数据时。在这篇博客中,我将分享如何使用 Python 的 requests
和 lxml
库来编写一个简单的爬虫,从某个小说网站上爬取整本小说的章节内容,并将其保存为一个本地的文本文件。
我们将介绍逐行的代码解析、爬取流程,以及如何处理特殊情况,比如爬取到最后一章时终止程序。
在这次项目中,我们主要用到以下几个 Python 库:
requests
:用于发送 HTTP 请求并获取网页的 HTML 内容。lxml
:用于解析 HTML 内容,帮助我们使用 XPath 定位并提取需要的数据。time
和 random
:用于添加延迟和生成随机的等待时间,防止频繁请求被服务器封禁。在开始之前,确保你已安装了这些库,可以通过以下命令安装:
pip install requests
pip install lxml
这个爬虫的任务是逐章获取小说内容,并将每一章的内容保存到本地文件中。以下是主要的爬取步骤:
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 = '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'
确保可以正确处理中文字符。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。final_url
,说明已经爬取到最后一章,程序终止爬取。 except requests.exceptions.RequestException as e:
print(f"请求出现错误: {e}")
time.sleep(5)
except Exception as ex:
print(f"发生错误: {ex}")
break
通过这篇博客,我们构建了一个简单但功能强大的爬虫。它能够自动抓取小说的多章节内容,并将它们按顺序保存到本地文件。我们实现了以下功能:
这只是爬虫的一个基础示例,针对不同网站的结构,爬虫可以进一步扩展。希望这篇文章能够为你提供一些启发,让你在爬虫的世界里更进一步!