Scrapy学习涵盖了从安装到项目部署的全过程,介绍了Scrapy的安装方法、项目结构和基本概念。文章还详细讲解了如何编写和使用Spider,以及高级技巧如中间件的定制和异常处理。
Scrapy简介与安装 Scrapy是什么Scrapy 是一个用于抓取网站数据并提取结构化信息的 Python 库。它主要用于构建 Web 爬虫,能够快速地抓取数据并解析数据。Scrapy 通常用于数据挖掘、信息处理和存储,以及从网站收集数据等任务。Scrapy 的设计目标是将网络爬虫的编写变得简单且可扩展。
Scrapy的特点与优势Scrapy 有以下几个显著的特点和优势:
- 异步爬取:Scrapy 使用异步 I/O 实现了高效的爬取速度,可以在短时间内处理大量请求。
- 强大的选择机制:Scrapy 提供了 XPath 和 CSS 选择器来解析 HTML 和 XML 代码,使得数据提取变得容易。
- 灵活的数据提取:Scrapy 通过定义 Item 和自定义提取规则来方便地获取所需数据。
- 可扩展性:Scrapy 的模块化设计使得扩展和自定义变得更加简单,可以方便地添加中间件、管道等组件。
- 稳健性:Scrapy 支持处理大量数据和高并发请求,能够避免被目标网站检测到并被封禁。
Scrapy 可以通过 pip
包管理工具进行安装。以下是具体的安装步骤:
- 打开命令行工具(如 Windows 的命令提示符、macOS 或 Linux 的终端)。
- 使用以下命令安装 Scrapy:
pip install scrapy
此命令会安装 Scrapy 以及其依赖库。
创建第一个Scrapy项目创建一个新的 Scrapy 项目需要执行以下步骤:
- 打开命令行工具。
- 转到你希望创建项目的工作目录。
- 执行以下命令来创建一个新的 Scrapy 项目(假设项目名为
myproject
):
scrapy startproject myproject
该项目结构将如下:
myproject/
scrapy.cfg # 项目配置文件
myproject/
__init__.py # 空白的 Python 包初始化文件
items.py # 定义项目中所有 Item 类的文件
middlewares.py # 定义中间件类的文件
pipelines.py # 定义 Pipeline 类的文件
settings.py # 项目的设置文件
spiders/ # 存放所有 Spider 文件的目录
__init__.py # 空白的 Python 包初始化文件
- 在
spiders
目录下创建一个新的 Spider 类文件,例如my_spider.py
,并在其中定义一个简单的 Spider:
# myproject/spiders/my_spider.py
import scrapy
class MySpider(scrapy.Spider):
name = 'myspider' # Spider 名称
start_urls = [
'http://example.com/',
]
def parse(self, response):
# 解析响应内容
self.log('Visited %s' % response.url)
- 运行新创建的 Spider:
cd myproject
scrapy crawl myspider
这将启动 Scrapy 并运行 myspider
Spider,开始抓取 start_urls
中定义的 URL。
Scrapy 项目的目录结构如下:
scrapy.cfg
:项目配置文件,用于设置 Scrapy 版本等信息。myproject
:项目的主目录,包括以下文件和文件夹:__init__.py
:空白的 Python 包初始化文件。items.py
:用于定义所有要抓取的数据结构。pipelines.py
:实现数据处理和保存的 Pipeline。settings.py
:设置 Scrapy 的全局配置。spiders/
:存放所有 Spider 文件的目录。middlewares.py
:用于定义中间件类的文件。
Item
Item 是 Scrapy 中用来存储抓取数据的容器。它类似于 Python 字典,但更加严格,确保数据的一致性和规范性。在 items.py
文件中定义 Item 类:
# myproject/items.py
import scrapy
class MyprojectItem(scrapy.Item):
title = scrapy.Field()
url = scrapy.Field()
content = scrapy.Field()
Item 类中定义了抓取数据的字段,例如 title
、url
和 content
。这些字段是 scrapy.Field
类型,用于存储数据。
Spider
Spider 是 Scrapy 中用于定义爬虫逻辑的类。一个 Spider 可以包含多个方法,如 start_requests()
和 parse()
。Spider 的主要功能是定义要抓取的 URL 和数据提取规则。例如:
# myproject/spiders/example_spider.py
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
start_urls = ['http://example.com']
def parse(self, response):
for item in response.css('div.item'):
yield {
'title': item.css('a::text').get(),
'url': item.css('a::attr(href)').get(),
}
在这个例子中,parse
方法使用 CSS 选择器提取数据。
Pipeline
Pipeline 是 Scrapy 中用于后处理抓取数据的机制。它负责对抓取的数据进行清洗、验证、持久化等操作。在 pipelines.py
文件中定义 Pipeline 类:
# myproject/pipelines.py
class MyprojectPipeline:
def process_item(self, item, spider):
# 对 item 数据进行处理
return item
process_item()
方法用于处理传入的 Item 数据。
解释Scrapy的工作流程
Scrapy 的工作流程可以概括为以下几个步骤:
- 启动:通过执行
scrapy crawl <spider_name>
命令启动一个 Spider。 - 发送请求:Spider 中的
start_requests()
方法定义了初始 URL,然后 Scrapy 使用这些 URL 发送请求。 - 接收响应:Scrapy 发送请求后,会接收到响应。
- 解析数据:解析器(通常是
parse()
方法)解析响应内容,并从中提取数据。 - 生成 Item:解析方法生成并返回
Item
类的实例。 - 数据处理:Item 通过 Pipeline 进行处理,数据可以被清洗、验证或保存。
- 存储数据:处理过后,数据可以被保存到数据库或其他存储介质。
以下是一个简单的 Spider 示例,用于抓取网站上的文章标题和链接:
# myproject/spiders/example_spider.py
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
start_urls = ['http://example.com']
def parse(self, response):
for article in response.css('div.post'):
title = article.css('h2 a::text').get()
url = article.css('h2 a::attr(href)').get()
yield {
'title': title,
'url': url,
}
此 Spider 定义了一个 parse()
方法,该方法使用 CSS 选择器提取文章标题和链接,并生成 Item
。
Spider 的基本结构包括以下几个部分:
- name:Spider 的名称,用于唯一标识 Spider。
- start_urls:包含初始 URL 的列表,用于启动爬取过程。
- parse 方法:解析响应内容并从中提取数据的方法。
# myproject/spiders/example_spider.py
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
start_urls = ['http://example.com']
def parse(self, response):
# 解析响应内容并提取数据
for article in response.css('div.post'):
title = article.css('h2 a::text').get()
url = article.css('h2 a::attr(href)').get()
yield {
'title': title,
'url': url,
}
解析HTML页面
Scrapy 提供了两种主要的方法来解析 HTML 代码:XPath 和 CSS。
XPath
XPath 是一种在 XML 文档中查找节点的语言。Scrapy 使用 XPath 语法来定位和提取数据:
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
start_urls = ['http://example.com']
def parse(self, response):
# 使用 XPath 提取节点
for article in response.xpath('//div[@class="post"]'):
title = article.xpath('.//h2/a/text()').get()
url = article.xpath('.//h2/a/@href').get()
yield {
'title': title,
'url': url,
}
CSS
CSS 选择器在 Scrapy 中用于选择 HTML 元素。CSS 选择器通常比 XPath 更具可读性,并且适用于简单的选择任务:
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
start_urls = ['http://example.com']
def parse(self, response):
# 使用 CSS 选择器提取节点
for article in response.css('div.post'):
title = article.css('h2 a::text').get()
url = article.css('h2 a::attr(href)').get()
yield {
'title': title,
'url': url,
}
提取数据与追加请求
提取数据
Scrapy 提供了 extract()
和 get()
方法来提取数据。extract()
方法返回一个列表,而 get()
方法返回单个值。
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
start_urls = ['http://example.com']
def parse(self, response):
titles = response.css('h1.title').extract()
for title in titles:
yield {'title': title}
追加请求
可以通过生成新的 Request
对象来追加请求。追加请求通常用于处理分页、递归调用等情况。
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
start_urls = ['http://example.com']
def parse(self, response):
next_page = response.css('a.next::attr(href)').get()
if next_page is not None:
yield response.follow(next_page, callback=self.parse)
for item in response.css('div.post'):
title = item.css('h2 a::text').get()
url = item.css('h2 a::attr(href)').get()
yield {
'title': title,
'url': url,
}
在这个例子中,parse()
方法通过 response.follow()
方法生成新的请求,并传递回调函数 parse
。
Scrapy 中间件是一系列钩子函数,允许你拦截和修改请求和响应。中间件用于扩展 Scrapy 功能,例如处理登录、添加头信息等。
定义中间件
中间件的定义通常在 settings.py
文件中:
# myproject/settings.py
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.MyCustomMiddleware': 543,
}
中间件类定义在 middlewares.py
文件中:
# myproject/middlewares.py
from scrapy import signals
class MyCustomMiddleware:
@classmethod
def from_crawler(cls, crawler):
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
return s
def spider_opened(self, spider):
spider.logger.info('Spider opened: %s' % spider.name)
自定义中间件
自定义中间件可能会在请求和响应中进行处理:
# myproject/middlewares.py
from scrapy import signals
class MyCustomMiddleware:
def process_request(self, request, spider):
# 在请求发送之前处理
spider.logger.info('Request processed: %s' % request)
return None
def process_response(self, request, response, spider):
# 在响应接收后处理
spider.logger.info('Response processed: %s' % response)
return response
设置并发请求限制与延时
Scrapy 允许你设置并发请求的数量和延时,以防止被目标网站检测到。这些设置通常在 settings.py
文件中进行:
# myproject/settings.py
CONCURRENT_REQUESTS = 16 # 并发请求限制
DOWNLOAD_DELAY = 1 # 下载延迟,单位:秒
并发请求限制
CONCURRENT_REQUESTS
设置了 Scrapy 同时进行的最大请求数量。
下载延迟
DOWNLOAD_DELAY
设置了下载每个请求之间的最小延迟,以秒为单位。
自定义下载器
自定义下载器可以让你更灵活地处理请求和响应。下载器定义在 settings.py
文件中:
# myproject/settings.py
DOWNLOADER = 'myproject.custom_downloader.CustomDownloader'
下载器类定义在 custom_downloader.py
文件中:
# myproject/custom_downloader.py
from scrapy.core.downloader.handlers.http import HTTPDownloadHandler
class CustomDownloader(HTTPDownloadHandler):
def download_request(self, request, spider):
# 自定义下载逻辑
return super().download_request(request, spider)
处理异常
Scrapy 提供了 errback
方法来处理异常请求:
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
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 errback_httpbin(self, failure):
# 处理异常
self.logger.error(repr(failure))
return failure
errback_httpbin
方法会处理任何请求失败的情况。
部署 Scrapy 项目时,需要注意以下几点:
- 性能优化:确保项目的性能优化,例如设置合适的并发请求数量和下载延迟。
- 错误处理:确保项目有良好的错误处理机制,以应对各种异常情况。
- 日志记录:使用日志记录功能,以便于维护和调试。
- 资源使用:确保项目在生产环境中的资源使用合理,避免占用过多系统资源。
设置并发请求限制与延时
在 settings.py
文件中设置并发请求限制和下载延迟:
# myproject/settings.py
CONCURRENT_REQUESTS = 16 # 并发请求限制
DOWNLOAD_DELAY = 1 # 下载延迟,单位:秒
错误处理
确保项目有良好的错误处理机制,例如通过 try-except
块来捕获和处理异常:
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
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 errback_httpbin(self, failure):
# 处理异常
self.logger.error(repr(failure))
return failure
日志记录
使用日志记录功能,以便于维护和调试:
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
start_urls = ['http://example.com']
def parse(self, response):
self.log('Visited %s' % response.url)
资源使用
确保项目在生产环境中的资源使用合理,避免占用过多系统资源。例如,通过限制并发请求和下载延迟来减少资源消耗。
使用Scrapy Cloud或Docker部署Scrapy项目Scrapy Cloud
Scrapy Cloud 是一个基于 Scrapy 的云爬虫服务,可以方便地部署和管理 Scrapy 项目:
-
安装 Scrapy Cloud CLI:
pip install scrapy-cloud
-
配置 Scrapy Cloud:
scrapy_cloud configure
- 部署项目:
scrapy_cloud deploy
Docker
使用 Docker 部署 Scrapy 项目可以确保环境的一致性和可移植性:
-
创建 Dockerfile:
FROM python:3.8-slim WORKDIR /app COPY requirements.txt requirements.txt RUN pip install -r requirements.txt COPY . . CMD ["scrapy", "crawl", "myspider"]
-
构建 Docker 镜像:
docker build -t myproject .
- 运行 Docker 容器:
docker run -it myproject
Scrapy 本身没有内置的监控工具,但可以使用日志和第三方监控工具来监控项目运行状态:
-
日志监控:
Scrapy 会生成详细的日志信息,可以通过日志文件来监控项目的运行情况。 - 第三方监控工具:
使用如 Prometheus、Grafana 等工具来监控 Scrapy 项目的运行状态和性能。
- 网站被封禁:增加下载延迟和减少并发请求,确保遵守目标网站的使用政策。
- 爬虫速度慢:优化爬虫逻辑,减少不必要的请求,提高解析效率。
- 数据提取不准确:检查选择器和解析逻辑,确保选择器正确匹配目标数据。
- 内存泄漏:确保及时清理不再使用的对象,避免内存泄漏。
- Scrapy 官方文档:详细介绍了 Scrapy 的安装、配置和使用方法。
- Scrapy 中文社区:提供 Scrapy 的教程、案例和问答。
- 慕课网:提供了 Scrapy 的在线课程,适合不同水平的学习者。
- GitHub:Scrapy 项目源代码和相关示例在 GitHub 上公开,可以参考学习。
- Scrapy 中文社区:Scrapy 中文社区是 Scrapy 在中国的官方交流平台,提供了丰富的资源和讨论环境。
- GitHub:GitHub 上有大量的 Scrapy 开源项目和示例代码,可以参考学习。
- Stack Overflow:Stack Overflow 是一个问答社区,你可以在这里找到 Scrapy 相关的问题和解答。
共同学习,写下你的评论
评论加载中...
作者其他优质文章