网络爬虫框架-Scrapy

发布时间丨2023-02-25 16:56:47作者丨zhaomeng浏览丨0


Scrapy 是一个高级 Python Web 爬虫框架,基于 Twisted 异步网络库进行开发。它提供了一个完整的和可定制的爬虫流程,涵盖了数据抓取、处理、存储等几乎所有的操作步骤。同时,Scrapy 还支持多种数据格式(如 JSON、CSV、XML 或者原生 Python)、多个网站的并行下载以及动态网页的抓取和解析,适用于大规模高效的网络爬虫任务。

下面是 Scrapy 框架的主要组件和架构:

  1. Scrapy Engine:Scrapy 引擎是最核心的部分,负责控制整个爬取过程,包括处理请求调度及传递、反馈收集、响应处理、中间件和插件管理等等。

  2. Scheduler:Scheduler 模块负责接收 Scrapy Engine 发来的请求,并进行调度,将请求分发给 Downloader 并等待其响应。

  3. Downloader:Downloader 负责下载器组件,向远程服务器发送请求和接收响应,还可以通过钩子实现自定义输出、用户代理、Cookie 管理和传输编码等功能。

  4. Spiders:Spiders 是用户自定义的处理爬虫逻辑的模块,负责从特定的起始 URL (seed URL) 开始抓取网页,以及解析内容,生成 Item 和 Request 对象以供 Scrapy Engine 处理。

  5. Item Pipeline:Item Pipeline 模块负责处理从 Spider 中提取的 Item 对象,包括清洗、验证、去重、持久化存储等操作。Pipeline 可以按照优先级顺序进行多个处理步骤,同时也支持异步处理和插件扩展。

  6. Middleware:中间件是 Scrapy 爬虫框架的核心功能之一,它提供了多种钩子用于在各个阶段(比如请求发起前、下载响应后、Item 数据处理中等)介入处理流程,对请求和响应进行修改和过滤。用户可以编写自己的 Middleware 或者使用第三方库来完成功能扩展。

在 Scrapy 中,用户只需要编写 Spider 和 Item Pipeline 两个模块就可以构建一个简单的爬虫任务。Spider 负责定义初始 URL,抓取网页并解析数据,然后通过 Item 类将结果封装。Pipeline 模块则负责接收输入的 Item 对象,并进行处理和存储。用户也可以通过修改 Settings.py 文件来自由配置爬虫任务的各个参数(比如 User-Agent、Cookie、延迟时限、重试次数、Log 格式、数据导出格式等等)。

Scrapy 中有两种类型的中间件:下载中间件和爬虫中间件。

  1. 下载中间件

    下载中间件是在 Scrapy 发送请求到下载器之前拦截请求处理的类。它们可以通过修改 requests、响应(response)或其他项目来更改爬取的行为,如重新定向、发送 cookies、GZip 压缩 HTML 等。当 Scrapy 发送一个请求时,其会依次经过所有的下载中间件,每个下载中间件可以对请求进行一些修改或操作,最后生成请求并返回给 Scrapy Engine。

  2. 爬虫中间件

    爬虫中间件是在 Scrapy 处理 Spider 中解析 response 数据时拦截和处理 response 的类。与下载中间件不同,爬虫中间件主要用于处理解析出的 Item 以及对 Spider 解析函数的输入输出进行处理。比如可以对数据进行增、删、改等处理,也可以对 spider 进行扩展,这样能够降低 spider 的复杂度并且让不同的功能实现分离开来,同时这种方式也很容易在不麻烦其他代码之前添加新功能。

无论是下载中间件还是爬虫中间件,都需要注册,在 Scrapy 的 settings.py 文件中添加相关配置参数即可。Scrapy 默认提供了很多中间件,并且用户也可以根据自己的需求编写自定义中间件,拓展 Scrapy 的功能。

在 Scrapy 爬虫框架中,settings.py 是一个非常重要的配置文件,它可以影响爬虫行为、下载器性能、数据存储方式、日志记录等方方面面。下面是一些常见设置和参数的详细说明:

  1. USER_AGENT:用于模拟浏览器的请求头 User-Agent 字段,可以将其设置为特定的浏览器或自定义标识。

  2. DOWNLOAD_DELAY:设置爬取网页的时间间隔,以防止过多流量访问同一网络站点。可以在下载中间件使用time.sleep()实现延时。

  3. COOKIES_ENABLED:是否启动 cookies 处理功能,默认 False。

  4. ITEM_PIPELINES:设置数据保存管道,可以在其中编写数据清洗和转换的处理函数。

  5. CONCURRENT_REQUESTS:设置同时发送的请求数量,可以控制并发请求数的上限。

  6. LOG_LEVEL:设置输出的日志信息级别,包括 CRITICAL, ERROR, WARNING, INFO, DEBUG, VERBOSE,可以根据需要进行调整。

  7. FEED_URI and FEED_FORMAT:将爬取到的数据导出成 Json,csv或xml格式,在某些特殊场合中可替代原有的数据库存储功能。

  8. DOWNLOAD_TIMEOUT:设置下载请求响应超时时间,当等待指定时间后没有收到相应内容,爬虫就会返回错误信息。

  9. ROBOTSTXT_OBEY:是否遵循 robots.txt 协议,避免对数据源站点产生过大的影响。

  10. REDIRECT_ENABLED:是否开启重定向功能,默认为 True,在某些情况下可以通过关闭重定向来提高爬虫效率。

总之,Settings.py 文件说明了 Scrapy 的许多参数和配置选项。掌握这些选项将有助于获取更好的爬取结果并优化爬虫性能。要想获得更详细和完整的信息,可以参考 Scrapy 官方文档。

在 Scrapy 中,Item 对象是一个简单的容器,用于保存从爬取到的页面中解析出来的数据。对应的代码文件为 item.py

item.py 文件中,我们通常需要定义一个 Item 类,并在其中定义数据结构,包括字段名称、数据类型等等。以下是一个示例:

import scrapy

class QuoteItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    text = scrapy.Field()
    author = scrapy.Field()
    tags = scrapy.Field()

这个示例定义了一个名为 "QuoteItem" 的 Item 类,它包含三个字段:text、author 和 tags。可以按照具体需求自行添加、删除和修改定义的字段。

要注意的是,由于 Item 对象是一个字典形式的对象,所以定义字段时需要指定对应的值类型,比如上述的 text 字段的值类型就是 scrapy.Field()。

定义好 Item 类之后,就可以在 Spider 的回调函数中使用 Python 字典形式来保存在爬虫过程中提取的数据,随后再把处理完的字典数据返回给一个 scrapy.Item 实例化对象,将返回对象传递给 Scrapy 数据流,最终将数据存储到对应设置好的 pipelines 存储方式里面。

在 Scrapy 框架中,Spider 是整个爬虫流程中最为核心的部分。Spider 负责根据初始 URL 开始抓取网页,解析网页数据,并根据相应规则提取出所需数据。

spider.py 文件主要包含了 Spider 类的定义和实现,下面是一个 Spider 的示例:


import scrapy

class MySpider(scrapy.Spider):
    name = "myspider"
    start_urls = ["http://www.example.com"]
    
    def parse(self, response):
        # 解析页面,提取数据
        
        # 构造下一级爬取请求,并通过回调函数再次发送请求
        quotes = response.css("div.quote")
    
        for quote in quotes:
            item = QuoteItem()
            item["text"] = quote.css("span.text::text").get()
            item["author"] = quote.css("span small::text").get()
            item["tags"] = quote.css("div.tags a.tag::text").getall()
            yield item

    

以上示例中,我们定义了一个名为 "QuoteItem" 的 Item 类,并在 Spider 的回调函数 parse() 中使用它来保存从页面上提取的数据。通过 item[] 方式将数据存入字典实例,并 yield 出 Scrapy 框架的数据流完整副本,最后由 pipelines 的逐一处理并根据设置输出到不同位置。

这样就完成了 Item 对象的定义和使用,可以方便地管理从页面上抽取出的各种数据。

在 Scrapy 中,Pipeline 可以理解为是一种数据处理管道,用于对 Item 对象进行后续的处理和存储操作。当爬虫提取到某些数据时,会通过 Item 对象将这些数据传递给 Pipeline 进行处理。

pipelines.py 文件扮演着重要的角色,其中定义了若干个类,每个类均实现了数据处理管道的功能,主要包括以下几个部分:

  1. 数据清洗:即对爬虫爬取到的数据进行过滤、去重、格式化等操作。

  2. 数据存储:将清洗后的数据保存到指定的文件、数据库等位置中。Scrapy 框架支持多种存储方式,比如常见的 Json,CSV,以及 MySQL,Oracle,MongoDB,Redis,NOSQL 等关系型数据库或非关系型数据库。

  3. 其他处理:可以将数据传递给其他非存储组件进行处理,比如发送邮件、推送消息等。

以下是一个简单的 Pipeline 示例:

class QuotePipeline:
    def process_item(self, item, spider):
        text = item["text"]
        author = item["author"]
        tags = item["tags"]
        
        # 在这里对数据进行清洗、存储等操作
        
        return item

以上代码实现了一个名为 "QuotePipeline" 的 Pipeline,它从 Item 对象中提取出 text、author 和 tags 三个字段,并对数据进行了简单的处理。

在 Scrapy 中,可以定义多个 Pipeline 来处理数据,并可通过 ITEM_PIPELINES 设置各 Pipeline 的优先级和顺序。以常见的 Json 或 CSV 文件存储为例子,以下代码片段展示了如何使用 Pipeline 存储抓取到的数据:

以上代码实现了一个将 Item 对象转换成json格式字符串,并保存到指定文件 quotes.jl 中的 Pipeline。在 Scrapy 的 settings.py 文件中添加以下配置项即可使用该 Pipeline:

ITEM_PIPELINES = {
    'myproject.pipelines.JsonWriterPipeline': 800,
}

上述代码中的 "myproject.pipelines.JsonWriterPipeline" 分别表示类所在模块名、类名,"800" 表示这个 Pipeline 在数据处理管道中的优先级越高,数据会先经过 "JsonWriterPipeline" 后再经过其他的 Pipeline 进行处理。

综上所述,Scrapy 的 pipelines.py 文件是处理数据流程中非常重要的一部分,可以根据需要自己开发和定制多个 Pipeline 处理器来实现数据清洗、数据持久化等操作。