admin 管理员组文章数量: 887021
Scrapy架构
Scrapy 是一个用于 Python 的高级 Web 爬取框架,它被设计用来爬取网站并从页面中提取结构化的数据。Scrapy 的核心是一个异步处理引擎,基于 Twisted 这个事件驱动网络引擎构建而成。
主要组件
-
Scrapy Engine(Scrapy 引擎):
- 负责处理所有的数据流,发送请求、返回响应以及调度数据到各个组件。
-
Scheduler(调度器):
- 排队待处理的请求,并根据优先级将它们发送给引擎。
-
Downloader(下载器):
- 负责处理所有实际的 HTTP 请求和响应。
-
Spider(爬虫):
- 解析响应数据,提取数据(抓取项目),以及生成新的请求。
-
Item Pipeline(项目管道):
- 处理爬取的数据,例如清洗、验证、存储等。
-
Middleware(中间件):
- 处理 Scrapy 组件之间的钩子,允许用户修改或扩展 Scrapy 的行为。
创建项目和爬虫
创建项目
- 打开命令行工具。
- 使用
scrapy startproject <project_name>
命令创建一个新的 Scrapy 项目。 - 进入项目目录:
cd <project_name>
。
创建爬虫
- 在项目目录下运行
scrapy genspider <name> <domain>
命令来创建一个爬虫。<name>
是爬虫的名字。<domain>
是你想要爬取的网站域名。
- 编辑
spiders/<name>.py
文件来定义爬虫的行为。 - 定义
start_requests
方法以启动爬虫。 - 实现
parse
方法来解析响应并提取数据。
数据管道和中间件
数据管道 (Item Pipeline)
数据管道是用来处理爬虫提取的 Item 对象的一系列组件。你可以定义多个管道来处理数据,比如清理数据、验证数据、存储数据等。
- 在
settings.py
中启用管道。 - 定义一个类继承自
scrapy.pipelines.ItemPipeline
。 - 实现
process_item
方法,该方法接收 Item 和 Spider 并返回 Item 或抛出异常。
中间件 (Middleware)
中间件允许用户拦截 HTTP 请求和响应,可以用来处理各种需求,如添加 HTTP 头、处理 cookies、设置代理等。
-
Downloader Middlewares:
- 这些中间件位于下载器与 Scrapy 引擎之间,可以修改请求和响应。
- 需要在
settings.py
中配置中间件列表DOWNLOADER_MIDDLEWARES
。
-
Spider Middlewares:
- 这些中间件位于爬虫与 Scrapy 引擎之间,可以过滤响应和提取的 Item。
- 配置在
settings.py
中通过SPIDER_MIDDLEWARES
字典。
这些是 Scrapy 框架的核心概念和使用方法。你可以根据具体需求进行定制和扩展。如果你需要更详细的代码示例或者有其他具体问题,请告诉我!
下面我将展示如何创建一个简单的 Scrapy 项目,并编写一个爬虫来抓取一个网站上的数据。同时,我会介绍如何定义数据管道和中间件。
首先,确保你已经安装了 Scrapy。如果还没有安装,可以通过 pip 安装 Scrapy:
pip install scrapy
然后,按照以下步骤创建项目和爬虫:
创建 Scrapy 项目
打开终端或命令提示符,执行以下命令来创建一个新的 Scrapy 项目:
scrapy startproject myproject
cd myproject
这将在当前目录下创建一个名为 myproject
的文件夹,其中包含了项目的基本结构。
创建爬虫
接下来,我们将创建一个爬虫来抓取一个假设的博客站点 example
上的文章标题和链接。
在项目目录中,执行以下命令创建爬虫:
scrapy genspider example example
这将创建一个名为 example.py
的文件在 myproject/spiders
目录下。打开这个文件并编辑它:
# myproject/spiders/example.py
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example']
start_urls = ['http://example']
def parse(self, response):
# 提取文章标题和链接
for article in response.css('div.article'):
yield {
'title': article.css('h2.title::text').get(),
'link': article.css('a::attr(href)').get(),
}
# 提取下一页的链接
next_page = response.css('div.pagination a.next::attr(href)').get()
if next_page is not None:
yield response.follow(next_page, self.parse)
定义数据管道
为了保存爬取到的数据,我们需要定义一个数据管道。在 myproject/pipelines.py
文件中定义一个简单的数据管道:
# myproject/pipelines.py
import json
class MyprojectPipeline:
def open_spider(self, spider):
self.file = open('items.json', 'w')
def close_spider(self, spider):
self.file.close()
def process_item(self, item, spider):
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
return item
接下来,在 settings.py
文件中激活这个管道:
# myproject/settings.py
ITEM_PIPELINES = {
'myproject.pipelines.MyprojectPipeline': 300,
}
定义中间件
我们可以定义一个中间件来处理请求头。在 myproject/middlewares.py
文件中定义一个简单的中间件:
# myproject/middlewares.py
class CustomUserAgentMiddleware:
def process_request(self, request, spider):
request.headers['User-Agent'] = 'MyCustomUserAgent'
然后在 settings.py
中激活这个中间件:
# myproject/settings.py
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.CustomUserAgentMiddleware': 543,
}
运行爬虫
现在,我们可以通过以下命令来运行爬虫:
scrapy crawl example
这将开始爬取 example
网站,并将数据保存到 items.json
文件中。
以上就是创建一个简单的 Scrapy 项目、爬虫、数据管道和中间件的基本过程。你可以根据需要对这些代码进行修改和扩展。如果有任何疑问或需要进一步的帮助,请随时告诉我!
让我们继续扩展代码,以便更好地理解 Scrapy 的工作原理。我们将添加错误处理、日志记录、更复杂的管道功能以及更多的中间件功能。
错误处理
在爬虫中,我们应该处理可能发生的错误,比如网页找不到的情况。我们可以为 parse
方法添加异常处理逻辑:
# myproject/spiders/example.py
import scrapy
class ExampleSpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example']
start_urls = ['http://example']
def parse(self, response):
if response.status != 200:
self.logger.error(f"Failed to load page {response.url}, status code: {response.status}")
return
# 提取文章标题和链接
for article in response.css('div.article'):
yield {
'title': article.css('h2.title::text').get(),
'link': article.css('a::attr(href)').get(),
}
# 提取下一页的链接
next_page = response.css('div.pagination a.next::attr(href)').get()
if next_page is not None:
yield response.follow(next_page, self.parse)
更复杂的管道
让我们在管道中增加一些额外的功能,比如检查是否有重复的项,并且添加一些基本的日志记录。
# myproject/pipelines.py
import json
import logging
class MyprojectPipeline:
def __init__(self):
self.seen_urls = set()
self.file = None
def open_spider(self, spider):
self.file = open('items.json', 'w')
def close_spider(self, spider):
self.file.close()
def process_item(self, item, spider):
url = item.get('link')
if url and url not in self.seen_urls:
self.seen_urls.add(url)
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
logging.info(f"Processed item: {item}")
return item
else:
logging.warning(f"Duplicated link found: {url}")
return item
更多的中间件功能
我们可以在中间件中添加一些额外的功能,比如随机选择 User-Agent 或者处理重试机制。
# myproject/middlewares.py
from scrapy import signals
import random
class CustomUserAgentMiddleware:
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:90.0) Gecko/20100101 Firefox/90.0",
]
def process_request(self, request, spider):
request.headers['User-Agent'] = random.choice(self.USER_AGENTS)
def process_response(self, request, response, spider):
if response.status == 404:
self.logger.error(f"Received 404 for URL: {request.url}")
# 可以在此处实现重试机制
return request
return response
@classmethod
def from_crawler(cls, crawler):
# This method is used by Scrapy to create your spiders.
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)
运行爬虫
最后,再次运行爬虫以测试新添加的功能:
scrapy crawl example
这些更改增加了错误处理、日志记录、去重功能和更复杂的中间件功能。这应该能够帮助你更好地理解和应用 Scrapy 的各个组件。如果你还有其他具体的需求或者想了解更多的细节,请告诉我!
版权声明:本文标题:Python爬虫技术 第25节 爬虫框架Scrapy 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1726436472h960318.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论