初识scrapy爬虫框架

1 概述

在具体的学习scrapy之前,我们先对scrapy的架构做一个简单的了解,之后所有的内容都是基于此架构实现的,在初学阶段只需要简单的了解即可,之后的学习中,你会对此架构有更深的理解。 下面是scrapy官网给出的最新的架构图示。

1.1 基本组件

  • 引擎(Engine) 引擎负责控制数据流在系统中所有组件中流动,并在相应动作发生时触发事件。 详细内容查看下面的数据流(Data Flow)部分。
  • 调度器(Scheduler) 调度器从引擎接受request并将他们入队,以便之后引擎请求他们时提供给引擎。
  • 下载器(Downloader) 下载器负责获取页面数据并提供给引擎,而后提供给spider。
  • 爬虫(Spiders) Spider是Scrapy用户编写用于分析response并提取item(即获取到的item)或额外跟进的URL的类。 每个spider负责处理一个特定(或一些)网站。
  • 管道(Item Pipeline) Item Pipeline负责处理被spider提取出来的item。典型的处理有清理、验证及持久化(例如存取到数据库中)。
  • 下载器中间件(Downloader middlewares) 下载器中间件是在引擎及下载器之间的特定钩子(specific hook),处理Downloader传递给引擎的response。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。
  • Spider中间件(Spider middlewares) Spider中间件是在引擎及Spider之间的特定钩子(specific hook),处理spider的输入(response)和输出(items及requests)。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。

1.2 数据流向

Scrapy的数据流由执行引擎(Engine)控制,其基本过程如下:

  1. 引擎从Spider中获取到初始Requests。
  2. 引擎将该Requests放入调度器,并请求下一个要爬取的Requests。
  3. 调度器返回下一个要爬取的Requests给引擎
  4. 引擎将Requests通过下载器中间件转发给下载器(Downloader)。
  5. 一旦页面下载完毕,下载器生成一个该页面的Response,并将其通过下载中间件(返回(response)方向)发送给引擎。
  6. 引擎从下载器中接收到Response并通过Spider中间件(输入方向)发送给Spider处理。
  7. Spider处理Response并返回爬取到的Item及(跟进的)新的Request给引擎。
  8. 引擎将(Spider返回的)爬取到的Item交给ItemPipeline处理,将(Spider返回的)Request交给调度器,并请求下一个Requests(如果存在的话)。
  9. (从第一步)重复直到调度器中没有更多地Request。

2 安装

pip install scrapy

3 实战:爬取博客园文章信息

3.1 创建项目

创建项目是爬取内容的第一步,Scrapy通过

scrapy startproject

命令来在当前目录下创建一个新的项目。 下面我们创建一个爬取博客园(https://www.cnblogs.com/)文章信息的项目

scrapy startproject cnblog

其中cnblog是你的项目的名字,可以自己定义。 其目录结构如下

cnblog/
    scrapy.cfg

    cnblog/
         __init__.py

        items.py

        pipelines.py

        middlewares.py

        settings.py

        spiders/
            __init__.py

下面简单的讲解一下各目录/文件的作用:

  • scrapy.cfg 项目的配置文件,带有这个文件的那个目录作为scrapy项目的根目录
  • items.py 定义你所要抓取的字段
  • pipelines.py 管道文件,当spider抓取到内容(item)以后,会被送到这里,这些信息(item)在这里会被清洗,去重,保存到文件或者数据库。
  • middlewares.py 中间件,主要是对功能的拓展,你可以添加一些自定义的功能,比如添加随机user-agent, 添加proxy。
  • settings.py 设置文件,用来设置爬虫的默认信息,相关功能开启与否,比如是否遵循robots协议,设置默认的headers,设置文件的路径,中间件的执行顺序等等。
  • spiders/ 在这个文件夹下面,编写你自定义的spider。

3.2 编写爬虫

编写spider文件 在项目中的spiders文件夹下面创建一个文件,命名为cnblog_spider.py我们将在这个文件里面编写我们的爬虫。先上代码再解释。

import scrapy  # 导入scrapy模块

class Cnblog_Spider(scrapy.Spider):  # 定义一个spider类,继承自scrapy.Spider父类

    name = "cnblog"  # name: 用于区别Spider。 该名字必须是唯一的,不可以为不同的Spider设定相同的名字。这一点很重要。
    allowed_domains = ["cnblogs.com"]
    start_urls = [
     'https://www.cnblogs.com/',  # start_urls: 包含了Spider在启动时进行爬取的url列表。第一个被获取到的页面将是其中之一。即这是爬虫链接的起点,爬虫项目启动,便开始从这个链接爬取,后续的URL则从初始的URL获取到的数据中提取。
    ]

    def parse(self, response):  # parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象。 
        title = response.xpath('//a[@class="titlelnk"]/text()').extract()
        link = response.xpath('//a[@class="titlelnk"]/@href').extract()
        print(title)
        print(link)
  • 导入scrapy模块
  • 定义一个spider类,继承自scrapy.Spider父类。
  • name: 用于区别Spider。 该名字必须是唯一的,不可以为不同的Spider设定相同的名字。这一点很重要。
  • start_urls: 包含了Spider在启动时进行爬取的url列表。第一个被获取到的页面将是其中之一。即这是爬虫链接的起点,爬虫项目启动,便开始从这个链接爬取,后续的URL则从初始的URL获取到的数据中提取。
  • parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象。

修改settings.py文件 将settings.py文件里面的下列内容修改如下,其余的内容不动。

ROBOTSTXT_OBEY = False   #不遵循robots协议

#去掉下面的这个注释,以设置请求头信息,伪造浏览器headers,并手动添加一个user-agent
DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
  #user-agent新添加
  'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
}

运行我们的爬虫项目 至此,项目必要的信息已经全部完成了,下面就是运行我们的爬虫项目 进入带有scrapy.cfg文件的那个目录,前面已经说过,这是项目的根目录,执行下面的命令

scrapy crawl cnblog

cnblog是spiders/cnblog_spider.py文件里面我们定义的那个具有唯一性的name 你会发现打印出了博客园首页的文章列表和文章的url信息,如下所示。

3.3 数据存储

我们简单的实现了一个博客首页信息的爬取,并在控制台输出,但是,爬下来的信息自然是需要保存下来的。这一节主要是实现信息的存储,我们以将信息保存到文件为例,学习数据的存储,依然是以博客首页信息为例。

3.4 编写爬虫

修改items.py文件来定义我们的item Item 是保存爬取到的数据的容器;其使用方法和python字典类似。虽然你也可以在Scrapy中直接使用dict,但是Item提供了额外保护机制来避免拼写错误导致的未定义字段错误。简单的来说,你所要保存的任何的内容,都需要使用item来定义,比如我们现在抓取的页面,我们希望保存title,link, 那么你就要在items.py文件中定义他们,以后你会发现,items.py文件里面你所要填写的信息是最简单的了。

import scrapy

class CnblogItem(scrapy.Item):
    title = scrapy.Field()
    link = scrapy.Field()

这样就已经定义好了。
编写spider文件 在项目中的spiders文件夹下面创建一个文件,命名为cnblog_spider.py我们将在这个文件里面编写我们的爬虫。先上代码再解释

import scrapy
from cnblog.items import CnblogItem   #新添加

class Cnblog_Spider(scrapy.Spider):

    name = "cnblog"
    allowed_domains = ["cnblogs.com"]
    start_urls = [
     'https://www.cnblogs.com/',
    ]

    def parse(self, response):
        item = CnblogItem()    #新添加
        item['title'] = response.xpath('//a[@class="titlelnk"]/text()').extract()   #修改
        item['link'] = response.xpath('//a[@class="titlelnk"]/@href').extract()     #修改
        yield item   #新添加

下面主要对新添加或者修改的地方讲解

  • 导入CnblogItem自定义类,注意:新建项目中带有scrapy.cfg文件的那个目录默认作为项目的根目录,因此from cnblog.items import CnblogItem就是从cnblog项目里面的items.py文件里面导入我们自定义的那个类,名称是CnblogItem,就是上面我们定义的那个CnblogItem ,只有导入了这个类,我们才可以保存我们的字段。
  • item = CnblogItem() 实例化,不多说。
  • item['title']和item['link'],前面已经说过,item其实就是可以简单的理解为字典,这个地方就是相当于给字典里面的键赋值。 最后yield item生成器,scrapy会将item传递给pipeline进行后续的处理,当然,前提是你打开了settings设置里面的设置项,相关的设置马上就会说到。

修改pipelines.py文件,实现保存。

class FilePipeline(object):
    '''
    实现保存到txt文件的类,类名这个地方为了区分,做了修改,
    当然这个类名是什么并不重要,你只要能区分就可以,
    请注意,这个类名待会是要写到settings.py文件里面的。
    '''
    def process_item(self, item, spider):
        with open('cnblog.txt', 'w', encoding='utf-8') as f:
            titles = item['title']
            links = item['link']
            for i,j in zip(titles, links):
                f.write(i + ':' + j + '\n')
        return item

修改settings.py文件
之前,我们修改了两个内容,ROBOTSTXT_OBEY和DEFAULT_REQUEST_HEADERS,这里我们在之前的基础上,在添加如下内容。

OBOTSTXT_OBEY = False

DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
  'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
}
#新修改
ITEM_PIPELINES = {      
    'cnblog.pipelines.FilePipeline': 300,    #实现保存到txt文件
}

对于上面的含义,

  • cnblog.pipelines.FilePipeline其实就是应用cnblog/pipelines模块里面的FilePipeline类,就是我们之前写的那个,300的含义是执行顺序,如果还有其他管道保存到数据库,定义管道执行顺序。

运行爬虫 进入到项目文件,执行 scrapy crawl cnblog 可以看到根目录下生成了cnblog.txt的文件

你可能感兴趣的:(初识scrapy爬虫框架)