中间件的使用

  • 作用:拦截所有的请求和响应

  • 拦截请求:process_request拦截正常的请求,process_exception拦截异常的请求

    • 篡改请求的头信息

      def process_request(self, request, spider):
      print('proces_request!!!')
      #UA伪装
      request.headers['User-Agent'] = random.choice(self.user_agent_list)
      return None # user_agent_list 这个列表中是大量的浏览器信息为了给User-Agent切换信息
    • 代理

      #拦截发生异常的请求,目的就是为了将异常的请求进行修正,然后将修正之后的正常的请求进行重新发送
      def process_exception(self, request, exception, spider):
      #代理操作
      # request.meta['proxy'] = 'http://ip:port'
      print('i am exception!!!')
      return request

      注意:process_exception,return request的作用是将修正后的请求重新发送

  • 拦截响应 ------ 以爬取网易新闻为例

    • 篡改响应数据

      • 不满足需求的响应数据对应的一定是不满足需求的响应对象
      • 直接更换响应对象
    • 需求:爬取网易新闻中国内,国际,军事,航工,无人机这五个板块下所有的新闻标题和内容

      • 如何通过中间件更换不满足需求的响应对象
      • selenum如何作用到scrapy中
    • 分析:每一个板块中显示的新闻标题是动态加载的

    • selenium在scrapy中的编码流程:

      • 实例化浏览器对象:爬虫类中将实例化出来的浏览器作为爬虫类的一个属性属性可以交互给中间件类
      • 编写自动化操作:写在中间件的process_response中
      • 关闭浏览器:写在爬虫类的closed(self)方法中
    • 代码实现:

      爬虫文件得到代码:

      # -*- coding: utf-8 -*-
      import scrapy
      from selenium import webdriver
      from wangyiPro.items import WangyiproItem
      class WangyiSpider(scrapy.Spider):
      name = 'wangyi'
      # allowed_domains = ['www.xxx.com']
      start_urls = ['https://news.163.com/']
      #整个项目中涉及的响应对象个数:
      # - 1+5+n
      #解析:解析五个新闻板块对应的url
      five_model_urls = []
      bro = webdriver.Chrome(executable_path=r'C:\Users\Administrator\Desktop\爬虫+数据+算法\chromedriver.exe') #方法只会被调用一次
      def closed(self,spider):
      self.bro.quit() def parse(self, response):
      li_list = response.xpath('//*[@id="index2016_wrap"]/div[1]/div[2]/div[2]/div[2]/div[2]/div/ul/li')
      model_indexs = [3,4,6,7,8]
      for index in model_indexs:
      li_tag = li_list[index]
      #解析出了每一个板块对应的url
      model_url = li_tag.xpath('./a/@href').extract_first()
      self.five_model_urls.append(model_url)
      #对每一个板块的url进行手动的请求发送
      yield scrapy.Request(model_url,callback=self.parse_model) #解析:每一个板块中的新闻标题和新闻详情页的url(两个值都是动态加载出来的)
      def parse_model(self,response):
      #遇到了不满足需求的响应对象就是当前方法中的response参数
      div_list = response.xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/ul/li/div/div')
      for div in div_list:
      title = div.xpath('./div/div[1]/h3/a/text()').extract_first()
      detail_url = div.xpath('./div/div[1]/h3/a/@href').extract_first()
      item = WangyiproItem()
      item['title'] = title
      if detail_url:
      yield scrapy.Request(detail_url,callback=self.parse_detail,meta={'item':item}) def parse_detail(self,response):
      item = response.meta['item']
      content = response.xpath('//*[@id="endText"]//text()').extract()
      content = ''.join(content)
      item['content'] = content yield item

      items.py文件的代码:

      import scrapy
      
      class WangyiproItem(scrapy.Item):
      # define the fields for your item here like:
      title = scrapy.Field()
      content = scrapy.Field()

      middlewares.py文件的代码:中间件

      # -*- coding: utf-8 -*-
      
      # Define here the models for your spider middleware
      #
      # See documentation in:
      # https://docs.scrapy.org/en/latest/topics/spider-middleware.html from scrapy import signals
      from scrapy.http import HtmlResponse
      from time import sleep class WangyiproDownloaderMiddleware(object): def process_request(self, request, spider):
      return None
      #拦截所有的响应(1+5+n),只有5个响应不满足需求
      def process_response(self, request, response, spider):
      #1.将拦截到所有的响应中的指定5个不满足需求的响应对象找出
      # request.url:每一个响应对应的url
      #spider.five_model_urls:5个板块对应的url
      # print(spider.five_model_urls)
      if request.url in spider.five_model_urls:
      #满足if条件的response就是5个板块对应的response
      spider.bro.get(request.url)#对每一个板块对应的url进行get请求发送
      sleep(3)
      spider.bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
      sleep(2)
      spider.bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
      sleep(2)
      page_text = spider.bro.page_source
      new_response = HtmlResponse(url=request.url,body=page_text,encoding='utf-8',request=request)
      return new_response
      #2.将这5个响应对象删除,实例化5个新的响应对象
      #3.保证5个新的响应对象中包含动态加载出来的新闻标题数据
      #4.将满足需求的5个新的响应对象返回
      else:
      return response def process_exception(self, request, exception, spider): pass

    ​ 注:记得在settings.py文件中开启对应的操作

scrapy框架的中间件的更多相关文章

  1. 爬虫2.5-scrapy框架-下载中间件

    目录 scrapy框架-下载中间件 scrapy框架-下载中间件 middlewares.py中有两个类,一个是xxSpiderMiddleware类 一个是xxDownloaderMiddlewar ...

  2. python 全栈开发,Day138(scrapy框架的下载中间件,settings配置)

    昨日内容拾遗 打开昨天写的DianShang项目,查看items.py class AmazonItem(scrapy.Item): name = scrapy.Field() # 商品名 price ...

  3. scrapy框架中间件配置代理

    scrapy框架中间件配置代理import random#代理池PROXY_http = [ '106.240.254.138:80', '211.24.102.168:80',]PROXY_http ...

  4. scrapy框架之下载中间件

    介绍 中间件是Scrapy里面的一个核心概念.使用中间件可以在爬虫的请求发起之前或者请求返回之后对数据进行定制化修改,从而开发出适应不同情况的爬虫. “中间件”这个中文名字和前面章节讲到的“中间人”只 ...

  5. Python爬虫从入门到放弃(十一)之 Scrapy框架整体的一个了解

    这里是通过爬取伯乐在线的全部文章为例子,让自己先对scrapy进行一个整理的理解 该例子中的详细代码会放到我的github地址:https://github.com/pythonsite/spider ...

  6. Python爬虫从入门到放弃(十二)之 Scrapy框架的架构和原理

    这一篇文章主要是为了对scrapy框架的工作流程以及各个组件功能的介绍 Scrapy目前已经可以很好的在python3上运行Scrapy使用了Twisted作为框架,Twisted有些特殊的地方是它是 ...

  7. Scrapy框架

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以 ...

  8. python爬虫入门(六) Scrapy框架之原理介绍

    Scrapy框架 Scrapy简介 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬 ...

  9. Scrapy 框架流程详解

    框架流程图 Scrapy 使用了 Twisted 异步非阻塞网络库来处理网络通讯,整体架构大致如下(绿线是数据流向): 简单叙述一下每层图的含义吧: Spiders(爬虫):它负责处理所有Respon ...

随机推荐

  1. PHP文件包含及使用伪协议getshell

    file:// - 访问本地文件系统 http:// - 访问 HTTP(s) 网址 ftp:// - 访问 FTP(s) URLs php:// - 访问各个输入/输出流(I/O streams) ...

  2. 聊聊自学大数据flume中容易被人忽略的细节

    ​前言:老刘不敢保证说的有多好,但绝对是非常良心地讲述自学大数据开发路上的一些经历和感悟,保证会讲述一些不同于别人技术博客的细节. 01 自学flume的细节 老刘现在想写点有自己特色的东西,讲讲自学 ...

  3. .NET+SqlServer 实现数据读写分离

    如今,我们操作数据库一般用ORM框架 现在用.NET Core + EFCore + SqlServer 实现数据读写分离 介绍 为什么要读写分离? 降低数据库服务器的压力 如何实现读写分离? 1.一 ...

  4. 安装篇六:安装PHP(7.2.29版本)

    准备环境,下载依赖软件 # No1:在前面安装好的基础上,关闭iptables.selinux # No2:安装依赖包 yum install zlib-devel bzip2-devel -y &l ...

  5. 为什么线程安全的List推荐使用CopyOnWriteArrayList,而不是Vector

    注:本系列文章中用到的jdk版本均为java8 相比很多同学在刚接触Java集合的时候,线程安全的List用的一定是Vector.但是现在用到的线程安全的List一般都会用CopyOnWriteArr ...

  6. CentOS7下常用安装服务软件yum方式的介绍

    简介:介绍yum软件包的管理并配置本地yum源 yum安装:基于 C/S 架构,yum安装称之为傻瓜式安装 yum安装优点:方便快捷,不用考虑包依赖,自动下载软件包. yum安装缺点:人为无法干预,无 ...

  7. 【转载】Vue.nextTick 的原理和用途

    对于 Vue.nextTick 方法,自己有些疑惑.在查询了各种资料后,总结了一下其原理和用途,如有错误,请不吝赐教. 概览 官方文档说明: 用法: 在下次 DOM 更新循环结束之后执行延迟回调.在修 ...

  8. informix部署安装

    informix部署安装 一.环境准备 Linux版本:centos7.6 Linux主机名:localhost informix安装包:ibm.ids.14.10.FC4W1.LNX.tar inf ...

  9. 自动化运维工具-Ansible之5-流程控制

    自动化运维工具-Ansible之5-流程控制 目录 自动化运维工具-Ansible之5-流程控制 playbook条件语句 单条件 多条件 多条件运算 示例 playbook循环语句 with_ite ...

  10. Sentry(v20.12.1) K8S 云原生架构探索,SENTRY FOR JAVASCRIPT SDK 配置详解

    系列 Sentry-Go SDK 中文实践指南 一起来刷 Sentry For Go 官方文档之 Enriching Events Snuba:Sentry 新的搜索基础设施(基于 ClickHous ...