1.引言
1.1主题
本博客旨在通过一个具体的案例——使用scrapy框架采集小说内容,并存储子txt文件中,来展示网络爬虫技术的实际应用。我们将探索如何使用爬虫技术来自动收集、处理和分析网络上的公开数据,以及如何将这些数据转化为有价值的信息。
2.数据来源
url:https://www.bxuu.net/31/31909/
3.介绍scrapy框架
Scrapy是一个快速的、高层次的web抓取和网页爬虫框架,用于抓取web站点并从页面中提取结构化的数据。它提供了一套非常灵活的机制来抓取网站,并且可以用于各种用途,如数据挖掘、信息处理或历史存档。
以下是Scrapy框架的一些主要特点:
- 异步处理:Scrapy是基于Twisted异步网络框架构建的,这意味着它可以在不阻塞的情况下进行快速的网页请求。
- 高性能:Scrapy设计用于处理大量的并发请求,因此它非常适合大规模的抓取任务。
- 可扩展性:Scrapy允许用户通过编写扩展来增加额外的功能,这些扩展可以在抓取过程中的特定阶段被调用。
- 中间件支持:Scrapy提供了请求/响应中间件,用户可以自定义中间件来处理请求和响应。
- 选择器:Scrapy提供了XPath和CSS选择器,使得从HTML/XML响应中提取数据变得简单。
- 内置支持:Scrapy内置了对多种数据格式的支持,如JSON、CSV和XML。
- 命令行工具:Scrapy提供了一个命令行工具,可以通过命令行来运行爬虫、查看日志和执行其他任务。
- 项目结构:Scrapy项目通常包含一个项目文件、一个或多个爬虫文件、一个设置文件、一个中间件文件和一个管道文件。
- 管道(Pipelines):Scrapy允许定义管道来处理抓取到的数据,例如清洗、验证和存储。
- 去重:Scrapy内置了去重机制,可以避免重复抓取相同的页面。
- 支持代理:Scrapy支持使用代理服务器进行抓取,这对于绕过IP限制非常有用。
- 用户代理和Cookies:Scrapy可以模拟浏览器行为,包括设置用户代理和处理Cookies。
4.具体操作
4.1 命令行下载必要的库
pip install Scrapy # 注:windows平台需要依赖pywin32
pip install pypiwin32
4.2 创建项目
scrapy startproject myspider
cd myspider
scrapy genspider bxuu bxuu.net
4.3 全局设置-settings.py
# Scrapy 配置文件 for myspider2 项目
#
# 为了简化,此文件仅包含被认为是重要或
# 常见的设置。您可以通过以下链接找到更多设置:
#
# https://docs.scrapy.org/en/latest/topics/settings.html
# https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
# https://docs.scrapy.org/en/latest/topics/spider-middleware.html
# 用于生成随机的 User-Agent
from fake_useragent import UserAgent
# 定义机器人名称
BOT_NAME = "myspider2"
# 定义蜘蛛模块所在的位置
SPIDER_MODULES = ["myspider2.spiders"]
NEWSPIDER_MODULE = "myspider2.spiders"
# 通过识别自己(和您的网站)在 user-agent 上负责任地爬取
USER_AGENT = UserAgent().random # 使用随机 User-Agent
# 遵守 robots.txt 规则
ROBOTSTXT_OBEY = False # 默认情况下不遵守
# 配置项目管道
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
"myspider2.pipelines.BxuuPipeline": 300,
}
4.4 采集数据
import scrapy
class BxuuSpider(scrapy.Spider):
# 爬虫名称
name = "bxuu"
# 允许的域名
allowed_domains = ["bxuu.net"]
# 起始URL
start_urls = ["https://www.bxuu.net/31/31909/"]
def parse(self, response):
# 设置基础URL
self.base_url = 'https://www.bxuu.net/31/31909/'
# 获取书名并截取前7个字符
book_name = response.xpath('//*[@id="ztopinfo"]/div[2]/h1/text()').extract_first()
book_name = book_name[:7]
print(book_name)
# 获取章节标题和URL
chapters = response.xpath("//*[@id='zcontent']/dl/dd/a/text()").getall()[:135]
urls = response.xpath("//*[@id='zcontent']/dl/dd/a/@href").getall()[:135]
# 遍历章节和URL
for index,(url,chapter) in enumerate(zip(urls,chapters),start=1):
# 构建完整URL
compete_url=self.base_url+url.split('/')[-1]
print(f'chapter:{chapter},url:{compete_url}')
# 发送请求到章节页面
yield scrapy.Request(compete_url,callback=self.parse_chapter,meta={'book_name': book_name, 'chapter': chapter,'index':index})
def parse_chapter(self,response):
# 获取章节内容
content =response.xpath("//*[@id='content']/text()").extract()
content = ' '.join(content)
index = response.meta['index']
chapter = response.meta['chapter']
# 组装并返回章节信息
yield {
'book_name': response.meta['book_name'],
'chapter':chapter,
'content': content,
'index': index
}
4.5 保存数据-pipelines.py
# 在这里定义您的项目管道(pipeline)
#
# 别忘了在设置项`ITEM_PIPELINES`中添加您的管道
# 请参考: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# 对于使用统一接口处理不同类型的项目(item)很有用
from itemadapter import ItemAdapter
import os
# 定义BxuuPipeline类,用于处理爬取到的项目数据
class BxuuPipeline:
# 当Spider开启时调用,用于做一些初始化工作
def open_spider(self, spider):
# 打印开始爬取信息
print("开始爬取")
# 用于处理每个采集到的项目(item)
def process_item(self, item, spider):
# 获取书籍的名称,用于创建目录
dir_path = item.get('book_name')
# 如果书籍目录不存在,则创建
if not os.path.exists(dir_path):
os.mkdir(dir_path)
# 获取章节的索引,用于文件命名
index = str(item.get('index'))
# 获取章节的标题
chapter = item.get('chapter')
# 构造文件名
file_name = f"{index}_{chapter}.txt"
# 构造文件的完整路径
file_path = os.path.join(dir_path,file_name)
# 如果文件不存在,则创建并写入章节内容
if not os.path.exists(file_path):
with open(file_path,'w',encoding='utf-8') as f:
f.write(item.get('content'))
# 返回项目对象,以便后续管道继续处理
return item
# 当Spider关闭时调用,用于做一些收尾工作
def close_spider(self, spider):
# 打印爬取结束信息
print("爬取结束")
4.6 运行结果