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

Scrapy爬虫框架学习:从入门到初级实战教程

标签:
Python 爬虫
概述

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

在安装 Scrapy 之前,确保你已经安装了 Python 3.x。Scrapy 支持 Python 3.6 及以上版本。以下是安装 Scrapy 的步骤:

  1. 打开终端或命令提示符。
  2. 使用 pip 命令安装 Scrapy:

    pip install scrapy
  3. 如果安装成功,可以使用 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的主要组件介绍

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 项目的运行机制如下:

  1. 初始化: Scrapy 初始化时会解析 scrapy.cfgsettings.py 文件中的配置。
  2. 启动请求: Spider 通过 start_requests 方法发起初始请求。
  3. 请求处理: Scrapy 发送请求,处理响应,并调用 parse 方法来提取数据。
  4. 数据处理与存储: 提取的数据通过 Pipeline 处理并保存。
  5. 中间件调用: 在请求和响应处理过程中,中间件会参与进来,进行额外的处理。
创建第一个Scrapy爬虫
创建Scrapy项目与爬虫

在 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 文件中。

Scrapy爬虫的XPath和CSS选择器
XPath的基础语法与用法

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爬虫的扩展与进阶
Scrapy中间件的使用

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 爬虫中的问题。

点击查看更多内容
TA 点赞

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

评论

作者其他优质文章

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

100积分直接送

付费专栏免费学

大额优惠券免费领

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

举报

0/150
提交
取消