Scrapy爬虫框架学习介绍了Scrapy的强大功能和特点,包括异步处理、多种抓取策略和强大的数据提取工具。文章详细讲解了Scrapy的安装与环境搭建、项目结构与主要组件,以及XPath和CSS选择器的使用方法。此外,还涉及了数据提取与处理、中间件和管道的使用等高级内容。
Scrapy爬虫框架简介 Scrapy是什么Scrapy 是一个强大的 Python 组件,用于抓取网站并提取结构化数据。它能够处理大型网站,执行高效率的数据提取任务。Scrapy 是一个异步框架,支持多种抓取策略,包括深度优先和广度优先等。Scrapy 通常用于构建 Web 数据提取器,如网络爬虫、数据挖掘工具等。
Scrapy的特点和优势特点
- 异步处理: Scrapy 使用异步 I/O 来处理网络请求,能够在单个进程中处理大量的并发请求。
- 灵活的抓取策略: Scrapy 支持多种抓取策略,如深度优先和广度优先等。
- 强大的数据提取功能: Scrapy 提供了 XPath 和 CSS 选择器等强大的数据提取工具。
- 中间件支持: Scrapy 允许通过中间件来修改请求和响应,支持用户自定义中间件。
- 管道支持: Scrapy 支持通过管道将提取的数据进行处理和存储。
优势
- 高性能: Scrapy 的异步 I/O 设计使其在抓取大量数据时表现优异。
- 可扩展性: Scrapy 的模块化设计使它容易扩展和定制。
- 易于使用: Scrapy 提供了清晰的文档和丰富的示例代码,易于学习和使用。
- 丰富插件: Scrapy 生态系统中有大量的插件和扩展,可以满足不同的需求。
安装Scrapy
在安装 Scrapy 之前,确保你已经安装了 Python 3.x。Scrapy 支持 Python 3.6 及以上版本。以下是安装 Scrapy 的步骤:
- 打开终端或命令提示符。
-
使用 pip 命令安装 Scrapy:
pip install scrapy
-
如果安装成功,可以使用 Python 的命令行工具验证安装:
```bash票价
python -m scrapy startproject myproject如果没有错误输出,说明安装成功。
创建Scrapy项目
使用 Scrapy 创建一个新项目:
scrapy startproject myproject
这将创建一个名为 myproject
的目录,其中包含 Scrapy 项目的初始结构。
项目结构
Scrapy 项目的初始结构如下:
myproject/
scrapy.cfg
myproject/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
- scrapy.cfg: Scrapy 配置文件,定义项目的配置。
- myproject:
- items.py: 定义项目中需要爬取的数据结构。
- pipelines.py: 定义数据处理和存储的管道。
- settings.py: 配置项目的各种设置。
- spiders: 存放爬虫文件的目录。
创建虚拟环境(可选)
为了隔离项目的依赖,建议创建一个虚拟环境:
python -m venv myenv
source myenv/bin/activate # Windows: myenv\Scripts\activate
这样可以确保项目的依赖不会干扰其他项目。
Scrapy项目结构与基本组件 Scrapy项目的目录结构Scrapy 项目的目录结构如上文所述,具体说明如下:
- scrapy.cfg: Scrapy 配置文件,定义项目的配置。
- myproject:
- items.py: 定义项目中需要爬取的数据结构。
- pipelines.py: 定义数据处理和存储的管道。
- settings.py: 配置项目的各种设置。
- spiders: 存放爬虫文件的目录。
Scrapy 项目中有几个主要组件,它们共同工作来完成抓取和处理数据的任务:
Spider
Spider 是 Scrapy 项目中最核心的组件之一,负责定义如何抓取网站并提取所需的数据。每个 Spider 类需要继承自 scrapy.Spider
类,并定义几个关键的方法:
__init__
: 初始化方法,可以定义一些初始化参数。start_requests
: 返回初始的 Request 对象列表,这些请求用于启动抓取。parse
: 默认的回调函数,用于处理 Response 数据。通常,该方法会处理 Response 对象并返回一个或多个scrapy.Item
对象。
示例代码:
import scrapy
class MySpider(scrapy.Spider):
name = 'myspider'
allowed_domains = ['example.com']
start_urls = ['http://example.com']
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(url, callback=self.parse)
def parse(self, response):
title = response.css('title::text').get()
yield {'title': title}
Item
Item 是 Scrapy 中用于存储爬取到的数据的容器。它类似于 Python 中的字典,但具有更强的数据验证能力。
示例代码:
import scrapy
class MyItem(scrapy.Item):
title = scrapy.Field()
url = scrapy.Field()
content = scrapy.Field()
Pipeline
Pipeline 是 Scrapy 中用于处理和存储提取的数据的组件。每个 Pipeline 类需要实现几个方法:
process_item
: 对每个提取的数据进行处理。例如,清洗数据、保存到数据库等。open_spider
: 当 Spider 开始运行时调用。close_spider
: 当 Spider 结束运行时调用。
示例代码:
class MyPipeline:
def process_item(self, item, spider):
# 数据清洗
if not item['title']:
return
# 数据存储
with open('output.json', 'a') as f:
f.write(json.dumps(dict(item), ensure_ascii=False) + '\n')
return item
Middlewares
Middleware 是 Scrapy 中用于扩展功能的组件。每个 Middleware 类需要实现几个方法:
process_request
: 对每个请求进行处理。process_response
: 对每个响应进行处理。process_exception
: 对抓取过程中的异常进行处理。
示例代码:
class MyMiddleware:
def process_request(self, request, spider):
# 请求预处理
return request
def process_response(self, request, response, spider):
# 响应处理
return response
def process_exception(self, request, exception, spider):
# 异常处理
return None
Settings
Settings 是 Scrapy 中用于配置项目全局设置的组件。每个设置通常定义在 settings.py
文件中,例如:
# 爬虫延迟
DOWNLOAD_DELAY = 1
# 限制并发数
CONCURRENT_REQUESTS = 16
# 日志级别
LOG_LEVEL = 'INFO'
Scrapy项目的运行机制
Scrapy 项目的运行机制如下:
- 初始化: Scrapy 初始化时会解析
scrapy.cfg
和settings.py
文件中的配置。 - 启动请求: Spider 通过
start_requests
方法发起初始请求。 - 请求处理: Scrapy 发送请求,处理响应,并调用
parse
方法来提取数据。 - 数据处理与存储: 提取的数据通过 Pipeline 处理并保存。
- 中间件调用: 在请求和响应处理过程中,中间件会参与进来,进行额外的处理。
在 Scrapy 项目中,爬虫文件通常位于 spiders
目录下。创建一个新的爬虫,可以使用 Scrapy 的命令行工具:
cd myproject
scrapy genspider example example.com
这将创建一个名为 example
的爬虫文件,该文件位于 spiders
目录下。
示例一:简单的网页抓取
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example.com']
start_urls = ['http://example.com']
def parse(self, response):
title = response.css('title::text').get()
yield {'title': title}
示例二:递归抓取
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example.com']
start_urls = ['http://example.com']
def parse(self, response):
title = response.css('title::text').get()
yield {'title': title}
for link in response.css('a::attr(href)'):
yield response.follow(link, self.parse)
运行并测试爬虫
运行爬虫:
scrapy crawl example
Scrapy 将会输出抓取的数据。你可以使用 -o
参数将数据输出到文件:
scrapy crawl example -o output.json
这将把抓取的数据输出到 output.json
文件中。
XPath 是一种在 XML 文档中查找信息的语言,同时也适用于 HTML 文档。XPath 使用路径表达式来选取 XML 文档中的节点或节点集。以下是一些常用的 XPath 语法:
-
选取节点:
//
: 选取文档中的所有节点。//element
: 选取所有名为element
的节点。//element[@attribute="value"]
: 选取所有名为element
并具有attribute
属性且属性值为value
的节点。
-
选取属性:
@attribute
: 选取属性名为attribute
的属性值。
- 选取文本:
element/text()
: 选取名为element
的节点的所有文本内容。element/@attribute
: 选取名为element
的节点的属性attribute
的值。
示例代码:
response.xpath('//title/text()').get()
response.xpath('//a/@href').getall()
CSS选择器的基础语法与用法
CSS 选择器是另一种常用的提取数据的方法,它使用与 HTML 风格的 CSS 类似的选择器语法来定位 DOM 元素。以下是一些常用的 CSS 选择器语法:
-
选取节点:
element
: 选取所有名为element
的节点。element.className
: 选取所有名为element
且具有className
类的节点。element[attribute]
: 选取所有名为element
并具有attribute
属性的节点。element[attribute="value"]
: 选取所有名为element
并具有attribute
属性且属性值为value
的节点。
-
选取属性:
element::attr
: 选取名为element
节点的attr
属性值。
- 选取文本:
element::text()
: 选取名为element
的节点的所有文本内容。
示例代码:
response.css('title::text').get()
response.css('a::attr(href)').getall()
实例演示XPath和CSS选择器的使用
示例一:使用XPath
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example.com']
start_urls = ['http://example.com']
def parse(self, response):
title = response.xpath('//title/text()').get()
links = response.xpath('//a/@href').getall()
yield {'title': title, 'links': links}
示例二:使用CSS选择器
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example.com']
start_urls = ['http://example.com']
def parse(self, response):
title = response.css('title::text').get()
links = response.css('a::attr(href)').getall()
yield {'title': title, 'links': links}
Scrapy爬虫的数据提取与处理
数据的提取方法
Scrapy 提供了多种方法来提取数据,包括 XPath、CSS 选择器等。这些方法允许我们从 HTML 或 XML 文档中提取特定的数据。例如:
response.css('div.article::text').get()
response.xpath('//div[@class="article"]/text()').get()
数据的清洗与转换
数据提取后,通常需要对数据进行清洗和转换,以便后续处理。例如,去除空格、转换数据类型等。
示例代码:
# 清洗数据
def clean_text(text):
return text.strip()
# 转换数据类型
def convert_to_int(text):
return int(text)
item = response.css('div.price::text').get()
cleaned_item = clean_text(item)
converted_item = convert_to_int(cleaned_item)
示例:数据清洗与转换
以下是一个更完整的示例,展示了如何清洗和转换数据:
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example.com']
start_urls = ['http://example.com']
def parse(self, response):
title = response.css('title::text').get()
price = response.css('div.price::text').get()
cleaned_price = clean_text(price)
converted_price = convert_to_int(cleaned_price)
yield {'title': title, 'price': converted_price}
def clean_text(text):
return text.strip()
def convert_to_int(text):
return int(text)
实战:数据提取与处理实例
示例:从京东抓取商品信息
以下是一个从京东网站抓取商品信息的示例。
爬虫代码
import scrapy
class JdSpider(scrapy.Spider):
name = 'jd'
allowed_domains = ['jd.com']
start_urls = ['https://list.jd.com/list.html?cat=9987,653,655']
def parse(self, response):
for item in response.css('li.gl-item'):
title = item.css('div.p-name em::text').get()
price = item.css('div.p-price strong i::text').get()
cleaned_price = clean_text(price)
converted_price = convert_to_int(cleaned_price)
yield {'title': title, 'price': converted_price}
def clean_text(text):
return text.strip()
def convert_to_int(text):
return int(text)
数据清洗与转换
class JdSpider(scrapy.Spider):
# ...
def clean_text(self, text):
return text.strip()
def convert_to_int(self, text):
return int(text)
def parse(self, response):
for item in response.css('li.gl-item'):
title = item.css('div.p-name em::text').get()
price = item.css('div.p-price strong i::text').get()
cleaned_price = self.clean_text(price)
converted_price = self.convert_to_int(cleaned_price)
yield {'title': title, 'price': converted_price}
运行爬虫
scrapy crawl jd -o output.json
这将把抓取的数据输出到 output.json
文件中。
Scrapy 中间件允许在请求和响应处理过程中插入自定义处理逻辑。中间件可以修改请求和响应,或者返回自定义的响应。中间件可以分为以下几种类型:
- Request Middleware: 处理每个请求。
- Response Middleware: 处理每个响应。
- Exception Middleware: 处理请求过程中的异常。
- Downloader Middleware: 处理下载器的行为。
示例:自定义请求中间件
class CustomRequestMiddleware:
def process_request(self, request, spider):
print(f"Processing request: {request.url}")
return request
def process_response(self, request, response, spider):
print(f"Processing response: {response.url}")
return response
def process_exception(self, request, exception, spider):
print(f"Processing exception: {request.url}, {exception}")
注册中间件
# 在 settings.py 文件中注册中间件
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.CustomRequestMiddleware': 543,
}
Scrapy管道的使用
Scrapy 管道允许在数据提取后进行进一步的处理和存储。管道可以用于数据清洗、数据存储等操作。管道是通过实现几个关键方法来工作的:
process_item
: 对每个提取的数据进行处理。open_spider
: 当 Spider 开始运行时调用。close_spider
: 当 Spider 结束运行时调用。
示例:自定义管道
class CustomPipeline:
def __init__(self):
self.file = open('output.json', 'w')
def process_item(self, item, spider):
line = json.dumps(dict(item), ensure_ascii=False) + "\n"
self.file.write(line)
return item
def open_spider(self, spider):
self.file = open('output.json', 'w')
def close_spider(self, spider):
self.file.close()
注册管道
# 在 settings.py 文件中注册管道
ITEM_PIPELINES = {
'myproject.pipelines.CustomPipeline': 300,
}
Scrapy爬虫的调试与错误处理
调试 Scrapy 爬虫时,可以使用一些工具和方法来帮助定位问题。以下是一些常用的调试方法:
- 日志: Scrapy 提供了强大的日志系统,可以输出详细的调试信息。
- 断点调试: 使用 Python 的
pdb
模块在代码中设置断点,逐步执行代码。 - 异常处理: 使用中间件或管道中的异常处理逻辑来捕获和处理异常。
示例:使用日志
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example.com']
start_urls = ['http://example.com']
def parse(self, response):
try:
title = response.css('title::text').get()
links = response.css('a::attr(href)').getall()
print(f"Title: {title}")
for link in links:
print(f"Link: {link}")
except Exception as e:
self.logger.error(f"Error parsing response: {e}")
示例:使用 pdb
断点调试
import scrapy
import pdb
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example.com']
start_urls = ['http://example.com']
def parse(self, response):
pdb.set_trace()
title = response.css('title::text').get()
links = response.css('a::attr(href)').getall()
print(f"Title: {title}")
for link in links:
print(f"Link: {link}")
示例:使用异常处理
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example.com']
start_urls = ['http://example.com']
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(url, callback=self.parse, errback=self.errback_httpbin)
def parse(self, response):
title = response.css('title::text').get()
links = response.css('a::attr(href)').getall()
print(f"Title: {title}")
for link in links:
print(f"Link: {link}")
def errback_httpbin(self, failure):
self.logger.error(repr(failure))
通过这些方法,可以有效地调试和处理 Scrapy 爬虫中的问题。
共同学习,写下你的评论
评论加载中...
作者其他优质文章