为了账号安全,请及时绑定邮箱和手机立即绑定

Scrapy部署管理学习:新手入门教程

概述

Scrapy是一个强大的Python爬虫框架,本文将介绍从环境搭建到数据抓取的全过程,包括Scrapy的安装、项目创建、爬虫编写以及数据提取与存储。文章还将详细讲解Scrapy项目的部署与运行,包括常见的问题与解决方案,从而帮助读者更好地理解和使用Scrapy部署管理学习。

Scrapy简介与环境搭建
Scrapy是什么

Scrapy 是一个开源的 Python 爬虫框架,用于抓取网站的数据并保存至本地。Scrapy 让你能够以快速、高效且通用的方式抓取数据。它基于 Twisted 异步网络库,可以用于多种用途,如数据挖掘、网页抓取、搜索引擎爬虫等。

Scrapy 有以下几个主要特点:

  • 异步非阻塞:使用 Twisted 异步网络库进行请求处理,提高了爬虫的执行效率。
  • 通用性强:Scrapy 的设计使它适用于多种类型的数据抓取任务。
  • 灵活性:可以方便地根据需要定制和扩展。
  • 易于使用:Scrapy 提供了清晰的 API,使得编写新的爬虫变得简单。
  • 可扩展性:易于添加新的功能或扩展。

简单的Scrapy爬虫示例

以下是一个简单的 Scrapy 爬虫示例,用于抓取示例网站的数据:

import scrapy

class ExampleSpider(scrapy.Spider):
    name = 'example'
    allowed_domains = ['example.com']
    start_urls = ['http://example.com/']

    def parse(self, response):
        for item in response.css('div.item'):
            yield {
                'title': item.css('h2::text').get(),
                'link': item.css('a::attr(href)').get(),
                'desc': item.css('p::text').get(),
            }

        next_page = response.css('a.next_page::attr(href)').get()
        if next_page:
            yield response.follow(next_page, self.parse)
安装Scrapy所需环境

Scrapy 的运行依赖于 Python 环境,以下步骤将介绍如何在本地机器上安装 Scrapy 环境。

安装Python

首先确保你的机器上安装了 Python 3.6 或更高版本。可以通过以下命令检查 Python 版本:

python --version

如果没有安装 Python,可以从 Python 官方网站下载并安装最新版本的 Python。

安装Scrapy

安装 Python 后,可以使用 pip 工具来安装 Scrapy。打开命令行(或终端),执行以下命令:

pip install scrapy

安装过程中可能会提示你需要 root 权限,这时可以使用 sudo 命令:

sudo pip install scrapy

安装完成后,可以通过以下命令检查 Scrapy 是否安装成功:

scrapy --version

成功安装后,命令行会显示 Scrapy 的版本信息:

Scrapy 2.4.1

安装虚拟环境

为了更好地管理和隔离 Scrapy 项目,推荐使用虚拟环境。以下是使用 virtualenv 创建虚拟环境的步骤:

  1. 安装 virtualenv:
pip install virtualenv
  1. 创建虚拟环境:
virtualenv my_scrapy_env

进入虚拟环境:

source my_scrapy_env/bin/activate

在激活的虚拟环境中安装 Scrapy:

pip install scrapy

安装完成后,可以检查 Scrapy 是否安装成功:

scrapy --version

输出:

Scrapy 2.4.1

创建Scrapy项目

安装完成后,可以创建一个新的 Scrapy 项目。执行以下命令:

scrapy startproject my_scrapy_project

这会创建一个新的 Scrapy 项目 my_scrapy_project。目录结构如下:

my_scrapy_project/
    scrapy.cfg
    my_scrapy_project/
        __init__.py
        items.py
        middlewares.py
        pipelines.py
        settings.py
        spiders/
            __init__.py

安装Scrapy依赖库

Scrapy 项目可能需要额外的 Python 库,如 requestslxml 等。可以使用 pip 安装这些库:

pip install requests lxml
Scrapy项目的创建

创建完 Scrapy 项目后,接下来可以编写并运行爬虫。

编写一个简单的爬虫

进入项目的 spiders 文件夹,创建一个新的 Python 文件,如 tutorial_spider.py

import scrapy

class TutorialSpider(scrapy.Spider):
    name = 'tutorial'
    allowed_domains = ['example.com']
    start_urls = ['http://example.com/']

    def parse(self, response):
        pass

运行爬虫

在项目根目录下,运行以下命令来启动爬虫:

scrapy crawl tutorial

这将运行 tutorial 爬虫并抓取 example.com 的数据(注意,这里使用的是示例域名,实际抓取中需要替换为具体的网站域名)。

保存爬取的数据

Scrapy 提供了多种数据存储方式,如保存到 JSON 文件。

settings.py 中启用 JSON 文件存储:

FEED_FORMAT = 'json'
FEED_URI = 'output.json'

运行爬虫时,数据将保存到 output.json 文件中:

scrapy crawl tutorial -o output.json

以上是 Scrapy 的环境搭建和项目创建过程。接下来将介绍 Scrapy 项目的目录结构和基本组件。

Scrapy项目结构解析
Scrapy项目的目录结构

Scrapy 项目主要由以下几个组成部分构成:

my_scrapy_project/
    scrapy.cfg
    my_scrapy_project/
        __init__.py
        items.py
        middlewares.py
        pipelines.py
        settings.py
        spiders/
            __init__.py

scrapy.cfg

Scrapy 项目配置文件,用于配置 Scrapy 的一些全局设置。如项目名称、版本号等:

[settings]
default = my_scrapy_project.settings

my_scrapy_project/

Scrapy 项目的 Python 包,包含项目的主配置文件和相关支持文件。

__init__.py

Python 包的初始化文件。

# my_scrapy_project/__init__.py

items.py

定义爬虫抓取的数据结构。以 Python 类的方式定义数据项:

import scrapy

class MyScrapyItem(scrapy.Item):
    url = scrapy.Field()
    title = scrapy.Field()
    content = scrapy.Field()

middlewares.py

定义爬虫的中间件,用于处理请求和响应。中间件可以修改请求、响应,或者对爬虫行为进行扩展。

# my_scrapy_project/middlewares.py
class MyScrapyMiddleware:
    def process_request(self, request, spider):
        # 处理请求
        return None

    def process_response(self, request, response, spider):
        # 处理响应
        return response

pipelines.py

定义数据处理管道。管道可以对抓取的数据进行清洗、转换和持久化操作。

# my_scrapy_project/pipelines.py
class MyScrapyPipeline:
    def process_item(self, item, spider):
        # 处理数据
        return item

settings.py

配置爬虫的各种设置,如并发数、下载延迟、用户代理等:

# my_scrapy_project/settings.py
BOT_NAME = 'my_scrapy_project'

SPIDER_MODULES = ['my_scrapy_project.spiders']
NEWSPIDER_MODULE = 'my_scrapy_project.spiders'

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
DOWNLOAD_DELAY = 1
CONCURRENT_REQUESTS_PER_DOMAIN = 16

spiders/

存放爬虫的 Python 文件。每个爬虫文件都是一个 Spider 类的定义。

# my_scrapy_project/spiders/tutorial_spider.py
import scrapy

class TutorialSpider(scrapy.Spider):
    name = 'tutorial'
    allowed_domains = ['example.com']
    start_urls = ['http://example.com/']

    def parse(self, response):
        # 解析数据
        for item in response.css('div.item'):
            yield {
                'title': item.css('h2::text').get(),
                'link': item.css('a::attr(href)').get(),
                'desc': item.css('p::text').get(),
            }

        # 发送新的请求
        next_page = response.css('a.next_page::attr(href)').get()
        if next_page:
            yield response.follow(next_page, self.parse)

init.py

Python 包的初始化文件。

Scrapy的基本组件介绍

Scrapy 项目由几个核心组件构成:

Spider

爬虫的主要部分,负责抓取网站数据。每个 Spider 都是一个 Python 类,继承自 scrapy.Spider。每个 Spider 类中定义了:

  • name:爬虫的唯一标识。
  • allowed_domains:允许爬取的域名。
  • start_urls:爬虫起始的 URL 列表。
  • parse:默认的回调函数,用于处理响应并生成新的请求或数据项。

示例:

import scrapy

class ExampleSpider(scrapy.Spider):
    name = 'example'
    allowed_domains = ['example.com']
    start_urls = ['http://example.com/']

    def parse(self, response):
        # 提取数据
        for item in response.css('div.item'):
            yield {
                'title': item.css('h2::text').get(),
                'link': item.css('a::attr(href)').get(),
                'desc': item.css('p::text').get(),
            }

        # 发送新的请求
        next_page = response.css('a.next_page::attr(href)').get()
        if next_page:
            yield response.follow(next_page, self.parse)

Request

请求对象,用于描述要发送的 HTTP 请求。通常由 Spider 的回调函数生成:

yield scrapy.Request(url='http://example.com/page/2', callback=self.parse_page2)

请求对象可以设置一些参数,如 urlcallbackmethodheaderscookiesmeta 等。

Response

响应对象,包含服务器对请求的响应数据。它是 parse 函数的主要参数,可以使用 Scrapy 提供的解析方法来提取数据:

response.css('div.item > h2').get()
response.xpath('//div[@class="item"]//text()').get()

Item Pipeline

数据处理管道,用于清洗、转换和存储抓取的数据。管道类定义了处理数据的方法:

class CleanTextPipeline:
    def process_item(self, item, spider):
        item['title'] = item['title'].strip()
        return item

Item

数据项,定义爬虫抓取的数据结构。通常定义在 items.py 文件中:

import scrapy

class ExampleItem(scrapy.Item):
    title = scrapy.Field()
    link = scrapy.Field()
    desc = scrapy.Field()

Spider Middleware

中间件,用于对请求和响应进行处理。中间件可以修改请求、响应,或者对爬虫行为进行扩展:

class CustomMiddleware:
    def process_request(self, request, spider):
        request.headers['User-Agent'] = 'Custom User Agent'
        return request

Item Pipeline

管道,用于清洗、转换和存储抓取的数据。管道类定义了处理数据的方法:

class CleanTextPipeline:
    def process_item(self, item, spider):
        item['title'] = item['title'].strip()
        return item

通过以上组件,Scrapy 提供了一个强大且灵活的框架来抓取和处理网站数据。下一节将详细介绍 Scrapy 爬虫的基础配置。

Scrapy爬虫基础配置
编写Scrapy爬虫的基本语法

Scrapy 爬虫的核心是继承自 scrapy.Spider 的类。以下是编写 Scrapy 爬虫的基本步骤:

定义爬虫名称

爬虫必须有一个唯一的名称,通过 name 属性定义:

class MySpider(scrapy.Spider):
    name = 'myspider'

设置允许的域名

爬虫可以限制抓取的域名,通过 allowed_domains 属性定义:

allowed_domains = ['example.com']

定义起始 URL

爬虫从指定的 URL 开始抓取,通过 start_urls 属性定义:

start_urls = ['http://example.com/']

编写解析函数

爬虫通过 parse 方法处理响应并提取数据。parse 方法接受一个参数 response,该参数是一个 Response 对象:

def parse(self, response):
    # 解析数据
    for item in response.css('div.item'):
        yield {
            'title': item.css('h2::text').get(),
            'link': item.css('a::attr(href)').get(),
            'desc': item.css('p::text').get(),
        }

    # 发送新的请求
    next_page = response.css('a.next_page::attr(href)').get()
    if next_page:
        yield response.follow(next_page, self.parse)

发送新的请求

parse 方法可以生成新的请求,使用 scrapy.Requestresponse.follow 方法:

yield scrapy.Request(url='http://example.com/page/2', callback=self.parse_page2)
yield response.follow('http://example.com/page/2', self.parse)

处理响应

解析方法解析响应数据,返回数据项或生成新的请求。解析方法的返回值可以是一个生成器,每次迭代返回一个或多个数据项:

def parse(self, response):
    yield {
        'title': response.css('h1::text').get(),
    }

跟踪嵌套的响应

Scrapy 支持处理嵌套的响应,例如处理 AJAX 请求或异步加载的数据。可以使用 response.follow 方法来跟踪这些嵌套的响应:

yield response.follow('http://example.com/page/2', self.parse)

定义访问顺序

默认情况下,Scrapy 以广度优先的方式访问页面。可以通过设置 DEPTH_PRIORITY 选项来调整访问顺序:

settings = {
    'DEPTH_PRIORITY': 1,
    'SCHEDULER_DISK_QUEUE': 'scrapy.squeues.PickleFifoDiskQueue',
    'SCHEDULER_MEMORY_QUEUE': 'scrapy.squeues.PickleFifoMemoryQueue',
}

编写其他解析方法

除了 parse 方法外,可以定义其他解析方法来处理不同类型的响应:

def parse_page2(self, response):
    return {
        'title': response.css('h1::text').get(),
    }

使用递归调用

解析方法可以递归调用,以支持复杂的抓取逻辑:

def parse(self, response):
    yield {
        'title': response.css('h1::text').get(),
    }

    next_page = response.css('a.next_page::attr(href)').get()
    if next_page:
        yield response.follow(next_page, self.parse)

异步处理

Scrapy 使用异步模型处理请求,这使得它能够高效地处理大量请求。每个解析方法都是一个协程,可以并行执行。

错误处理

Scrapy 提供了错误处理机制,可以自定义错误处理逻辑。例如,可以通过 handle_httpstatus_list 设置处理特定 HTTP 状态码的方法:

def handle_404(self, response):
    # 处理 404 错误
    pass

外部依赖

爬虫可以依赖外部库来辅助抓取数据。例如,可以使用正则表达式库 re、JSON 处理库 json 等:

import re

def parse(self, response):
    for item in response.css('div.item'):
        title = item.css('h2::text').get()
        if re.search(r'example', title):
            yield {
                'title': title,
            }

以上是编写 Scrapy 爬虫的基本语法和步骤。接下来将介绍 Scrapy 爬虫的基本配置项设置。

爬虫的基本配置项设置

Scrapy 爬虫可以通过 settings.py 文件中的配置项来设置各种行为和性能参数。以下是一些常用的配置项:

设置User-Agent

可以通过 USER_AGENT 配置项来设置请求的 User-Agent,以模拟不同的浏览器:

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'

设置下载延迟

可以通过 DOWNLOAD_DELAY 配置项设置下载之间的延迟时间,以避免对服务器造成过大压力:

DOWNLOAD_DELAY = 1

设置并发请求数量

可以通过 CONCURRENT_REQUESTS_PER_DOMAIN 配置项设置每个域名的最大并发请求数量:

CONCURRENT_REQUESTS_PER_DOMAIN = 16

设置下载超时时间

可以通过 DOWNLOAD_TIMEOUT 配置项设置下载超时时间,以防止长时间未响应的请求:

DOWNLOAD_TIMEOUT = 10

设置请求重试次数

可以通过 RETRY_TIMES 配置项设置请求失败后的重试次数:

RETRY_TIMES = 3

设置Cookie持久化

可以通过 COOKIES_ENABLED 配置项启用或禁用 Cookie 持久化:

COOKIES_ENABLED = True

设置代理服务器

可以通过 DOWNLOADER_MIDDLEWARESHTTP_PROXY 配置项设置代理服务器:

DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 1,
    'my_project.middlewares.ProxyMiddleware': 100,
}

HTTP_PROXY = 'http://my-proxy:8080'

设置请求头

可以通过 DEFAULT_REQUEST_HEADERS 配置项设置默认的请求头:

DEFAULT_REQUEST_HEADERS = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en',
}

设置日志级别

可以通过 LOG_LEVEL 配置项设置日志级别,以控制输出日志的详细程度:

LOG_LEVEL = 'INFO'

设置中间件

可以通过 DOWNLOADER_MIDDLEWARESSPIDER_MIDDLEWARES 配置项启用或禁用中间件:

DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
    'my_project.middlewares.MyUserAgentMiddleware': 400,
}

SPIDER_MIDDLEWARES = {
    'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': None,
    'my_project.middlewares.MyOffsiteMiddleware': 500,
}

设置管道

可以通过 ITEM_PIPELINES 配置项启用或禁用管道,并设置处理顺序:

ITEM_PIPELINES = {
    'my_project.pipelines.CleanTextPipeline': 300,
    'my_project.pipelines.SaveToDatabasePipeline': 800,
}

设置下载器中间件

下载器中间件主要用于处理由 Scrapy 发出的请求和接收到的响应。可以通过 DOWNLOADER_MIDDLEWARES 配置项启用或禁用中间件:

DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': 500,
    'my_project.middlewares.MyRetryMiddleware': 540,
}

设置爬虫中间件

爬虫中间件主要用于处理 Scrapy 发出的请求和接收到的响应,以及处理回调函数。可以通过 SPIDER_MIDDLEWARES 配置项启用或禁用中间件:

SPIDER_MIDDLEWARES = {
    'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': 500,
    'my_project.middlewares.MyOffsiteMiddleware': 540,
}

设置爬虫日志文件

可以通过 LOG_FILE 配置项设置日志文件路径,以将日志输出到文件:

LOG_FILE = 'scrapy.log'

以上是 Scrapy 爬虫的一些常用配置项。通过这些配置项,可以灵活地调整爬虫的行为和性能。下一节将介绍 Scrapy 数据提取与存储。

Scrapy数据提取与存储
Xpath与CSS选择器基础

在 Scrapy 中,数据提取主要依赖于 Xpath 和 CSS 选择器。这两种选择器可以帮助我们从 HTML 响应中提取所需的文本内容或 HTML 元素。

Xpath 选择器

Xpath 是一种强大的路径表达式语言,用来在 XML 文档中定位和选择节点。在 Scrapy 中,可以通过 response.xpath 方法使用 Xpath 选择器:

response.xpath('//div[@class="item"]//text()').get()

例如,假设我们有一个 HTML 响应,其中包含以下内容:

<div class="item">
    <h2>Item 1</h2>
    <p>Content 1</p>
</div>
<div class="item">
    <h2>Item 2</h2>
    <p>Content 2</p>
</div>

我们可以使用以下 Xpath 选择器来提取标题和内容:

titles = response.xpath('//div[@class="item"]/h2/text()').getall()
contents = response.xpath('//div[@class="item"]/p/text()').getall()

CSS 选择器

CSS 选择器是一种简洁的语法,用来选择 HTML 文档中的元素。在 Scrapy 中,可以通过 response.css 方法使用 CSS 选择器:

response.css('div.item h2::text').get()

例如,使用相同的 HTML 响应,我们可以使用以下 CSS 选择器来提取标题和内容:

titles = response.css('div.item h2::text').getall()
contents = response.css('div.item p::text').getall()

选择器的组合

选择器可以组合使用,以更精确地提取所需的数据。例如,可以使用 // 来选择任意层级的子节点:

items = response.xpath('//div[@class="item"]//h2//text()').getall()

也可以使用 . 来选择当前节点的子节点:

items = response.css('div.item .content::text').getall()

提取属性值

选择器不仅限于提取文本,还可以提取元素的属性值。例如,使用 Xpath 选择器:

links = response.xpath('//a/@href').getall()

使用 CSS 选择器:

links = response.css('a::attr(href)').getall()

以上是 Scrapy 中 Xpath 和 CSS 选择器的基础使用方法。接下来将介绍如何制定数据提取规则。

数据提取规则的制定

在 Scrapy 中,数据提取规则是通过解析函数来实现的。解析函数通常定义在爬虫类中,并通过 parse 方法来处理响应数据。

定义数据提取规则

解析函数可以使用 Xpath 或 CSS 选择器来提取所需的数据。例如,假设我们需要从一个包含商品列表的页面中提取商品标题和链接:

import scrapy

class ExampleSpider(scrapy.Spider):
    name = 'example'
    allowed_domains = ['example.com']
    start_urls = ['http://example.com/']

    def parse(self, response):
        for item in response.css('div.item'):
            yield {
                'title': item.css('h2::text').get(),
                'link': item.css('a::attr(href)').get(),
            }

处理嵌套的响应

在某些情况下,响应中包含嵌套的请求或数据。Scrapy 提供了 response.follow 方法来处理嵌套的响应。例如,假设我们从商品列表页面跳转到商品详情页:

def parse(self, response):
    for item in response.css('div.item'):
        yield {
            'title': item.css('h2::text').get(),
            'link': item.css('a::attr(href)').get(),
        }

    next_page = response.css('a.next_page::attr(href)').get()
    if next_page:
        yield response.follow(next_page, self.parse)

递归调用解析函数

Scrapy 支持递归调用解析函数,以处理更复杂的抓取逻辑。例如,假设我们需要从多个层级的页面中提取数据:

def parse(self, response):
    for item in response.css('div.item'):
        yield {
            'title': item.css('h2::text').get(),
            'link': item.css('a::attr(href)').get(),
        }

    for page in response.css('a.next_page::attr(href)'):
        yield response.follow(page, self.parse)

错误处理

在抓取过程中,可能会遇到各种错误,如 404 错误、超时错误等。Scrapy 提供了错误处理机制,可以通过自定义中间件或设置 handle_httpstatus_list 来处理这些错误:

def handle_404(self, response):
    # 处理 404 错误
    pass

以上是 Scrapy 中数据提取规则的制定方法。接下来将介绍如何将抓取的数据存储到不同格式。

数据存储到不同格式

Scrapy 提供了多种数据存储方式,可以将抓取的数据存储到不同的格式。以下是一些常见的存储方式:

存储到JSON文件

可以通过 FEED_FORMATFEED_URI 配置项将数据存储到 JSON 文件:

FEED_FORMAT = 'json'
FEED_URI = 'output.json'

运行爬虫时,数据将保存到 output.json 文件中:

scrapy crawl example -o output.json

存储到CSV文件

可以通过 FEED_FORMATFEED_URI 配置项将数据存储到 CSV 文件:

FEED_FORMAT = 'csv'
FEED_URI = 'output.csv'

运行爬虫时,数据将保存到 output.csv 文件中:

scrapy crawl example -o output.csv

存储到数据库

可以通过定义数据处理管道将数据存储到数据库中。例如,可以使用 SQLite 或 MySQL 数据库:

import sqlite3

class SaveToDatabasePipeline:
    def open_spider(self, spider):
        self.conn = sqlite3.connect('example.db')
        self.cursor = self.conn.cursor()
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS items (
                title TEXT,
                link TEXT
            )
        ''')
        self.conn.commit()

    def process_item(self, item, spider):
        self.cursor.execute('''
            INSERT INTO items (title, link) VALUES (?, ?)
        ''', (item['title'], item['link']))
        self.conn.commit()
        return item

    def close_spider(self, spider):
        self.conn.close()

存储到远程服务器

可以通过定义数据处理管道将数据传输到远程服务器。例如,可以使用 FTP 或 HTTP 上传文件:

import requests

class UploadToServerPipeline:
    def process_item(self, item, spider):
        # 将 item 转换为 JSON 字符串
        data = json.dumps(item)
        # 发送 POST 请求到远程服务器
        response = requests.post('http://example.com/upload', data=data)
        return item

存储到其他格式

除了上述常见格式外,Scrapy 还支持将数据存储到其他格式,如 XML、JSON Lines 等。可以通过配置 FEED_FORMATFEED_URI 来实现:

FEED_FORMAT = 'xml'
FEED_URI = 'output.xml'

运行爬虫时,数据将保存到 output.xml 文件中:

scrapy crawl example -o output.xml

以上是 Scrapy 中数据存储的几种常见方式。通过这些存储方式,可以灵活地将抓取的数据保存到不同格式中。下一节将介绍 Scrapy 的部署与运行。

Scrapy部署与运行
Scrapy项目运行方式

Scrapy 项目可以通过命令行来运行,也可以通过其他方式部署和运行。以下是 Scrapy 项目的运行方式:

本地运行

在本地机器上运行 Scrapy 项目,可以通过以下命令:

scrapy crawl <spider_name>

例如,假设我们有一个名为 example 的爬虫,可以通过以下命令运行:

scrapy crawl example

运行多个爬虫

在 Scrapy 项目中,可以包含多个爬虫。可以通过以下命令运行多个爬虫:

scrapy crawlall

或者指定多个爬虫名称:

scrapy crawl <spider_name> -a <argument>=<value>

例如,假设我们有一个名为 exampletutorial 的爬虫,可以通过以下命令运行:

scrapy crawl example
scrapy crawl tutorial

保存运行结果

运行爬虫时,可以通过命令行选项将输出结果保存到文件中。例如,将数据保存到 JSON 文件:

scrapy crawl example -o output.json

或者将日志信息保存到文件中:

scrapy crawl example -s LOG_FILE=example.log

自定义参数

可以通过 -a 参数传递自定义参数给爬虫:

scrapy crawl example -a arg=value

例如,假设我们的爬虫定义了 start_url 参数:

class ExampleSpider(scrapy.Spider):
    name = 'example'
    start_urls = ['http://example.com/']

    def __init__(self, start_url=None, *args, **kwargs):
        super(ExampleSpider, self).__init__(*args, **kwargs)
        self.start_urls = [start_url] if start_url else self.start_urls

可以通过以下命令运行爬虫并传递自定义参数:

scrapy crawl example -a start_url=http://example.com/page/2

使用脚本运行

可以通过编写 Python 脚本来运行 Scrapy 项目。例如,创建一个 run_spider.py 脚本:

import scrapy
from scrapy.crawler import CrawlerProcess

process = CrawlerProcess({
    'USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36',
    'FEED_FORMAT': 'json',
    'FEED_URI': 'output.json'
})

process.crawl(ExampleSpider)
process.start()

使用 Docker 运行

可以通过 Docker 容器来运行 Scrapy 项目。首先创建一个 Dockerfile:

FROM python:3.8-slim-buster

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

COPY . .

CMD ["scrapy", "crawl", "example"]

然后构建并运行 Docker 容器:

docker build -t my_scrapy_project .
docker run -it --rm my_scrapy_project

使用 Kubernetes 运行

可以通过 Kubernetes 来部署和运行 Scrapy 项目。首先创建一个 Kubernetes 部署文件(如 scrapy-deployment.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: scrapy-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: scrapy
  template:
    metadata:
      labels:
        app: scrapy
    spec:
      containers:
      - name: scrapy
        image: python:3.8-slim-buster
        workingDir: /app
        command: ["scrapy", "crawl", "example"]
        env:
        - name: SCRAPY_SETTINGS_MODULE
          value: my_scrapy_project.settings
        volumeMounts:
        - mountPath: /app
          name: scrapy-volume
      volumes:
      - name: scrapy-volume
        emptyDir: {}

然后部署 Kubernetes 部署:

kubectl apply -f scrapy-deployment.yaml

以上是 Scrapy 项目的运行方式。接下来将介绍 Scrapy 项目的部署流程。

Scrapy项目的部署流程

Scrapy 项目的部署流程主要包括以下步骤:

项目打包

将 Scrapy 项目打包成一个可执行的脚本或容器。可以通过以下命令创建一个可执行的脚本:

python setup.py sdist bdist_wheel

或者创建一个 Docker 镜像:

FROM python:3.8-slim-buster

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

COPY . .

CMD ["scrapy", "crawl", "example"]

配置环境

配置运行环境,包括安装 Python 和 Scrapy 环境,以及安装所需的依赖库:

pip install scrapy requests lxml

配置Scrapy设置

配置 Scrapy 的设置文件,包括 settings.py 文件中的参数设置:

BOT_NAME = 'my_scrapy_project'

SPIDER_MODULES = ['my_scrapy_project.spiders']
NEWSPIDER_MODULE = 'my_scrapy_project.spiders'

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
DOWNLOAD_DELAY = 1
CONCURRENT_REQUESTS_PER_DOMAIN = 16

配置定时任务

配置定时任务来定期运行 Scrapy 项目。例如,可以使用 cron 来定时运行 Scrapy 项目:

0 0 * * * /usr/local/bin/scrapy crawl example

或者使用 Kubernetes CronJob 来定时运行 Scrapy 项目:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: scrapy-cronjob
spec:
  schedule: "0 0 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: scrapy
            image: python:3.8-slim-buster
            workingDir: /app
            command: ["scrapy", "crawl", "example"]
            env:
            - name: SCRAPY_SETTINGS_MODULE
              value: my_scrapy_project.settings
            volumeMounts:
            - mountPath: /app
              name: scrapy-volume
          volumes:
          - name: scrapy-volume
            emptyDir: {}
          restartPolicy: Never

配置日志记录

配置日志记录,将日志输出到文件或远程服务器。例如,可以使用 LOG_FILE 配置项将日志输出到文件:

LOG_FILE = 'scrapy.log'

或者使用 LOGSTATS_INTERVAL 配置项来控制日志输出的间隔:

LOGSTATS_INTERVAL = 60

监控与报警

配置监控和报警,以监控 Scrapy 项目的运行状态并发送报警信息。例如,可以使用 Prometheus 和 Alertmanager 来监控 Scrapy 项目的运行状态:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: scrapy-monitor
spec:
  selector:
    matchLabels:
      app: scrapy
  endpoints:
  - port: web
    interval: 30s
    path: /metrics

备份与恢复

配置备份和恢复,以备份 Scrapy 项目的数据和配置文件,并在需要时恢复。例如,可以使用 rsync 来备份 Scrapy 项目的文件:

rsync -avz /path/to/scrapy /backup/scrapy

或者使用 tar 来备份 Scrapy 项目的文件:

tar -czvf /backup/scrapy.tar.gz /path/to/scrapy

以上是 Scrapy 项目的部署流程。通过这些步骤,可以将 Scrapy 项目部署到生产环境中,以定期爬取和处理数据。下一节将介绍 Scrapy 常见问题与解决方案。

Scrapy常见问题与解决方案
解析Scrapy运行中常见错误

在 Scrapy 项目的运行过程中,可能会遇到一些常见的错误。以下是一些常见错误及其解决方案:

403 Forbidden 错误

当 Scrapy 请求被目标服务器拒绝时,可能会返回 403 Forbidden 错误。这通常是因为目标服务器检测到 Scrapy 的爬虫行为,并拒绝了请求。

解决方案:

  • 修改 User-Agent:可以通过修改 USER_AGENT 设置来模拟不同的浏览器:
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
  • 使用代理:可以通过设置代理服务器来绕过服务器的检测:
DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 1,
    'my_project.middlewares.ProxyMiddleware': 100,
}

HTTP_PROXY = 'http://my-proxy:8080'

404 Not Found 错误

当 Scrapy 请求的目标页面不存在时,可能会返回 404 Not Found 错误。

解决方案:

  • 检查 URL:确保请求的 URL 是正确的。
  • 跟踪重定向:使用 response.follow 方法来跟踪重定向:
yield response.follow('http://example.com/page/2', self.parse)

网站反爬虫机制

一些网站通过 JavaScript 等方式来阻止爬虫抓取数据。

解决方案:

  • 使用 Selenium:可以通过 Selenium 模拟浏览器行为来抓取数据:
from selenium import webdriver

def parse(self, response):
    driver = webdriver.Chrome()
    driver.get(response.url)
    html = driver.page_source
    driver.quit()

    # 使用 Xpath 或 CSS 选择器解析 HTML
    items = response.xpath('//div[@class="item"]').getall()
    return items

爬虫性能问题

当 Scrapy 爬虫运行速度较慢时,可能会遇到性能问题。

解决方案:

  • 调整并发请求数量:通过设置 CONCURRENT_REQUESTS_PER_DOMAIN 来调整并发请求数量:
CONCURRENT_REQUESTS_PER_DOMAIN = 16
  • 设置下载延迟:通过设置 DOWNLOAD_DELAY 来增加下载延迟:
DOWNLOAD_DELAY = 1

数据清洗问题

当抓取的数据包含无用或错误的信息时,可能需要进行数据清洗。

解决方案:

  • 使用管道:通过定义数据处理管道来清洗抓取的数据:
class CleanTextPipeline:
    def process_item(self, item, spider):
        item['title'] = item['title'].strip()
        return item

依赖库问题

当 Scrapy 项目依赖于第三方库时,可能会遇到依赖库的问题。

解决方案:

  • 安装依赖库:确保所有依赖库都已安装:
pip install requests lxml
  • 检查依赖库版本:确保依赖库版本与项目兼容:
import requests
requests.__version__

项目配置问题

当 Scrapy 项目的配置出现问题时,可能会导致运行失败。

解决方案:

  • 检查配置文件:确保 settings.py 文件中的配置正确:
BOT_NAME = 'my_scrapy_project'
SPIDER_MODULES = ['my_project.spiders']
NEWSPIDER_MODULE = 'my_project.spiders'
  • 检查日志信息:通过查看日志文件来定位配置问题:
cat scrapy.log

Python环境问题

当 Python 环境配置出现问题时,可能会导致 Scrapy 项目无法运行。

解决方案:

  • 安装虚拟环境:使用 virtualenv 创建独立的 Python 环境:
virtualenv my_scrapy_env
source my_scrapy_env/bin/activate
pip install scrapy
  • 检查 Python 版本:确保 Python 版本与 Scrapy 兼容:
python --version

其他常见问题

  • 内存泄露:可以通过设置 CLOSESPIDER_PAGECOUNT 来限制页面抓取数量:
CLOSESPIDER_PAGECOUNT = 100
  • 数据重复:可以通过设置 DUPEFILTER_CLASS 来启用或禁用重复过滤器:
DUPEFILTER_CLASS = 'scrapy.dupefilters.BaseDupeFilter'
  • 数据编码问题:可以通过设置 ENCODING 来指定数据编码:
ENCODING = 'utf-8'

解决方案总结

  • 查看错误日志:通过查看日志文件来定位错误信息。
  • 检查配置文件:确保 settings.py 文件中的配置正确。
  • 调试代码:通过逐步调试代码来定位问题。
  • 使用 Scrapy Shell:使用 scrapy shell 工具来测试解析逻辑:
scrapy shell http://example.com

以上是 Scrapy 运行中常见的错误及其解决方案。通过这些方法,可以有效地解决 Scrapy 项目中的各种问题。接下来将介绍 Scrapy 优化与调试技巧。

Scrapy优化与调试技巧

在编写 Scrapy 爬虫时,可以通过以下方法来优化和调试爬虫:

优化请求处理

优化请求处理可以提高爬虫的执行效率。以下是一些优化请求处理的技巧:

  • 调整并发请求数量
CONCURRENT_REQUESTS_PER_DOMAIN = 16
  • 设置下载延迟
DOWNLOAD_DELAY = 1
  • 使用异步处理
import asyncio
import aiohttp

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        return results

results = asyncio.run(main())

调试解析逻辑

调试解析逻辑可以帮助我们确保数据抓取的准确性。以下是一些调试解析逻辑的技巧:

  • 使用 Scrapy Shell
scrapy shell http://example.com
  • 输出日志信息
import logging

logging.getLogger('scrapy').info('Parsing item: %s', item)

数据清洗与转换

数据清洗和转换可以确保抓取的数据符合预期格式。以下是一些数据清洗和转换的技巧:

  • 使用正则表达式
import re

clean_title = re.sub(r'[^a-zA-Z0-9]', '', title)
  • 使用数据处理管道
class CleanTextPipeline:
    def process_item(self, item, spider):
        item['title'] = item['title'].strip()
        return item

优化存储性能

优化存储性能可以提高数据存储的效率。以下是一些优化存储性能的技巧:

  • 使用数据库连接池
from sqlalchemy.pool import QueuePool

engine = create_engine('sqlite:///example.db', poolclass=QueuePool)
  • 批量存储数据
class SaveToDatabasePipeline:
    def open_spider(self, spider):
        self.conn = sqlite3.connect('example.db')
        self.cursor = self.conn.cursor()
        self.cursor.execute('''
            CREATE TABLE IF NOT EXISTS items (
                title TEXT,
                link TEXT
            )
        ''')
        self.conn.commit()

    def process_item(self, item, spider):
        self.cursor.executemany('''
            INSERT INTO items (title, link) VALUES (?, ?)
        ''', [(item['title'], item['link']) for item in items])
        self.conn.commit()
        return item

    def close_spider(self, spider):
        self.conn.close()

日志记录与监控

日志记录和监控可以帮助我们更好地了解爬虫的运行状态。以下是一些日志记录与监控的技巧:

  • 配置日志级别
LOG_LEVEL = 'INFO'
  • 输出日志信息
import logging

logging.getLogger('scrapy').info('Parsing item: %s', item)
  • 使用日志文件
LOG_FILE = 'scrapy.log'

性能测试与优化

性能测试与优化可以帮助我们提高爬虫的执行效率。以下是一些性能测试与优化的技巧:

  • 使用 Scrapy Benchmark
scrapy bench
  • 使用 Scrapy Profiler
scrapy profile -s JOBDIR=jobdir
  • 使用性能测试工具
scrapy bench --benchmarks="parse,process_item"

调试与优化总结

  • 使用 Scrapy Shell:通过 scrapy shell 工具来测试解析逻辑。
  • 输出日志信息:通过输出日志信息来跟踪爬虫的运行状态。
  • 使用 Profiler:通过 Profiler 工具来分析爬虫的性能瓶颈。
  • 性能测试:通过性能测试工具来评估爬虫的执行效率。

以上是 Scrapy 优化与调试的一些技巧。通过这些方法,可以有效地优化和调试 Scrapy 项目。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消