Scrapy基础 --- #1

这是 DataWhale 新闻推荐系统实战的 Task3,主要任务有:

  • 爬虫
  • 构建画像
  • 物料入库

本篇博客主要参考Fun-rec的文档,在这里

本篇博客主要内容是 scrapy 的介绍,以及项目中新闻物料的爬取和保存。

Scrapy

说起爬虫框架,那 scrapy 必是当之无愧的一哥了。虽然我还没用 scrapy 写过爬虫,但也是仰慕已久。犹记当初刚学了一点 python,尝试的第一个项目就是写爬虫,那时候的爬虫还是用 requests 库来做的。那时候第一次接触这么花里胡哨丰富多彩的东西,心理甚是激动,熬夜学习 html、css、xpath、Beautiful Soup 等东西(虽然现在已经忘得差不多了),但是在学得半吊子的情况下,用着这几个简陋的工具,也是爬到了不少好东西(嘿嘿🤭,具体是什么就不说了)。学完爬虫后感觉自己会了不少东西,网上这么多东西都尽逃不出我手,一时之间得意的很。后来慢慢的兴趣漂移了,开始晚一些其他的东西了,直到今天,漂移到了推荐系统上,不知道以后还要飘到哪,嗨~🤨。

先看看 scrapy 的自我介绍:

Scrapy is a fast high-level web crawling and web scraping framework, used to crawl websites and extract structured data from their pages. It can be used for a wide range of purposes, from data mining to monitoring and automated testing.

里面提到了两个很相似的词:

  • web crawling:爬取和存储一个站点上的所有数据
  • web scraping:抽取一个站点上的指定内容的数据,例如淘宝网上的产品数据
    可以参看下面图,来自这里

从上面的介绍,我们知道了 scrapy 有两个主要的功能:网页抓取和内容抽取。

官网的一个例子

看一下这段代码:

import scrapy


class QuotesSpider(scrapy.Spider):
    name = 'quotes'
    start_urls = [
        'http://quotes.toscrape.com/tag/humor/',
    ]

    def parse(self, response):
        for quote in response.css('div.quote'):
            yield {
                'author': quote.xpath('span/small/text()').get(),
                'text': quote.css('span.text::text').get(),
            }

        next_page = response.css('li.next a::attr("href")').get()
        if next_page is not None:
            yield response.follow(next_page, self.parse)

我们把它保存在 quotes_spider.py 这个文件里,然后在文件所在的目录下执行:scrapy runspider quotes_spider.py -o quotes.jl。看一下回车后输出的内容:

可以看到,scrapy 先是启动了一些中间件(middlewares),然后找到了 Spider(即 quotes_spider.py 中继承了 scrapy.Spider 的类),然后打开了爬虫(Spider opened)。接着就是爬取网页(Crawled)(Q1.怎么知道爬取哪个网页的呢?),抓取到一个网页后就会按照代码制定的规则解析其中的内容(Scraped)。一页的内容处理完后就抓取下一页(Q2.下一页是如何获得的呢?),然后继续抽取数据,知道没有下一页了,最后关闭爬虫(Closing spider),再把内容保存到输出文件(Stored)。整理以下流程:

  1. 启动一些中间件;
  2. 启动爬虫;
  3. 爬取网页;
    1.按照规则抽取数据;
    2.是否有下一页,有则返回3;
  4. 关闭爬虫;
  5. 保存数据。

在梳理过程的时候我们有两个疑问:

  1. 怎么知道爬取哪个网页的呢?
  2. 下一页是如何获得的呢?

我们在下一节寻找答案。

Scrapy 架构

先看一下官网给出的架构图

官网给出的 scrapy 工作流程:

  1. Engine 从 Spider 那拿到初始的爬取请求
  2. Engine 在 Scheduler 安排手中拿到的请求,并请求下一个要爬取的请求;
  3. Scheduler 将下一个要爬取的请求返回给 Engine;
  4. Engine 通过下载中间件(见 process_request() )将请求发送给 Downloader;
  5. 完成下载后,Downloader 生成一个响应,通过下载中间件(见 process_response() )将其发送给 Engine;
  6. Engine 接收来自 Downloader 的响应,并通过 Spider 中间件(见 process_spider_input() )将其发送给 Spider,让 Spider 来处理响应;
  7. Spider 处理响应并通过 Spider 中间件把抽取到的项目和下一个要跟踪的请求传给 Engine;
  8. Engine 收到项目后,将其发送到 Item Pipelines,然后将处理过的请求发送给 Scheduler,并请求下一个要爬取的请求(如果有的话);
  9. 以上过程重复直至 Scheduler 中没有新的请求。

从上述流程我们可以找到未解答的两个问题:

  1. 怎么知道爬取哪个网页的呢?

从 spider 那里拿到初始的请求。回到那个例子来看,start_urls 指定了我们定义的那个爬虫从哪里开始爬取。

  1. 下一页是如何获得的呢?

也是来自 spider。回到那个例子,下一个要爬取的请求是通过 next_page = response.css('li.next a::attr("href")').get() 得到的,然后通过 yield response.follow(next_page, self.parse) 将下一个请求发送给了 Engine。

通过架构图和工作流程,我们也看出来了 scrapy 中有一些重要的角色,比如处于 c 位的 Engine 和 Scheduler,当然每一个成功的系统都离不开每一颗螺丝的付出。

Components

  1. Engine
    Engine 负责控制数据(如请求、抽取的内容等)在 scrapy 组件间的流动,并且当一些特定的动作出现后触发相应的事件。

  2. Scheduler
    Scheduler 从 Engine 接收请求,并将它们放入队列中,等 Engine 请求它们的时候将其发送给 Engine;

  3. Downloader
    Downloader 负责把网页从被爬取的站点抓取下来,然后发送给 Engine;

  4. Spiders
    Spider 是由用户自定义的爬虫类(需要继承 scrapy.Spider),负责解析响应,从中抽取项目,或者需要额外跟踪的请求(例如下一页);

  5. Item Pipeline
    Item Pipeline 负责处理被 Spiders 抽取的项目。Item Pipelines 典型的工作内容包括清洗、验证及持久化保存。

  6. Downloader middlewares
    Downloader middlewares 是位于 Engine 和 Scheduler 间的狗子钩子(hook),当有请求从 Engine 传递给 Downloader 时,Downloader middlewares 就会先处理这些请求,同理,当响应被传递给 Engine 时也会被其处理。

  7. Spider middlewares
    Spider middlewares 是位于 Engine 和 Spiders 之间的钩子,能够处理 spider 的输入(响应)和输出(items 和请求)。

  8. Event-driven networking
    Scrapy 是构建在 Twisted 的基础上的,Twisted 是一个流行的事件驱动的网络框架。

posted @ 2021-12-26 12:23  Milkha  阅读(42)  评论(0)    收藏  举报