爬虫 scrapy ——scrapy shell调试及下载当当网数据(十一)

news2024/11/22 21:47:09

目录

一、scrapy shell

1.什么是scrapy shell?

 2.安装 ipython

3.使用scrapy shell

二、当当网案例

1.在items.py中定义数据结构

2.在dang.py中解析数据

3.使用pipeline保存

4.多条管道的使用

5.多页下载

参考


一、scrapy shell

1.什么是scrapy shell?

什么是scrapy shell?

        scrapy终端,是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码。其本意是用来测试提取数据的代码,不过您可以将其作为正常的python终端,在上面测任何的python代码。该终端是用来测试Xpath或css表达式,查看他们的工作方式及从爬取的网页中提取的数据。在编写您的spider时,一旦熟悉了scrapy终端后,您会发现其在开发和调试spider时发挥的最大作用。

 2.安装 ipython

安装ipython

        pip install ipython 

        安装ipython后,scrapy终端将使用ipython代替python终端,ipython终端与其他相比更为强大,提供智能的自动补全,高亮输出及其他特性。

3.使用scrapy shell

在终端输入以下命令

scrapy shell 域名

eg:scrapy shell www.baidu.com

输出:进入到ipython

以上命令返回了一个response,可以直接使用

如下所示:可以调试返回的结果

二、当当网案例

目标:爬取当当网目标图书类目的所有图片、书名和价格,实现三者并行下载。

1.在items.py中定义数据结构

定义要获取的图片、书名和价格

class Scrapy095Item(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 通俗地讲就是你下载的数据都有什么

    # 爬取图片
    img = scrapy.Field()
    # 爬取书名
    name = scrapy.Field()
    # 爬取价格
    price = scrapy.Field()

    pass

2.在dang.py中解析数据

同时下载书名、图片和价格,找到三者共在的标签 ‘ul’

定位Xpath路径,我们之前是这样写的,获取了每个内容的列表,但是我们想要的是书名、图片和价格相对应的结果。

# 找到三者共同所在的标签
img = response.xpath('//ul[@id="component_59"]/li//img/@src')
name = response.xpath('//ul[@id="component_59"]/li//img/@alt')
response.xpath('//ul[@id="component_59"]/li//p[@class="price"]/span[1]/text()')

所以我们现在这样写:

调用selector下的Xpath,可以同时获取一个 li 中的三个内容。

# 所有selector对象可以在此调用 Xpath方法
li_list = response.xpath('//ul[@id="component_59"]/li')
for li in li_list:
    img = li.xpath('.//img/@src').extract_first()
    name = li.xpath('.//img/@alt').extract_first()
    price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
    print(img,name,price)

这样就获取到了。 

但是发现,图片全都为 “none”,这是因为网页的懒加载造成的,避免网页一下子加载太多数据。

所以我们要找到真正的图片链接,即 ‘data-original’,而不是‘src’。

然后我们修改路径,得到下面结果。

又发现了问题,我们并没有拿到第一个数据的链接,因为第一个数据没有‘data-original’属性。

修改为以下代码

 # 所有selector对象可以在此调用 Xpath方法
li_list = response.xpath('//ul[@id="component_59"]/li')
for li in li_list:
    # 第一章图片的链接在 src 里
    # 其余图片的链接在 data-original 里
    img = li.xpath('.//img/@data-original').extract_first()
    if img:
         img = img
    else:
         img = li.xpath('.//img/@src').extract_first()

     name = li.xpath('.//img/@alt').extract_first()
     price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
     print(img,name,price)

 这样我们就获取到了所有数据

3.使用pipeline保存

将数据交给 pipeline,添加最后两行代码。

调用 items.py 中的 Scrapy095Item 类。其中img=,name=和price=为 items.py中定义的变量。

# 所有selector对象可以在此调用 Xpath方法
li_list = response.xpath('//ul[@id="component_59"]/li')
for li in li_list:
    # 第一章图片的链接在 src 里
    # 其余图片的链接在 data-original 里
    img = li.xpath('.//img/@data-original').extract_first()
    if img:
       img = img
    else:
       img = li.xpath('.//img/@src').extract_first()

    name = li.xpath('.//img/@alt').extract_first()
    price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
    print(img,name,price)

    book = Scrapy095Item(img=img,name=name,price=price)

    # 将 book 交给 pipeline 下载
    yield book

什么是yield?        

        带有yield的函数可以视作一个生成器generator,可用于迭代。yield是一个类似于return的关键字,迭代一个遇到yield时就返回yield后面的值。重点是:下一次迭代时,从上一次迭代遇到的yield后面的代码开始执行。

        也就是说,yield会不断把book传递给pipeline。

如果要使用管道的话,就要在 settings.py 中开启管道,解开注释。

在 pipelines.py 中保存数据

# 如果要使用管道的话,就要在 settings.py 中开启管道
class Scrapy095Pipeline:
    # item 就是 yield 的返回值
    def process_item(self, item, spider):
        # 保存数据
        with open('book.json','a', encoding='utf-8') as file:
            # 存在的问题
            # item 是一个对象,需要将其转换为 str
            # 写文件的方式要改为 ‘a’ 追加模式,而不是 ‘w’覆盖模式。
            file.write(str(item))

        return item

需要注意的是:

        item 是一个对象,需要将其转换为 str

        写文件的方式要改为 ‘a’ 追加模式,而不是 ‘w’覆盖模式。

这样就把内容保存下载来了

但是这样写文件的缺点是,写数据时需要频繁的打开关闭文件,对文件的操作过于频繁。

所以我们只要打开并关闭一次文件

定义两个函数 open_spider 和 close_spider ,这两个函数是 scrapy的内置函数,可以操作文件只打开或者关闭一次。

# 如果要使用管道的话,就要在 settings.py 中开启管道
class Scrapy095Pipeline:
    # 在爬虫文件开始之前就执行的一个文件
    def open_spider(self, spider):
        print('++++++++++++++++++++++++++')
        self.fp = open('book.json','w',encoding='utf-8')

    # item 就是 yield 的返回值
    def process_item(self, item, spider):
        # 我们不这样保存
        # # 保存数据
        # with open('book.json','a', encoding='utf-8') as file:
        #     # 存在的问题
        #     # item 是一个对象,需要将其转换为 str
        #     # 写文件的方式要改为 ‘a’ 追加模式,而不是 ‘w’覆盖模式。
        #     file.write(str(item))

        self.fp.write(str(item))

        return item

    # 在爬虫文件执行完之后再执行的方法
    def close_spider(self, spider):
        print('----------------------')
        self.fp.close()

4.多条管道的使用

在 pipelines.py 中添加一个类,模仿上一个类写,用来下载图片,注意,这个类中定义的方法要与上一个类相同,然后我们在这个类中写下载图片的代码,最后返回 item

import urllib.request
# 多条管道开启
# (1)定义管道类
# (2)在settings中开启管道
class Scrapy095_download_Pipeline:
    def process_item(self, item, spider):

        url = 'http:' + item.get('img')
        filename = './books/' + item.get('name') + '.jpg'
        urllib.request.urlretrieve(url=url, filename=filename)
        return item

重要的是,我们要为下图片创建一个新管道,才能实现JSON数据保存和图片下载的同时进行。

在 settings.py 中新添加一个管道,修改的名字就是我们定义的类名。

这样再运行爬虫文件,就可以得到JSON文件和所有的图片了。

5.多页下载

找一下每一页的url之间的规律

# http://category.dangdang.com/pg2-cp01.36.04.00.00.00.html

# http://category.dangdang.com/pg3-cp01.36.04.00.00.00.html

# http://category.dangdang.com/pg4-cp01.36.04.00.00.00.html

可以看到,只有page不一样

所以我们可以在 dang.py 的类中定义一个url_base。

url_base = 'http://category.dangdang.com/pg'
page = 1

然后在 parse方法中添加以下代码

使用 yield 将新的url再传递给 parse() 方法。

# 多个页面的请求
# 每一页爬取的业务逻辑都是一样的,所以我们只需要将执行的那个页的请求再次调用parse方法
# http://category.dangdang.com/pg2-cp01.36.04.00.00.00.html
# http://category.dangdang.com/pg3-cp01.36.04.00.00.00.html
# http://category.dangdang.com/pg4-cp01.36.04.00.00.00.html

if self.page < 10:
     self.page = self.page + 1
     url = self.url_base + str(self.page) + '-cp01.36.04.00.00.00.html'

     # 怎么调用 parse 方法
     # scrapy.Request 就是scrapy的get请求
     # url 就是请求地址,callback就是你要执行的那个函数,不需要加‘ () ’
     yield scrapy.Request(url=url, callback=self.parse)

完整代码:

dang.py

import scrapy
from ..items import Scrapy095Item

class DangSpider(scrapy.Spider):
    name = 'dang'
    # 如果是多页下载,allowed_domains只保留域名,去掉协议和地址,为的是扩大允许范围
    allowed_domains = ['category.dangdang.com']
    start_urls = ['http://category.dangdang.com/cp01.36.04.00.00.00.html']

    url_base = 'http://category.dangdang.com/pg'
    page = 1

    def parse(self, response):
        print('=============================')
        # pipeline  下载数据
        # items     定义数据结构

        # 找到三者共同所在的标签
        # img = response.xpath('//ul[@id="component_59"]/li//img/@data-original')
        # name = response.xpath('//ul[@id="component_59"]/li//img/@alt')
        # price = response.xpath('//ul[@id="component_59"]/li//p[@class="price"]/span[1]/text()')

        # 所有selector对象可以在此调用 Xpath方法
        li_list = response.xpath('//ul[@id="component_59"]/li')
        for li in li_list:
            # 第一章图片的链接在 src 里
            # 其余图片的链接在 data-original 里
            img = li.xpath('.//img/@data-original').extract_first()
            if img:
                img = img
            else:
                img = li.xpath('.//img/@src').extract_first()

            name = li.xpath('.//img/@alt').extract_first()
            price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
            print(img,name,price)

            book = Scrapy095Item(img=img,name=name,price=price)

            # 将 book 交给 pipeline 下载
            yield book


        # 多个页面的请求
        # 每一页爬取的业务逻辑都是一样的,所以我们只需要将执行的那个页的请求再次调用parse方法
        # http://category.dangdang.com/pg2-cp01.36.04.00.00.00.html
        # http://category.dangdang.com/pg3-cp01.36.04.00.00.00.html
        # http://category.dangdang.com/pg4-cp01.36.04.00.00.00.html

        if self.page < 10:
            self.page = self.page + 1
            url = self.url_base + str(self.page) + '-cp01.36.04.00.00.00.html'

            # 怎么调用 parse 方法
            # scrapy.Request 就是scrapy的get请求
            # url 就是请求地址,callback就是你要执行的那个函数,不需要加‘ () ’
            yield scrapy.Request(url=url, callback=self.parse)

        print('=============================')

items.py

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class Scrapy095Item(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 通俗地讲就是你下载的数据都有什么

    # 爬取图片
    img = scrapy.Field()
    # 爬取书名
    name = scrapy.Field()
    # 爬取价格
    price = scrapy.Field()

    pass

pipelines.py

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter

# 如果要使用管道的话,就要在 settings.py 中开启管道
class Scrapy095Pipeline:
    # 在爬虫文件开始之前就执行的一个文件
    def open_spider(self, spider):
        print('++++++++++++++++++++++++++')
        self.fp = open('book.json', 'w', encoding='utf-8')

    # item 就是 yield 的返回值
    def process_item(self, item, spider):
        # 我们不这样保存
        # # 保存数据
        # with open('book.json','a', encoding='utf-8') as file:
        #     # 存在的问题
        #     # item 是一个对象,需要将其转换为 str
        #     # 写文件的方式要改为 ‘a’ 追加模式,而不是 ‘w’覆盖模式。
        #     file.write(str(item))

        self.fp.write(str(item))

        return item

    # 在爬虫文件执行完之后再执行的方法
    def close_spider(self, spider):
        print('----------------------')
        self.fp.close()


import urllib.request
# 多条管道开启
# (1)定义管道类
# (2)在settings中开启管道
class Scrapy095_download_Pipeline:
    def process_item(self, item, spider):

        url = 'http:' + item.get('img')
        filename = './books/' + item.get('name') + '.jpg'
        urllib.request.urlretrieve(url=url, filename=filename)
        return item

settings.py 中只 取消ROBOTSTXT_OBEY的注释,并添加下面的管道。

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
    # 管道可以有很多个,但管道是有优先级的,优先级范围是 1-1000, 值越小,优先级越高。
   'scrapy_095.pipelines.Scrapy095Pipeline': 300,
   'scrapy_095.pipelines.Scrapy095_download_Pipeline': 301,
}

参考

尚硅谷Python爬虫教程小白零基础速通(含python基础+爬虫案例)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1317727.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VBA即用型代码手册之工作薄的创建及保存

我给VBA下的定义&#xff1a;VBA是个人小型自动化处理的有效工具。可以大大提高自己的劳动效率&#xff0c;而且可以提高数据的准确性。我这里专注VBA,将我多年的经验汇集在VBA系列九套教程中。 作为我的学员要利用我的积木编程思想&#xff0c;积木编程最重要的是积木如何搭建…

python封装执行cmd命令的方法

一、前置说明 在自动化时&#xff0c;经常需要使用命令行工具与系统进行交互&#xff0c;因此可以使用python封装一个执行cmd命令的方法。 二、代码实现 import subprocess import timefrom common.exception import RunCMDError from common.logger import loggerclass Cmd…

Nat Med | 白血病患儿持续存在CD19 CAR-T细胞的转录特征

今天给同学们分享一篇实验文章“Transcriptional signatures associated with persisting CD19 CAR-T cells in children with leukemia ”&#xff0c;这篇文章发表在Nat Med期刊上&#xff0c;影响因子为82.9。 结果解读&#xff1a; 研究队列和实验概述 作者研究了15例高…

网络编程day2作业

1.tcp实现通信 服务器&#xff1a; //tcp服务端#include <head.h>#define SERPORT 8888 #define IP "192.168.125.6"int main(int argc, const char *argv[]) { //1.创建套接字int sfdsocket(AF_INET,SOCK_STREAM,0);//2.绑定struct sockaddr_in ser;ser.sin…

java --- 集合进阶

目录 一、单列集合顶层接口 Collection 1.1 基本方法 1.2 Collection 的遍历方式 二、list集合 1.2 ArrayList Vector 底层结构 1.3 LinkedList ArrayList 和 LinkedList 比较 三、set接口 3.1、Set 接口和常用方法 3.2 HashSet HashSet 底层机制&#xff08;HashMap…

虚拟机Linux(Centos7)安装Docker

如果没有安装虚拟机的&#xff0c;可以参考这篇VMware虚拟机安装Linux操作系统&#xff08;CentOS7&#xff09; 文章目录 0.安装Docker1.CentOS安装Docker1.1.卸载&#xff08;可选&#xff09;如何看自己的虚拟机上是否安装过docker&#xff1f; 1.2.安装docker1.3.启动docke…

pytest之allure测试报告02:allure具体使用方法

一、allure包含的方法 二、allure使用教程 &#xff08;1&#xff09;用例中写入allure方法 allure.epic("数据进制项目epic") allure.feature("手机号模块feature") class TestMobile:allure.story("杭州的手机号story")allure.title("测…

多层记忆增强外观-运动对齐框架用于视频异常检测 论文阅读

MULTI-LEVEL MEMORY-AUGMENTED APPEARANCE-MOTION CORRESPONDENCE FRAMEWORK FOR VIDEO ANOMALY DETECTION 论文阅读 摘要1.介绍2.方法2.1外观和运动对其建模2.2.记忆引导抑制模块2.3. Training Loss2.4. Anomaly Detection 3.实验与结果4.结论 论文标题&#xff1a;MULTI-LEVE…

重磅!大模型(LLMs)排行榜清单发布!

目前&#xff0c;人工智能领域呈现出一片蓬勃发展的景象&#xff0c;大型模型成为了激发这一繁荣的关键引擎。 国内不仅涌现了众多大模型&#xff0c;而且它们的发展速度之快令人瞩目。这种全面拥抱大型模型的态势为整个人工智能生态系统赋予了新的活力&#xff0c;让我们对国…

栈——OJ题

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、最小栈1、题目讲解2、思路讲解3、代码实现 二、栈的压入、弹出序列1、题目讲解2、思路讲解…

CCD相机为什么需要积分球均匀光源

积分球内腔是一个具备高漫反射特性的收光球&#xff0c;其内部中空、内球面均匀地涂有漫反射材料&#xff0c;具有匀光与混光的作用&#xff0c;因此常常被用来做收光的均光球。由于光源性能等因素的影响&#xff0c;可能导致出射光线带偏振方向、出光不均匀&#xff0c;使用积…

Windows11环境下配置深度学习环境(Pytorch)

目录 1. 下载安装Miniconda2. 新建Python3.9虚拟环境3. 下载英伟达驱动4. 安装CUDA版Pytorch5. CPU版本pytorch安装 1. 下载安装Miniconda 下载安装包&#xff1a;镜像文件地址 将Miniconda相关路径添加至系统变量的路径中。 打开Anaconda Powershell Prompt&#xff0c;输入…

【C++学习————引用】

【C学习——————引用】 欢迎阅读新一期的c模块————引用 ✒️个人主页&#xff1a;-Joker- &#x1f3f7;️专栏&#xff1a;C &#x1f4dc;代码仓库&#xff1a;c_code &#x1f339;&#x1f339;欢迎大佬们的阅读和三连关注&#xff0c;顺着评论回访&#x1f339;&a…

秋招上岸记录咕咕咕了。

思考了一下&#xff0c;感觉并没有单独写这样一篇博客的必要。 能够写出来的&#xff0c;一些可能会对人有帮助的东西都做进了视频里面&#xff0c;未来会在blbl发布&#xff0c;目前剪辑正在施工中&#xff08;&#xff1f;&#xff09; 另外就是&#xff0c;那个视频里面使…

Win11 跑通tensorRT

cuda_12.3.1_546.12_windows TensorRT-8.6.1.6.Windows10.x86_64.cuda-12.0 cudnn-windows-x86_64-8.9.7.29_cuda12-archive 准备 1.安装cuda&#xff0c;成功之后文件夹如下图所示 2.下载cudnn&#xff0c;把cudnn对应的文件放在cuda里面 3.安装vs 4.安装对应cuda版本的te…

DevOps常用工具全家桶,实现高效运维和交付

专栏集锦&#xff0c;大佬们可以收藏以备不时之需&#xff1a; Spring Cloud 专栏&#xff1a;http://t.csdnimg.cn/WDmJ9 Python 专栏&#xff1a;http://t.csdnimg.cn/hMwPR Redis 专栏&#xff1a;http://t.csdnimg.cn/Qq0Xc TensorFlow 专栏&#xff1a;http://t.csdni…

Linux c++开发-06-使用Linux API 进行文件的读写

先简单的介绍一下open,read,write 先用open接口去打开文件&#xff0c;flag表示打开文件的权限不同。 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);示例 结果&#xff1a;

基于AT89C51单片机的LED点阵显示屏设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; [[https://download.csdn.net/download/qq_64505944/88637464?spm1001.2014.3001.5503]] **[源码获取] B 源码仿真图课程设计50 工程实训&#xff08;三&#xff09;课题设计 班级&#xff1a; …

FPGA — Vivado下ILA(逻辑分析仪)详细使用方法

使用软件&#xff1a; Vivado 开发板&#xff1a; EGO1采用Xilinx Artix-7系列XC7A35T-1CSG324C FPGA 使用程序&#xff1a;按键案例 ILA详细使用方法 一、ILA简介二、ILA的使用方法方法1 — 使用IP核创建ILA调试环境创建ILA IP核 方法二 — 使用 Debug 标记创建 ILA对需观察信…

使用IDEA创建springboot依赖下载很慢,解决方法

显示一直在resolving dependencies&#xff0c;速度很慢 原因&#xff1a;maven会使用远程仓库来加载依赖&#xff0c;是一个国外的网站&#xff0c;所以会很慢。应该使用阿里云的镜像&#xff0c;这样速度会提升很多。 步骤&#xff1a;1.右击pom.xml&#xff0c;选择"m…