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, }
浙公网安备 33010602011771号