初识Scrapy

初识Scrapy框架

之前学习的requestsselenium,它们基本上已经可以满足绝大部分的爬虫需求了。但是,在使用这两个模块的时候,往往会出现爬取效率低的情况,处理的事物多的时候多线程写起来比较麻烦。scrapy给我最大的感受就是可以使我们更便捷地写出高质量的爬虫程序。

1、Scrapy简介

Scrapy是一个为了爬取网站数据、提取结构性数据而编写的应用框架。它使用来Twisted异步网络框架,提高了爬取效率。很多东西框架已经写好,我们可以不用修改或者稍做修改,就可以使用,进而提高了写爬虫程序的效率。

2、Scrapy架构

2.1 5+2结构 (5个组件+2个中间件)

  • Scrapy Enhine: 引擎负责控制数据流在系统中所有组件中流动,并在相应动作发生时触发事件。

  • Scheduler(调度器): 调度器从引擎接受request并将他们入队,以便之后引擎请求他们时提供给引擎。

  • Downloader(下载器) 下载器负责获取页面数据并提供给引擎,而后提供给Spiders。

  • Spiders: Spider是Scrapy用户编写用于分析response并提取item(即获取到的item)或额外跟进的URL的类。 每个spider负责处理一个特定(或一些)网站。

  • Item Pipeline: Item Pipeline负责处理被spider提取出来的item。典型的处理有清理、 验证及持久化(例如存取到数据库中)。

  • Downloader middlewares(下载器中间件): 下载器中间件是在引擎及下载器之间的特定钩子(specific hook),处理Downloader传递给引擎的response。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。

  • Spider middlewares(Spider中间件): Spider中间件是在引擎及Spider之间的特定钩子(specific hook),处理spider的输入(response)和输出(items及requests)。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。

2.2 数据流

  1. 引擎(Scrapy Engine)打开一个网站,找到处理该网站的Spider,并向该Spider请求第一个要爬取的URL
  2. 引擎(Scrapy Engine)从Spider中获取到第一个要爬取的URL后,通过调度器(Scheduler)以Request的形式调度
  3. 引擎(Scrapy Engine)向调度器(Scheduler)请求下一个要爬取的URL
  4. 调度器(Scheduler)返回下一个要爬取的URL给引擎(Scrapy Engine),引擎将该URL通过下载中间件(Downloader middlewares)转发给下载器(Downloader)
  5. 下载器(Downloader)下载页面,一旦页面下载完毕,下载器生成一个该页面的Response,并将其通过下载中间件(Downloader middlewares)发送给引擎
  6. 引擎(Scrapy Engine)从下载中间件(Downloader middlewares)接收Response,并将其通过爬虫中间件(Spider middlewares)发送给爬虫(Spider)处理
  7. 爬虫(Spider)处理Response,并返回处理的Item及新的Request给引擎
  8. 引擎(Scrapy Engine)将爬虫(Spider)返回的Item给管道(Item Pipeline),将新的Request给调度器(Scheduler)
  9. 重复第2步到第8步,直到调度器(Scheduler)中没有更多的Request,引擎(Scrapy Engine)关闭该网站,爬虫结束

可见,Engine是整个程序的中枢。每一步的操作都要经过它。

3、使用Scrapy

3.1 安装Scrapy并配置环境

  1. pip install scrapy
  2. scrapy -h查看是否已添加到path
  3. 若2步骤不成功,则需要手动将scrapy添加到pyth

3.2 Scrapy使用步骤

新建项目–>明确目标Item(要爬取的目标数据)–>编写爬虫spider–> 持久化存储Item pipline

  • 建立一个scrapy爬虫工程
      scrapy startproject Demo #创建一个名为Demo的工程
    
  • 在工程中产生一个scrapy爬虫
      scrapy genspider demo mlp.ldeo.columbia.edu
    
    此时Demo文件夹下的spiders文件夹下会多一个demo.py文件
    .
    ├── Demo                            #外层目录
    │   ├── __init__.py                 #初始化脚本
    │   ├── __pycache__                 #缓存目录无需修改
    │   │   ├── __init__.cpython-38.pyc
    │   │   └── settings.cpython-38.pyc
    │   ├── items.py                   #Items代码模板(继承类) 
    │   ├── middlewares.py             #Middlewares代码模板(继承类)
    │   ├── pipelines.py               #Pipelines代码模板(继承类)
    │   ├── settings.py                #Scrapy爬虫的配置文件
    │   └── spiders                    #Spiders代码模板目录(继承类)
    │       ├── __init__.py            #初始化文件无需修改
    │       ├── __pycache__            #缓存目录无需修改
    │       │   └── __init__.cpython-38.pyc
    │       └── demo.py                #用户自定义的爬虫程序 
    └── scrapy.cfg                     #部署Scrapy爬虫的配置文件
    
  • 配置产生的spider爬虫
    • 编写Spider
      • start_urls
      • parser
      import scrapy
      
      class DemoSpider(scrapy.Spider):
          name = 'demo'
          allowed_domains = ['mlp.ldeo.columbia.edu']
          start_urls = ['https://mlp.ldeo.columbia.edu/logdb/scientific_ocean_drilling/result/']
      
          def parse(self, response):
              tr_list = response.xpath("//tr")
              for tr in tr_list[3:]:
                  item = {
             }
                  item['year']=tr.xpath('./td')[0].xpath('./text()').extract_first()
                  item['program']=tr.xpath('./td')[1].xpath('./text()').extract_first()
                  item['EG/EXP']=tr.xpath('./td')[2].xpath('./text()').extract_first()
                  item['HOLE']=tr.xpath('./td')[3].xpath('./a/text()').extract_first()
                  item['LOCATION']=tr.xpath('./td')[4].xpath('./text()').extract_first()
                  item['OCEAN/SEA']=tr.xpath('./td')[5].xpath('./text()').extract_first()
      
                  yield item
      
    • 编写pipeline
      • 在写pipeline之前需要在settings.py中将其开启
        ITEM_PIPELINES = {
              'Demo.pipelines.DemoPipeline': 300, 
        }
        
      • 同时将日志等级降,也在settings中设置
         LOG_LEVEL = "WARNING"
        
      • 写pipeline (在这里进行持久化存储)
        from itemadapter import ItemAdapter
        
          class DemoPipeline:
              def process_item(self, item, spider):
                  print(item) # 这里可以替换为保存到数据库、本地文件
                  return item
        
        
  • 运行爬虫工程
      scrapy cral demo 
    
全部评论

相关推荐

点赞 1 评论
分享
牛客网
牛客企业服务