在数据驱动的时代,网络爬虫已成为获取公开信息的核心工具。本文将带您通过Scrapy框架完成一个实战项目,涵盖从零搭建爬虫到多格式数据导出的完整流程,并深入解析Scrapy的Feed Exports功能。
一、项目背景与目标
我们将爬取书籍网站,提取每本书的URL、标题和价格,并将结果保存为多种格式文件(CSV/JSON/XML等)。此案例适用于数据挖掘、竞品分析等场景。
二、环境准备
1. 安装Scrapy
pip install scrapy
2. 创建项目与爬虫
scrapy startproject booklist # 创建项目
cd booklist
scrapy genspider book books.toscrape.com # 生成爬虫
三、核心代码实现
1. 定义数据结构(Items)
编辑 items.py
,声明需抓取的字段:
# booklist/items.py
from scrapy.item import Item, Field
class BooklistItem(Item):
url = Field() # 书籍链接
title = Field() # 书名
price = Field() # 价格
2. 编写爬取逻辑(Spider)
在 spiders/book.py
中实现数据提取:
import scrapy
from booklist.items import BooklistItem
class BookSpider(scrapy.Spider):
name = 'book'
allowed_domains = ['books.toscrape.com']
start_urls = ['http://books.toscrape.com/']
def parse(self, response):
for article in response.css('article.product_pod'):
yield BooklistItem(
url=response.urljoin(article.css("h3 > a::attr(href)").get()),
title=article.css("h3 > a::attr(title)").get(),
price=article.css(".price_color::text").get()
)
四、数据导出实战
方法1:命令行快速导出
通过 -o
参数直接指定输出文件(支持覆盖模式 -O
):
scrapy crawl book -o data/books.csv # CSV格式
scrapy crawl book -o data/books.json # JSON格式
scrapy crawl book -o data/books.xml # XML格式
方法2:配置文件管理导出(推荐)
代码位置
在 settings.py
中全局配置导出规则,适用于所有爬虫任务。
FEEDS = {
'data/output.csv': { # 输出文件路径
'format': 'csv', # 文件格式为CSV
'overwrite': True, # 如果文件已存在,则覆盖
'encoding': 'utf8' # 使用UTF-8编码
},
'data/output.json': { # 第二个输出文件路径
'format': 'json', # 文件格式为JSON
'indent': 4 # JSON文件缩进4个空格(美化格式)
}
}
关键点说明
- 多文件同时导出
✅ 是的! 这段代码会同时生成两个文件:data/output.csv
(CSV格式)data/output.json
(JSON格式)
Scrapy会根据配置自动处理,无需额外操作。
- 参数详解
format
: 指定导出文件的格式(支持csv
/json
/jsonlines
/xml
)。overwrite
: 若为True
,会覆盖已存在的文件;若为False
,则追加数据(部分格式不支持追加)。indent
: 仅对JSON有效,控制缩进空格数(美化输出)。encoding
: 指定文件编码(默认为UTF-8)。
- 文件路径规则
- 路径是相对于Scrapy项目根目录的(即与
settings.py
同级)。 - 若
data/
文件夹不存在,需提前手动创建,否则会报错。
- 路径是相对于Scrapy项目根目录的(即与
方法3:动态路径与自定义设置
在爬虫类(如 book.py
)中通过 custom_settings
覆盖全局配置。
custom_settings = {
'FEEDS': {
f'data/{name}_{time}.json': { # 动态文件名(需定义name和time变量)
'format': 'json',
'encoding': 'utf8'
}
}
}
关键点说明
-
动态文件名
-
{name}
和{time}
是占位符,但直接这样写会报错,因为name
和time
未定义。 -
正确写法需通过Scrapy内置变量实现动态路径,例如:
python
复制
f'data/{self.name}_{datetime.now().strftime("%Y%m%d")}.json'
需在爬虫类中导入
datetime
并调整代码结构。
-
-
优先级
custom_settings
的优先级高于全局settings.py
中的配置。- 若同时存在,以爬虫类中的设置为准。
-
适用场景
- 需要为不同爬虫任务定制输出路径时(如按日期、爬虫名称分类存储)。
- 需要动态生成文件名时(如加入时间戳)。
对比总结
特性 | 方法2(全局配置) | 方法3(自定义设置) |
---|---|---|
作用范围 | 所有爬虫共享 | 仅当前爬虫生效 |
多文件导出 | ✅ 支持 | ✅ 支持(需手动配置多个条目) |
动态路径 | ❌ 需硬编码路径 | ✅ 支持通过变量动态生成 |
代码维护性 | 集中管理,适合多爬虫项目 | 灵活,适合单一爬虫的定制需求 |
常见问题
-
如何同时导出多个格式?
在FEEDS
中添加多个条目即可(如方法2所示),Scrapy会分别处理。 -
动态路径中的变量如何定义?
需通过爬虫类的custom_settings
结合Python代码生成,例如:from datetime import datetime class BookSpider(scrapy.Spider): name = 'book' custom_settings = { 'FEEDS': { f'data/{name}_{datetime.now().strftime("%Y%m%d")}.json': { 'format': 'json' } } }
⚠️ 注意:直接使用
name
和time
会报错,需通过类属性或函数动态生成。 -
文件路径错误怎么办?
- 检查路径是否拼写正确。
- 确保父目录(如
data/
)已存在。 - 使用绝对路径(如
/tmp/data/output.json
)避免权限问题。
五、进阶技巧
1. 动态路径生成
通过占位符实现结构化存储:
FEEDS = {
'data/%(name)s/%(time)s.json': { # 如:data/book/20231010.json
'format': 'json'
}
}
2. 多格式同时导出
FEEDS = {
'books.csv': {'format': 'csv'},
'books.json': {'format': 'json'}
}
六、常见问题解决
问题 | 解决方案 |
---|---|
文件路径错误 | 检查项目根目录是否存在data 文件夹 |
编码乱码 | 添加'encoding': 'utf8' 配置 |
数据丢失 | 确认CSS选择器是否匹配目标网站最新结构 |
七、最后总结
本文通过Scrapy框架实现了从数据抓取到多格式导出的全流程,关键点包括:
- Items定义:结构化存储数据字段
- Spider逻辑:精准提取目标信息
- Feed Exports:灵活配置输出格式与路径
建议扩展方向:
- 增加异常处理(如重试机制)
- 对接数据库(MySQL/MongoDB)
- 部署至ScrapingHub云平台
立即动手尝试,开启您的数据采集之旅!