scrapy运行流程、核心组件、基于管道的持久化存储

Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速、简单、可扩展的方式从网站中提取所需的数据。但目前Scrapy的用途十分广泛,可用于如数据挖掘、监测和自动化测试等领域,也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。

Scrapy 是基于twisted框架开发而来,twisted是一个流行的事件驱动的python网络框架。因此Scrapy使用了一种非阻塞(又名异步)的代码来实现并发。

整体架构大致如下:

 

1、大体的运行流程

1、spider中的url被封装成请求对象交给引擎(每一个url对应一个请求对象);
2、引擎拿到请求对象之后, 将其全部交给调度器;
3、调度器拿到所有请求对象后, 通过内部的过滤器过滤掉重复的url, 最后将去重后的所有url对应的请求对象压入到队列中, 随后调度器调度出其中一个请求对象, 并将其交给引擎;
4、引擎将调度器调度出的请求对象交给下载器;
5、下载器拿到该请求对象去互联网中下载数据;
6、数据下载成功后会被封装到response中, 随后response会被交给下载器;
7、下载器将response交给引擎;
8、引擎将response交给spiders;
9、spiders拿到response后调用回调方法进行数据解析, 解析成功后产生item, 随后spiders将item交给引擎;
引擎将item交给管道, 管道拿到item后进行数据的持久化存储.

2、核心组件和中间件

引擎(Scrapy): 用来处理整个系统的数据流处理, 触发事务(框架核心)
调度器(Scheduler): 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
下载器(Downloader): 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
爬虫(Spiders): 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
项目管道(Pipeline): 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
下载器中间件(Downloader Middlewares): 位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
爬虫中间件(Spider Middlewares): 介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。
调度中间件(Scheduler Middewares): 介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。

3、持久化存储

方式一:基于终端指令:只可以将parse方法的返回值存储到磁盘文件中

  scrapy crawl wangyiyun(爬虫文件名) -o ***.csv

方式二:基于管道

实现流程:
- 数据解析

- 封装item类
- 实例化item类型的对象
- 将解析到的数据依次存储封装到item类型的对象中
- 将item提交给管道
- 在管道中实现io操作
- 开启管道

4、爬取网易国内新闻的代码

爬虫文件中:

# -*- coding: utf-8 -*-
import scrapy
import json
import re
from wangyinews.items import WangyinewsItem

class NewsSpider(scrapy.Spider):
    name = "news"
    # allowed_domains = ["www.jskaj.com"]
    start_urls = ['https://news.163.com/domestic/']

    def parse(self, response):
        title_url='https://temp.163.com/special/00804KVA/cm_guonei.js?callback=data_callback'
        yield scrapy.Request(url=title_url,callback=self.title_parse)
        #https://temp.163.com/special/00804KVA/cm_guonei.js?callback=data_callback

    def title_parse(self, response):
        response.ecoding='utf-8'
        title_list=re.findall('"title":"(.*?)",.*?"docurl":"(.*?)",',response.text,re.S)
        # print(title_list)
        for t,u in title_list:
            title=t.encode('iso-8859-1').decode('GBK')
            item=WangyinewsItem()
            item['title']=title
            yield scrapy.Request(url=u,callback=self.detail_parse,meta={'item':item})
            # print(title)
            # print(title,u)

    def detail_parse(self, response):
        item=response.meta['item']
        detail_list=response.xpath('//*[@id="endText"]/p//text()').extract()
        desc='\n'.join(detail_list)
        item['desc']=desc
        # print(desc)
        yield item

items.py文件中:

import scrapy


class WangyinewsItem(scrapy.Item):
    # define the fields for your item here like:
    title = scrapy.Field()
    desc = scrapy.Field()

piplines文件中:

class WangyinewsPipeline(object):
    fp=None
    def open_spider(self,spider):
        # title = item['title']
        print(spider)
        self.fp=open('wangyinews/网易国内新闻/'+'国内新闻'+'.txt','wt',encoding='utf-8')

    def process_item(self, item, spider):
        title=item['title']
        desc=item['desc'].strip()
        # desc = item['desc'].replace('问:','\n问:').replace('答:','\n答:')
        self.fp.write(title+'\n'+desc+'\n----------------------------------------\n')
        return item


    def close_spider(self,spider):
        self.fp.close()

settings中重设的配置项:

USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'

ROBOTSTXT_OBEY = False

LOG_LEVEL = 'ERROR'

ITEM_PIPELINES = {
   'wangyinews.pipelines.WangyinewsPipeline': 300,
}

 

posted @ 2019-05-07 21:42  海予心  阅读(118)  评论(0)    收藏  举报