【Python_Scrapy学习笔记(十四)】基于Scrapy框架的文件管道实现文件抓取(基于Scrapy框架实现多级页面的抓取)

前言

本文中介绍 如何基于 Scrapy 框架的文件管道实现文件抓取(基于Scrapy框架实现多级页面的抓取),并以抓取 第一PPT 网站的 PPT 模板为例进行展示,同时抓取此网站数据的方式也是对如何使用 Scrapy 框架实现多级页面的抓取进行详解。

正文

1、Scrapy框架抓取文件原理

Scrapy框架 提供了文件管道类 FilesPipeline,来抓取文件,在使用时需要导入from scrapy.pipelines.files import FilesPipeline,并且重新 get_media_requests() 方法,如果对保存的文件名有要求,则需要重写 file_path() 方法;通过 settings.py 文件中的 FILES_STORE 属性可以设置文件保存路径。

2、Scrapy框架抓取文件实现步骤

  1. 爬虫文件:将文件链接 yield 到管道

  2. 管道文件:导入并继承 scrapy 的 FilesPipeline 类,重写get_media_requests() 方法 和 file_path() 方法;

    from scrapy.pipelines.files import FilesPipeline
    class XxxPipeline(FilesPipeline):
         def get_media_requests(self,xxx):
             # 把链接交给调度器入队列
         def file_path(self,xxx):
             # 此处生成文件名
             return filename
    
  3. settings.py:在全局配置文件中,通过 FILES_STORE=“路径” 指定文件保存的位置。

3、Scrapy框架抓取文件案例

  1. 案例需求:爬取 第一PPT 网站下栏目分类各个类别的PPT模板并保存到本地
    在这里插入图片描述

  2. 一级页面分析:
    一级页面url地址:http://www.1ppt.com/xiazai/
    提取数据:
    li_list = "//div[@class='col_nav clearfix']/ul/li" 第一个不是
    1.1>栏目分类名称: ./a/text()
    1.2>栏目分类链接: ./a/@href:访问资源的路径 需要和 https://www.1ppt.com 进行拼接
    在这里插入图片描述

  3. 二级页面分析:进入到了某个栏目分类
    提取数据:li_list = "//div/dl/dd/ul[@class='tplist']/li"
    2.1>PPT名称: ./h2/a/text()
    2.2>进入详情页链接: ./h2/a/@href:访问资源的路径 需要和 https://www.1ppt.com 进行拼接
    在这里插入图片描述

  4. 三级页面分析:三级页面:进入到了PPT详情页
    提取数据:
    3.1>进入下载页的链接 //ul[@class='downurllist']/li/a/@href :访问资源的路径 需要和 https://www.1ppt.com 进行拼接
    在这里插入图片描述

  5. 四级页面分析:进入到了PPT下载页
    提取数据://ul[@class='downloadlist']/li[@class='c1']/a/@href
    4.1>具体PPT的下载链接 --> 交给项目管道文件处理
    在这里插入图片描述

  6. 创建Scrapy项目:编写items.py文件
    这里要明确最后要保存的只有 大分类的名称 及PPT下载链接

    import scrapy
    
    
    class PptItem(scrapy.Item):
        # 定义什么? 管道文件需要什么?
        # 大分类名称、具体PPT文件名、PPT下载链接
        parent_name = scrapy.Field()
        ppt_name = scrapy.Field()
        download_url = scrapy.Field()
    
    
  7. 编写爬虫文件:

    import scrapy
    from ..items import PptItem
    import json
    
    class PptSpider(scrapy.Spider):
        name = "ppt"
        allowed_domains = ["www.1ppt.com"]
        start_urls = ["http://www.1ppt.com/xiazai/"]
    
        def parse(self, response):
            """
            一级页面的解析函数,提取数据:分类名称和链接
            :param response:
            :return:
            """
            li_list = response.xpath("//div[@class='col_nav clearfix']/ul/li")
            for li in li_list[1:]:  # 从第二个元素开始
                item = PptItem()  # 创建item对象
                item["parent_name"] = li.xpath("./a/text()").get()
                class_href = "https://www.1ppt.com" + li.xpath("./a/@href").get()
                # 将class_href交给调度器入队列
                yield scrapy.Request(url=class_href, meta={
          
          "meta1": item}, callback=self.parse_second_page)
    
        def parse_second_page(self, response):
            """
            二级页面的解析函数,提取数据:PPT名称 & 进入详情页链接
            :return:
            """
            # 接受上一个解析函数传过来的meta对象
            meta1 = response.meta["meta1"]
            # 开始解析提取数据
            li_list = response.xpath("//div/dl/dd/ul[@class='tplist']/li")
            for li in li_list:
                item = PptItem()  # 创建item对象
                item["parent_name"] = meta1["parent_name"]
                item["ppt_name"] = li.xpath("./h2/a/text()").get()
                ppt_info_url = "https://www.1ppt.com" + li.xpath("./h2/a/@href").get()
                # 将ppt_info_url交给调度器入队列
                yield scrapy.Request(url=ppt_info_url, meta={
          
          "meta2": item}, callback=self.parse_third_page)
    
        def parse_third_page(self, response):
            """
            三级页面的解析函数,提取数据:进入下载页的链接
            :param response:
            :return:
            """
            meta2 = response.meta["meta2"]
            enter_download_page = "https://www.1ppt.com" + response.xpath("//ul[@class='downurllist']/li/a/@href").get()
            # 直接交给调度器入队列
            yield scrapy.Request(url=enter_download_page, meta={
          
          "item": meta2}, callback=self.parse_fourth_page)
    
        def parse_fourth_page(self, response):
            """
            四级页面的解析函数,提取数据:具体PPT的下载链接
            :param response:
            :return:
            """
            item = response.meta["item"]
            item["download_url"] = response.xpath("//ul[@class='downloadlist']/li[@class='c1']/a/@href").get()
            # 一条完整的item数据提取完成,交给管道文件处理
            yield item
    
    

    注意:四级页面中meta参数的使用

  8. 在管道文件中导入导入并继承 scrapy 的 FilesPipeline类,重写get_media_requests() 方法 和 file_path() 方法:

    import os
    import scrapy
    from scrapy.pipelines.files import FilesPipeline
    
    
    class PptPipeline(FilesPipeline):
        def get_media_requests(self, item, info):
            """
            重写get_media_requests()方法,将文件下载链接交给调度器入队列
            :param item:
            :param info:
            :return:
            """
            yield scrapy.Request(url=item["download_url"], meta={
          
          "item": item})
    
        def file_path(self, request, response=None, info=None, *, item=None):
            """
            重写file_path(),调整文件保存路径及文件名
            :param request:
            :param response:
            :param info:
            :param item:
            :return:
            """
            item = request.meta["item"]
            # filename:工作总结PPT/xxxxxxxxxxppt.zip
            filename = '{}/{}{}'.format(
                item["parent_name"],
                item["ppt_name"],
                os.path.splitext(item["download_url"])[1]
            )
            return filename
    
    
  9. 在全局配置文件中,通过 FILES_STORE=“路径” 指定文件保存的位置

    FILES_STORE = "./pptfiles/"
    
  10. 创建run.py文件运行爬虫:

    from scrapy import cmdline
    cmdline.execute("scrapy crawl ppt".split())
    
  11. 运行效果:
    在这里插入图片描述
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sallyyellow/article/details/130206148
今日推荐