爬虫_09_请求传参&中间件&大文件下载&CrawlSpider

09_请求传参&中间件&大文件下载&CrawlSpider

五大核心组件

目的

  1. 大概了解scrapy的运行机制
  2. 为分布式铺垫

在这里插入图片描述

在这里插入图片描述

请求传参实现的深度爬取

深度爬取:爬取的数据没有在同一张页面中(例如首页数据+详情页数据)

在scrapy中如果没有请求传参我们是无法持久化存储数据

实现方式:

  • scrapy.Request(url,callback,meta)
    • meta是一个字典,可以将meta传递给callback
  • callback取出meta:
    • response.meta[‘xx’]

例子:实现多页爬取、请求传参、深度爬取

ℹ️moviePro

import scrapy
from moviePro.items import MovieproItem

class MovieSpider(scrapy.Spider):
    name = 'movie'
    #allowed_domains = ['www.xxx.com']
    start_urls = ['http://www.4567kan.com/index.php/vod/show/id/5.html']
    url = 'http://www.4567kan.com/index.php/vod/show/id/5/page/%d.html'
    pageNum = 2
    def parse(self, response):
        li_list = response.xpath('/html/body/div[1]/div/div/div/div[2]/ul/li')
        for li in li_list:
            title = li.xpath('./div/a/@title').extract_first()
            detail_url = 'http://www.4567kan.com' + li.xpath('./div/a/@href').extract_first()
            item = MovieproItem()
            item['title'] = title
            #对详情页url发起请求
            #meta的作用:可以将meta字典传递给callback
            yield scrapy.Request(url=detail_url,callback=self.parse_detail,meta={'item':item})

        if self.pageNum<5:
            new_url = format(self.url%self.pageNum)
            self.pageNum+=1
            yield scrapy.Request(url=new_url,callback=self.parse)

    #被用作于解析详情页的数据
    def parse_detail(self,response):
        #接收传递过来的meta
        item = response.meta['item']
        desc = response.xpath('/html/body/div[1]/div/div/div/div[2]/p[5]/span[2]').extract_first()
        item['desc'] = desc
        yield item

中间件

  • 作用:批量拦截请求和响应

  • 爬虫中间件

  • 下载中间件(推荐)

    • ℹ️middlePro
    • middlewares.py
      • process_request
      • process_response
      • process_exception
    • 拦截请求:
      • 篡改请求url
      • 伪装请求头信息
        • UA
        • Cookie
      • 设置请求代理(重点)
    • 拦截响应
      • 篡改响应数据
    • 代理操作必须使用中间件才可以实现
      • process_exception:
        • request.meta['proxy'] = 'http://ip:port'

大文件下载

ℹ️imgPro

  • 大文件数据是在管道中请求到的
  • 下属管道类是scrapy封装好的我们直接用即可
  • from scrapy.pipelines.images import ImagesPipeline #提供了数据下载功能,图片、视频、音频
  • 重写该管道类的三个方法:
    • get_media_requests
      • 对图片地址发起请求
    • file_path
      • 返回图片名称即可
    • item_completed
      • 返回item,将其返回给下一个即将被执行的管道类
    • 在配置文件中添加:
      • IMAGES_STORE = ‘dirName’
  • 还有MediaPipeline和FilesPipeline

案例:爬取多张图片

#pipelines.py
#管道需要接收item中的图片地址和名称,然后在管道中请求到图片的数据对其进行持久化存储
from scrapy.pipelines.images import ImagesPipeline #提供了数据下载功能,图片、视频、音频
import scrapy
class ImgsPipeline(ImagesPipeline):
    #根据图片地址发起请求
    def get_media_requests(self, item, info):
        yield scrapy.Request(url=item['src'],meta={'item':item})

    def file_path(self, request, response=None, info=None, *, item=None):
        #通过request获取meta
        item = request.meta['item']
        filePath = item['name']
        return filePath #只需要返回图片名称
    
    #将item传递给下一个即将被执行的管道类
    def item_completed(self, results, item, info):
        return item
    
#settings.py
IMAGES_STORE = './imgLibs'
ITEM_PIPELINES = {
   'imgPro.pipelines.ImgsPipeline': 300,
}

setings.py中的常用配置

  • 增加并发,并发线程

    CONCURRENT_REQUESTS = 100

  • 降低日志级别

    LOG_LEVEL = 'INFO'

  • 禁止cookie

    COOKIES_ENABLED = False

  • 禁止重试,对失败的HTTP禁止重新请求

    RETRY_ENABLED = False

  • 减少下载超时,放弃非常慢的连接

    DOWNLOAD_TIMEOUT = 10 #10秒

CrawlSpider

  • 其实是Spider的一个子类。Spider爬虫文件中爬虫类的父类。
    • 子类的功能一定是多于父类
  • 作用:被用作于专业实现全站数据爬取
    • 将一个页面下所有页码对应的数据进行爬取
  • 基本使用:
    1. 创建一个工程
    2. cd 工程
    3. 创建一个基于CrawlSpider的爬虫文件
      • scrapy genspider -t crawl SpiderName www.xxx.com
    4. 执行工程
  • 注意:
    1. 一个链接提取器对应一个规则解析器(多个链接提取器和多个规则解析器)
    2. 在实现深度爬取的过程中需要和scrapy.Request()结合使用
  • 面试题:
    • 如何将一个网站中所有的链接都进行爬取
  • 任务(首页和详情页都有):尝试使用CrawlSpider实现深度爬取

案例:获得全部链接

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule

class FirstSpider(CrawlSpider):
    name = 'first'
    #allowed_domains = ['http://pic.netbian.com']
    start_urls = ['http://pic.netbian.com/4kfengjing/']

    #实例化LinkExtractor对象
    #链接提取器:根据指定规则(allow参数)在页面中进行连接(url)的提取
    #allow='正则':提取链接的规则
    # link = LinkExtractor(allow=r'http://pic.netbian.com/4kfengjing/index_\d+\.html')
    link = LinkExtractor(allow=r'') #取出网站全站的链接
    rules = (
        #实例化一个Rule对象
        #规则解析器:接收链接提取器提取到的链接,对其发起请求,然后根据指定规则(callback)解析数据
        Rule(link, callback='parse_item', follow=True),
    )
    #follow = True
    #将链接提取器 继续作用到 链接提取器提取到的页码 所对应的 页面中

    def parse_item(self, response):
        print(response)
        #基于response实现数据解析

CrawlSpider实现的深度爬取

通用方式:CrawlSpider+Spider实现

案例:多页问题反映并且获取页内内容
class SumSpider(CrawlSpider):
    name = 'sum'
    #allowed_domains = ['www.xxx.com']
    start_urls = ['http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1']
    #提取页码链接
    link = LinkExtractor(allow=r'id=1&page=\d+')
    #http://wz.sun0769.com/political/politics/index?id=489390
    # link_detail = LinkExtractor(allow=r'index\?id=\d+')
    rules = (
        #解析每一个页码对应页面中的数据
        Rule(link, callback='parse_item', follow=False),
        # Rule(link_detail,callback='parse_detail')
    )
        def parse_item(self, response):
        li_list = response.xpath('/html/body/div[2]/div[3]/ul[2]/li')
        for li in li_list:
            title = li.xpath('./span[3]/a/text()').extract_first().strip()
            status = li.xpath('./span[2]/text()').extract_first()
            detail_url = 'http://wz.sun0769.com' + li.xpath('./span[3]/a/@href').extract_first()
            item = SunproItem()
            item['title'] = title
            item['status'] = status
            yield scrapy.Request(url=detail_url,callback=self.parse_detail,meta={'item':item})

    def parse_detail(self,response):
        content = response.xpath('/html/body/div[3]/div[2]/div[2]/div[2]/pre/text()').extract_first()
        item = response.meta['item']
        item['content'] = content
        yield item
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值