【Python_Scrapy学习笔记(八)】基于Scrapy框架实现多级页面数据抓取

news/2024/7/19 11:03:44 标签: python, scrapy, 网络爬虫, 爬虫

基于Scrapy框架实现多级页面数据抓取

前言

本文中介绍 如何基于 Scrapy 框架实现多级页面数据的抓取,并以抓取汽车之家二手车数据为例进行讲解。

正文

在介绍如何基于 Scrapy 框架实现多级页面数据的抓取之前,先介绍下 Scrapy 框架的请求对象 request 和响应对象 response。

1、请求对象request属性及方法

  1. request.url:请求的 url 地址
  2. request.headers:请求头-字典格式
  3. request.meta:解析函数间 item 数据传递,定义代理
  4. request.cookies:Cookie 参数

2、响应对象response属性及方法

  1. response.url:返回实际数据的 url 地址
  2. response.text:响应内容-字符串格式
  3. response.body:响应内容-字符串格式
  4. response.encoding:响应字符编码
  5. response.status:HTTP响应码

3、请求对象request的meta参数

meta 参数:在不同的解析函数之间传递数据。
在执行 scrapy.Request() 方法时把一些回调函数中需要的数据传进去,meta 必须是一个字典,在下一个函数中可以使用 response.meta 进行访问,meta 会随着 response 响应对象一起回来,作为response 的一个属性。
注意:meta 传递的数据是浅拷贝传递的,如果传递的数据是可变的数据类型,那么很容易造成数据不对应的错误。
利用 mata 参数在不同的解析函数间传递数据:如有需要继续交给调度器的请求,则创建新的 item 对象。

4、基于Scrapy框架实现多级页面数据抓取

多级页面抓取的注意事项:

  1. 多级页面,数据不能直接提交给管道;
  2. 通过 meta 参数传递的数据是浅拷贝传递的,如果传递的数据是可变的数据类型,那么很容易造成数据不对应的错误;
  3. 针对 meta 参数传递数据不对应的的解决方法:传递多个参数。

案例详情:
这里参考 【Python_Scrapy学习笔记(六)】Scrapy框架基本使用流程 里的案例,并在此案例基础之上升级。

  1. 需求梳理:二级页面要爬取表显里程、上牌时间、排量
    在这里插入图片描述

  2. 整体思路:梳理要改写的 py 文件

    1. items.py:定义所有要抓取的数据结构
    2. car.py:将详情页链接继续交给调度器队列
    3. pipelines.py:处理全部汽车信息的item对象
  3. item.py:定义所有要抓取的数据结构,增加要爬取的三个字段

    python">import scrapy
    
    
    class CarspiderItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        # 汽车的名称、价格、和详情页链接,相当于定义了一个字典,只赋值了key,未赋值value
        name = scrapy.Field()
        price = scrapy.Field()
        link = scrapy.Field()
        # 表显里程、上牌时间、排量
        time = scrapy.Field()
        km = scrapy.Field()
        displacement = scrapy.Field()
    
  4. car.py:将详情页链接继续交给调度器队列,通过 meta 参数传递数据

    python">import scrapy
    from ..items import CarspiderItem
    
    
    class CarSpider(scrapy.Spider):
        name = "car"
        allowed_domains = ["www.che168.com"]
    
        # i = 1
    
        # 1、删除掉 start_urls 变量
        # start_urls = ["https://www.che168.com/china/a0_0msdgscncgpi1ltocsp1exx0/"]  # 从第一页开始
    
        def start_requests(self):
            """
            2、重写 start_requests() 方法:一次性生成所有要抓取的url地址,并一次性交给调度器入队列
            :return:
            """
    
            for i in range(1, 3):
                url = "https://www.che168.com/china/a0_0msdgscncgpi1ltocsp{}exx0/".format(i)
                # 交给调度器入队列,并指定解析函数
                yield scrapy.Request(url=url, callback=self.parse)
    
        def parse(self, response):
            item = {}
            # 先写基准xpath //body/div/div/ul/li
            li_list = response.xpath("//body/div/div/ul[@class='viewlist_ul']/li")
            for li in li_list:
                item["name"] = li.xpath("./@carname").get()
                item["price"] = li.xpath("./@price").get()
                if li.xpath("./a/@href").get().find('/dealer') == 0:
                    item["link"] = "https://www.che168.com" + li.xpath("./a/@href").get()
                else:
                    item["link"] = "https://" + li.xpath("./a/@href").get()[2:]
                # 此时把每个详情页的链接交给调度器入队列
                
                yield scrapy.Request(url=item["link"], meta={'k1': item['name'], 'k2': item['price'], 'k3': item['link']},
                                     callback=self.get_car_info)
                # meta传递的数据是浅拷贝传递的,如果传递的数据是可变的数据类型,那么很容易造成数据不对应的错误。
                # 当scrapy用请求对象发送请求并将返回结果给下一个解析方法后,接收到的meta里的数据是可以被操作修改的,所以item是会被for循环不断的修改,从而接收到的数据是被修改过后的数据。
                # 利用mata参数在不同的解析函数间传递数据:如有需要继续交给调度器的请求,则创建新的item对象
                # 解决方法:传递多个参数
                # 多级页面,不能直接提交给管道
    
        def get_car_info(self, response):
            """
            function:  提取二级页面的数据
                  in:
                 out:
              return:  int >0 ok, <0 some wrong
              others:
            """
            item = CarspiderItem()  # 给item.py的CarspiderItem类做实例化
            # meta会随着response响应对象一起回来,作为response的一个属性
            # item = response.meta["item"]
            item['name'] = response.meta['k1']
            item['price'] = response.meta['k2']
            item['link'] = response.meta['k3']
            item["time"] = response.xpath(".//div[@class='car-box']/ul/li[2]/h4/text()").get()
            item["km"] = response.xpath(".//div[@class='car-box']/ul/li[1]/h4/text()").get()
            item["displacement"] = response.xpath(".//div[@class='car-box']/ul/li[3]/h4/text()").get()
            yield item
    
    
  5. pipelines.py:处理全部汽车信息的item对象

    python">class CarspiderPipeline:
        def process_item(self, item, spider):
            print(item) # 这里只做打印处理
            return item
    
  6. 运行效果
    在这里插入图片描述


http://www.niftyadmin.cn/n/233101.html

相关文章

浅谈工厂模式

文章目录01 | 抽象工厂02 | 工厂方法03 | 未完待续创建模式在什么被创建&#xff0c;谁创建它&#xff0c;它是怎么被创建的&#xff0c;以及何时创建这些方面提供了很强的灵活性。通常创建模式允许用结构和功能差别很大的“产品”对象来配置一个系统 01 | 抽象工厂 抽象工厂模…

【华为OD机试真题 C++】1001 - 在字符串中找出连续最长的数字串含-号 | 机试题+算法思路+考点+代码解析

文章目录 一、题目🔸题目描述🔸输入输出二、代码参考作者:KJ.JK🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🍂个人博客首页: KJ.JK 💖系列专栏:华为OD机试真题(C++) 🍂专栏介绍: 华为OD机试真题汇总,使用C++来进行解析解答实现,帮…

使用ChatGPT+MindShow一键生成PPT,以后再也不用担心制作PPT啦

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

FlinkSQL基本概念、时间属性和窗口

一、需要引入的依赖 flink版本是1.13.3 <dependency><groupId>org.apache.flink</groupId> <artifactId>flink-table-api-java-bridge_${scala.binary.version}</artifactId><version>${flink.version}</version> </dependency…

【我在CSDN成长】我的两周年创作纪念日

【我在CSDN成长】我的两周年创作纪念日一、来到CSDN的大家庭二、在CSDN的收获1.在CSDN的感受2.在CSDN的收获三、在CSDN的未来规划憧憬一、来到CSDN的大家庭 当看到这个信息时&#xff0c;才发现不知不觉已经在CSDN创作两年了&#xff0c;今天才腾出时间来写下这篇博文。感叹时…

C++---状态机模型---大盗阿福(每日一道算法2023.4.11)

注意事项&#xff1a; 建议先了解状态机的基本定义&#xff1a;状态机-百度百科。 题目&#xff1a; 阿福是一名经验丰富的大盗。趁着月黑风高&#xff0c;阿福打算今晚洗劫一条街上的店铺。 这条街上一共有 N 家店铺&#xff0c;每家店中都有一些现金。 阿福事先调查得知&…

decodeURI、decodeURIComponent、encodeURI、encodeURIComponent是什么?

decodeURI(): 解码使用 encodeURI() 编码的统一资源标识符&#xff08;URI&#xff09;。 decodeURIComponent(): 解码使用 encodeURIComponent() 编码的统一资源标识符&#xff08;URI&#xff09;组件。 encodeURI(): 对统一资源标识符&#xff08;URI&#xff09;进行编码…

轻松看懂什么是索引

带你回顾怎么查字典的同时&#xff0c;了解索引 什么是索引&#xff1f; 首先&#xff0c;我们一起回忆一下小时候是如何查字典的吧。比如&#xff1a;萧熏儿的“薰” 我们会先在拼音表找到“X”&#xff0c;然后找到“xun”&#xff0c;看后面的页码是123~125&#xff0c;去…