目录
Scrapy官网:https://scrapy.org/
什么是Scrapy
Scrapy 是一个基于 Python 的快速的高级网页抓取和网页爬取框架,用于抓取网站并从其页面中提取结构化数据。它可用于多种用途,从数据挖掘到监控和自动化测试。
Scrapy核心组件
- 1. Scrapy Engine(Scrapy引擎)
- Scrapy 引擎是整个系统的核心,负责控制数据流在所有组件之间的流动。它从调度器获取请求,发送给下载器处理,然后将下载器返回的响应交给爬虫处理。
- 2. Scheduler(调度器)
- 调度器负责接收引擎发来的请求并进行排序,然后将这些请求发送给引擎。调度器可以处理优先级,并且支持去重机制以避免重复抓取。
- 3. Downloader(下载器)
- 下载器负责向互联网上的服务器发送请求,并接收响应。Scrapy 下载器是高度异步的,能够高效地处理大量请求。
- 4. Spiders(爬虫)
- 爬虫是用户定义的类,负责处理下载器返回的响应,从中提取数据(Item)或进一步生成请求。每个爬虫定义了要抓取的域名和处理响应的逻辑。
- 5. Item(数据项)
- Item 是一种简单的数据容器,用于存储从网页中提取的数据。Item 类似于字典,但提供了额外的保护和方法。
- 6. Item Pipeline(数据管道)
- 数据管道是一个序列化系统,用于处理和存储从爬虫中提取的数据。每个管道组件负责处理数据项的一部分,例如数据清洗、验证或存储。
- 7. Downloader Middlewares(下载中间件)
- 下载中间件是介于调度器和下载器之间的钩子,用于处理请求和响应。它们可以修改或扩展请求和响应的处理流程,例如设置代理、修改请求头等。
- 8. Spider Middlewares(爬虫中间件)
- 爬虫中间件是介于引擎和爬虫之间的钩子,用于处理爬虫输入和输出的响应和结果。它们可以修改或扩展爬虫的处理流程,例如添加额外的日志记录、处理异常等。
Scrapy扩展组件
- 1. Feed Exports(数据导出)
- Scrapy 支持将抓取的数据导出为多种格式(如 JSON、CSV、XML),并可以配置导出的细节(如字段顺序、编码等)。
- 2. Telnet Console(Telnet 控制台)
- Telnet 控制台提供了一个实时监控和调试爬虫的工具,允许开发者在爬虫运行时进行交互式调试。
- 3. Logging(日志)
- Scrapy 内置了强大的日志系统,用于记录运行时的各种信息,如调试信息、错误消息等。日志系统可以配置不同的日志级别和输出格式。
- 4. Extensions(扩展)
- 扩展模块用于增强 Scrapy 的功能,例如自动重试失败的请求、监控爬虫性能等。开发者可以自定义扩展模块以满足特定需求。
- 5. Stats Collectors(统计收集器)
- 统计收集器用于收集和记录爬虫运行时的各种统计信息,如请求数量、响应时间等。统计信息可以用于优化和调试爬虫。
组件交互流程
- 初始请求:爬虫从 start_urls 生成初始请求,并通过引擎(Engine)发送给调度器(Scheduler)。
- 请求调度:调度器(Scheduler)将请求排序并发送给下载器(Downloader)。
- 请求下载:下载器(Downloader)向目标网站(Internet)发送请求并获取响应。
- 响应处理:下载器(Downloader)将响应发送给引擎(Engine),进而交给爬虫(Spiders)处理。
- 数据提取:爬虫(Spiders)从响应中提取数据项,并生成新的请求(如果有)。
- 数据处理:提取的数据项通过数据管道(Item Pipeline)进行处理和存储。
安装Scrapy
pip install scrapy
Scrapy项目目录结构说明
Scrapy 项目的结构较为标准,以下是一个典型的 Scrapy 项目的目录结构图示及其简要说明,供方便理解。
myproject/
│
├── myproject/ # 项目目录(主目录)
│ ├── __init__.py
│ ├── items.py # 定义 Item 类(数据结构)
│ ├── middlewares.py # 自定义中间件
│ ├── pipelines.py # Item 处理管道
│ ├── settings.py # 项目设置文件
│ ├── spiders/ # 存放爬虫的目录
│ │ ├── __init__.py
│ │ ├── example_spider.py # 定义爬虫
│
├── scrapy.cfg # Scrapy 配置文件
│
└── README.md # 项目的说明文件(可选)
创建Scrapy项目
使用 scrapy startproject 命令来创建一个新的 Scrapy 项目。打开终端或命令行,进入你想要创建项目的目录,并运行以下命令
# scrapy startproject <项目名称>
scrapy startproject myproject
创建爬虫
在项目根目录中,你可以使用 scrapy genspider 命令创建新的爬虫。以下命令将创建一个名为 baidu 的爬虫,用于抓取 www.baidu.com 的域名
# scrapy genspider <爬虫名称> <允许爬取的域名>
scrapy genspider baidu www.baidu.com
完整目录结构如下
爬虫文件内容说明
解析方法解析response
# 解析方法,response:爬取起始url的响应
def parse(self, response):
# 解析示例
with open("baidu.html", "wb") as f:
f.write(response.body)
运行爬虫
运行爬虫之前需要修改 settings.py 配置文件的配置,如下:
使用 scrapy crawl 命令来运行你的爬虫。以下命令会启动名为 baidu 的爬虫:
# scrapy crawl <爬虫名称>
scrapy crawl baidu
配置请求头
-
全局配置请求头
在 settings.py 配置文件中,配置 USER_AGENT 和 DEFAULT_REQUEST_HEADERS 参数,示例如下:
# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
# Override the default request headers:
DEFAULT_REQUEST_HEADERS = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.9",
}
-
指定爬虫配置请求头
在指定爬虫文件中,配置 start_requests 方法,示例如下:
import scrapy
class TeibaSpider(scrapy.Spider):
name = "teiba"
allowed_domains = ["tieba.baidu.com"]
start_urls = ["https://tieba.baidu.com/f?kw=沙井"]
def start_requests(self):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
'Accept-Language': 'zh-CN,zh;q=0.9',
}
for url in self.start_urls:
yield scrapy.Request(url, headers=headers, callback=self.parse)
def parse(self, response):
pass
配置管道pipeline
-
全局配置pipeline
在 settings.py 配置文件中,配置ITEM_PIPELINES 参数用于开启管道,示例如下:
# Configure item pipelines
ITEM_PIPELINES = {
# myproject:项目名称
# pipelines:项目下的pipelines.py文件
# MyprojectPipeline:pipelines.py文件中指定的类
# 300:管道优先级,多个管道时,数字越小优先级越高越先执行
"myproject.pipelines.MyprojectPipeline": 300,
}
pipelines.py 文件内容如下:
当管道开启后,在我们启动爬虫时,日志打印信息如下:
-
方式一:指定爬虫配置pipeline
在指定爬虫文件中,配置 custom_settings 属性,示例如下:
import scrapy
class TeiBaSpider(scrapy.Spider):
name = "teiba"
allowed_domains = ["tieba.baidu.com"]
start_urls = ["https://tieba.baidu.com/f?kw=沙井"]
# 指定 pipeline
custom_settings = {
'ITEM_PIPELINES': {
'myproject.pipelines.TieBaPipeline': 300,
}
}
def parse(self, response):
item = {}
item['title='] = a.xpath('./@title').get()
item['url='] = "https://tieba.baidu.com/" + a.xpath('./@href').get()
# yield 的数据会返回到 TieBaPipeline 中
yield item
pipelines.py 文件内容如下:
-
方式二:指定爬虫配置pipeline
在 settings.py 配置文件中,配置 ITEM_PIPELINES 参数配置多个,示例如下:
ITEM_PIPELINES = {
"myproject.pipelines.BaiDuPipeline": 300,
"myproject.pipelines.TieBaPipeline": 301,
}
在 pipelines.py 文件中通过爬虫名称判断
from itemadapter import ItemAdapter
class BaiDuPipeline:
def open_spider(self, spider):
# 初始化方法,类比 def __init__(self)
if spider.name == "baidu":
pass
def process_item(self, item, spider):
if spider.name == "baidu":
pass
return item
def close_spider(self, spider):
# 析构方法,类比 def __del__(self)
if spider.name == "baidu":
pass
class TieBaPipeline:
def open_spider(self, spider):
if spider.name == "tieba":
pass
def process_item(self, item, spider):
if spider.name == "tieba":
pass
return item
def close_spider(self, spider):
if spider.name == "tieba":
pass
数据建模 items
数据建模的好处是统一数据字段免得写错,会在执行的时候对模板字段进行检测。清晰代码便于维护等好处。
1. 创建模型
在 items.py 文件中,创建模型
import scrapy
class UserItem(scrapy.Item):
# define the fields for your item here like:
# 用户名称
name = scrapy.Field()
# 用户年龄
age = scrapy.Field()
2. 爬虫中使用模型
import scrapy
from myproject.items import UserItem
class BaiduSpider(scrapy.Spider):
name = "baidu"
allowed_domains = ["www.baidu.com"]
start_urls = ["https://www.baidu.com"]
def parse(self, response):
# 使用模型
item = UserItem()
item['name'] = response.xpath('//h1/text()').get()
item['age'] = response.xpath('//h2/text()').get()
yield item
3. 管道中使用模型
from itemadapter import ItemAdapter
class MyprojectPipeline:
def process_item(self, item, spider):
# 把对象类型转换成字典类型
item = dict(item)
return item