scrapy爬取图片

news2024/12/27 11:10:06

文章目录

  • ImagesPipeline
  • 使用步骤:
    • 1. 数据解析: 获取图片的地址 & 2. 将存储图片地址的item提交到指定的管道类(`hotgirls.py`)
    • 3. 在管道文件中自制一个基于ImagesPipeLine的一个管道类
      • !!天大的坑 !!
    • 4. 在配置文件settings.py中:
    • item()类
  • 完整代码
    • hotgilrs.py 爬虫文件
    • items.py
    • pipelines.py

使用scrapy爬取图片,采用管道方法进行下载。

  • 这里采用继承ImagesPipeline类的方法来重写get_media_requests,file_path, item_completed。

ImagesPipeline

只需要img的src属性值进行解析,提交给该管道,该管道就会对图片的src进行请求发送获取图片的二进制数据,且保存到本地。

使用步骤:

  1. 数据解析: 获取图片的地址
  2. 将存储图片地址的item提交到指定的管道类
  3. 在管道文件中自制一个基于ImagesPipeLine的一个管道类
    • get_media_requests
    • file_path
    • item_completed
  4. 在配置文件settings.py中:
    • 指定图片的存储路径: IMAGES_STORE
    • 指定开启的管道:自定制的管道类。

本次解析的网站地址:https://www.tuiimg.com/meinv/在这里插入图片描述
谁不爱呢哈哈哈

原本思路:

  1. 每个图片对应一个图集的url。将这些图集详情页url保存下来,对这些详情页url进行解析。
  2. 将这些详情页url中的图片爬取下来

后来发现这个思路不太可行。因为在详情页中还需要点击展开全图,这需要用到selenium的操作,加上scrapy我实现了一下失败了,所以后面换别的方法。

在这里插入图片描述
发现在初始界面的图片src为https://i.tuiimg.net/007/3007/c.jpg
然后点进去他的详情页,发现它每张照片的url为:
在这里插入图片描述
所以我只需要将预览图的c.jpg换成123456就可以得到所有的图片src

1. 数据解析: 获取图片的地址 & 2. 将存储图片地址的item提交到指定的管道类(hotgirls.py

parse() 用于获取所有不同图集的图片src模板,即将c.jpg去掉。
parse_length() 用于获取每个图集的图片张数,并解析每一张图片,将其yield给管道并下载。

from time import sleep

import scrapy
from hotgilrsPro.items import HotgilrsproItem


class HotgirlsSpider(scrapy.Spider):
    name = "hotgirls"
    # allowed_domains = ["www.xxx.com"]
    start_urls = ["https://www.tuiimg.com/meinv/"]
    name_src_list = []
    idx = 0

    def parse_length(self, response):
        item = response.meta['item']
       #  print("当前在parse_length中解析的页面", response.url)
        length = response.xpath('.//div[@id="page"]/span[2]/i//text()').extract_first()
        length = int(length.split('/')[-1][:-1])    # 从str:展开全图(1/75)转到int: 75
        item['length'] = length
        print("当前的idx", self.idx)
        # print("当前长度为:", length)
        for i in range(1, length+1):
            #print("保存在字典中的改写的src为",src, "字典模板为", self.dic['img_template'])
            url = self.name_src_list[self.idx]['img_template'] + f"/{i}.jpg"

            item['src'] = url
           # print("在parse_length中生成的url:", url)
            yield item	# 将带有图片src的item传给管道,对应 2. 将存储图片地址的item提交到指定的管道类
        self.idx += 1

    def parse(self, response):
        # scrapy框架的内容
        li_list = response.xpath('/html/body/div[3]/ul/li') # /html/body/div[3]/ul
        item = HotgilrsproItem()
        item['page_url'] = []

        for li in li_list:
            name = li.xpath('.//a[2]/text()').extract_first()
            img_template = li.xpath('.//a[1]/img/@src').extract_first()
            img_template = img_template[:img_template.rfind('/')]   # 得到前面的模板
            img_template = ''.join(img_template)
            print("当前的name:", name)
            print("当前的模板:", img_template)
            item['img_template'] = img_template
            dic = {}
            dic['name'] = name
            item['name'] = name
            dic['img_srcs'] = {}
            dic['img_template'] = img_template
            self.name_src_list.append(dic)

            page_src = li.xpath('./a[1]/@href').extract_first()
            item['page_url'].append(page_src)
            yield scrapy.Request(url=page_src, callback=self.parse_length, meta={'item': item})  # 这一步是异步的,在这儿等请求响应并接着往下执行。
        print(self.name_src_list)

3. 在管道文件中自制一个基于ImagesPipeLine的一个管道类

!!天大的坑 !!

    return 'images/' + str(self.imgName) + ".jpg"	

这里写图片的路径的时候,前面必须再加上一个目录名,否则不会保存到本地,!!!!

# 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
import scrapy
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
from scrapy.pipelines.images import ImagesPipeline
# from hotgilrsPro.spiders.hotgirls import name_src_list

# 写这里别忘了修改settings。
# class HotgilrsproPipeline:
#     def process_item(self, item, spider):
#         return item

class imgsPileLine(ImagesPipeline):
    imgName = 1
    # 可以根据图片地址进行图片数据的请求
    def get_media_requests(self, item, info):
      #  print("当前在pipelines中请求到图片地址:", item['src'])
        yield scrapy.Request(item['src'])

    # 指定图片的存储路径
    # 这里本来想将图集名称也爬取下来,放到多个文件夹下,但是能力不够没能实现。只能按照张数123一张一张胡乱存。
    def file_path(self, request, response=None, info=None):
        print("当前图片", request.url, "的存储路径", self.imgName)
        self.imgName += 1
        return 'images/' + str(self.imgName) + ".jpg"	


    def item_completed(self, results, item, info):
        return item     # 返回给下一个即将被执行的管理类

4. 在配置文件settings.py中:

#指定图片存储的目录
IMAGES_STORE = './imgs_hotgirls'

# 开启指定管道
ITEM_PIPELINES = {
   # "hotgilrsPro.pipelines.HotgilrsproPipeline": 300,
   "hotgilrsPro.pipelines.imgsPileLine": 250,

}

item()类

class HotgilrsproItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 在item中定义相关的属性
    length = scrapy.Field()
    name = scrapy.Field()
    src = scrapy.Field()
    page_url = scrapy.Field()
    img_template = scrapy.Field()

完整代码

hotgilrs.py 爬虫文件

from time import sleep

import scrapy
from hotgilrsPro.items import HotgilrsproItem


class HotgirlsSpider(scrapy.Spider):
    name = "hotgirls"
    # allowed_domains = ["www.xxx.com"]
    start_urls = ["https://www.tuiimg.com/meinv/"]
    name_src_list = []
    idx = 0

    def parse_length(self, response):
        item = response.meta['item']
       #  print("当前在parse_length中解析的页面", response.url)
        length = response.xpath('.//div[@id="page"]/span[2]/i//text()').extract_first()
        length = int(length.split('/')[-1][:-1])    # 从str:展开全图(1/75)转到int: 75
        item['length'] = length
        print("当前的idx", self.idx)
        # print("当前长度为:", length)
        for i in range(1, length+1):
            #print("保存在字典中的改写的src为",src, "字典模板为", self.dic['img_template'])
            url = self.name_src_list[self.idx]['img_template'] + f"/{i}.jpg"

            item['src'] = url
           # print("在parse_length中生成的url:", url)
            yield item
        self.idx += 1

    def parse(self, response):
        # scrapy框架的内容
        li_list = response.xpath('/html/body/div[3]/ul/li') # /html/body/div[3]/ul
        item = HotgilrsproItem()
        item['page_url'] = []

        for li in li_list:
            name = li.xpath('.//a[2]/text()').extract_first()
            img_template = li.xpath('.//a[1]/img/@src').extract_first()
            img_template = img_template[:img_template.rfind('/')]   # 得到前面的模板
            img_template = ''.join(img_template)
            print("当前的name:", name)
            print("当前的模板:", img_template)
            item['img_template'] = img_template
            dic = {}
            dic['name'] = name
            item['name'] = name
            dic['img_srcs'] = {}
            dic['img_template'] = img_template
            self.name_src_list.append(dic)

            page_src = li.xpath('./a[1]/@href').extract_first()
            item['page_url'].append(page_src)
            yield scrapy.Request(url=page_src, callback=self.parse_length, meta={'item': item})  # 这一步是异步的,在这儿等请求响应并接着往下执行。
        print(self.name_src_list)

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 HotgilrsproItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    length = scrapy.Field()
    name = scrapy.Field()
    src = scrapy.Field()
    page_url = scrapy.Field()
    img_template = scrapy.Field()

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
import scrapy
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
from scrapy.pipelines.images import ImagesPipeline
# from hotgilrsPro.spiders.hotgirls import name_src_list

# 写这里别忘了修改settings。
# class HotgilrsproPipeline:
#     def process_item(self, item, spider):
#         return item

class imgsPileLine(ImagesPipeline):
    imgName = 1
    # 可以根据图片地址进行图片数据的请求
    def get_media_requests(self, item, info):
      #  print("当前在pipelines中请求到图片地址:", item['src'])
        yield scrapy.Request(item['src'])

    # 指定图片的存储路径
    def file_path(self, request, response=None, info=None):
        print("当前图片", request.url, "的存储路径", self.imgName)
        self.imgName += 1
        return 'images/' + str(self.imgName) + ".jpg"


    def item_completed(self, results, item, info):
        return item     # 返回给下一个即将被执行的管理类

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

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

相关文章

Linux常见操作命令(1)

​ 前言:作者也是初学Linux,可能总结的还不是很到位 ♈️今日夜电波:达尔文—林俊杰 0:30━━━━━━️💟──────── 4:06 🔄 ◀️ …

容易理解的归并排序(C语言)

以二路归并为例,可简单理解为: 把一个大的数组拆分成两个数组,拆出来的两个数组再分别拆出两个数组,以此类推,直到每个数组只有一个元素。然后将这些只有一个元素的数组两两合并到一个临时数组,即可完成排序…

ffmpeg、ffplay在线安装,离线导出整个程序,移植到其他服务器使用(linux系统)

环境说明 以ubuntu系统作为说明 在线安装 下面命令会同时安装ffplay和ffmpeg sudo apt-get install ffmpeg怎么验证安装成功? 输入ffmpeg命令 ffmpeg,如图则说明安装成功 转储可执行程序和依赖的文件 找到安装路径,一般在/usr/bin目录…

Redis与分布式-哨兵模式

接上文 Redis与分布式-主从复制 1.哨兵模式 启动一个哨兵,只需要修改配置文件即可, sentinel monitor lbwnb 1247.0.0.1 6001 1先将所有服务关闭,然后修改配置文件,redis Master,redis Slave,redis Slave…

buuctf-[Zer0pts2020]Can you guess it?

点击source&#xff0c;进入源代码 <?php include config.php; // FLAG is defined in config.phpif (preg_match(/config\.php\/*$/i, $_SERVER[PHP_SELF])) {exit("I dont know what you are thinking, but I wont let you read it :)"); }if (isset($_GET[so…

nodejs缓存策略

nodejs缓存策略 缓存是一种强大的技术&#xff0c;可以显著提高nodejs应用程序的性能。 在现代Web应用程序中&#xff0c;性能和效率是直接影响用户体验和应用程序成功的关键因素。 通过将频繁访问的数据存储在缓存中&#xff0c;我们可以减少对昂贵的计算或外部API调用的需求…

记录:Unity脚本的编写

目录 前言添加脚本到unity编写c#脚本查看效果 前言 在学习软件构造这门课的时候&#xff0c;对unity和c#进行了 一定程度的学习&#xff0c;包括简单的建立地形&#xff0c;添加对象&#xff0c;添加材质等&#xff0c;前不久刚好学习了如何通过c#脚本对模型进行操控&#xff…

加入PreAuthorize注解鉴权之后NullPointerException报错

记录一次很坑的bug&#xff0c;加入PreAuthorize注解鉴权之后NullPointerException报错&#xff0c;按理来说没有权限应该403报错&#xff0c;但是这个是500报错&#xff0c;原因是因为controller层的service注入失败&#xff0c;然而我去掉注解后service注入成功&#xff0c;并…

简历项目优化关键方法论-START

START方法论是非常著名的面试法则&#xff0c;经常被面试官使用的工具 Situation:情况、事情、项目需求是在什么情况下发生Task:任务&#xff0c;你负责的做的是什么Action:动作&#xff0c;针对这样的情况分析&#xff0c;你采用了什么行动方式Result:结果&#xff0c;在这样…

Lua如何调用C程序库

在Lua中加载和使用C库需要使用Lua的C API。以下是一个简单的示例&#xff1a; 首先&#xff0c;让我们创建一个C库。在C中&#xff0c;我们可以创建一个文件&#xff0c;如“mylib.c”&#xff0c;包含以下代码&#xff1a; #include <stdio.h> int add(int a, int b) …

imgui开发笔记<1>、ubuntu环境下快速应用

去这个链接下载imgui源码&#xff08;在此之前需要安装opengl glfw3等等&#xff09;&#xff1a; sudo apt-get install libglfw3-dev https://github.com/ocornut/imgui 我这里源码下载到/home/temp/imgui目录下&#xff0c;咱们不需要编译源码成库&#xff0c;而是直接将下…

数据库设计流程---以案例熟悉

案例名字&#xff1a;宠物商店系统 课程来源&#xff1a;点击跳转 信息->概念模型->数据模型->数据库结构模型 将现实世界中的信息转换为信息世界的概念模型&#xff08;E-R模型&#xff09; 业务逻辑 构建 E-R 图 确定三个实体&#xff1a;用户、商品、订单

go-fastdfs分布式文件存储集群搭建和测试

一、官方文件 https://sjqzhang.github.io/go-fastdfs/#character2、集群原理 小集群原理&#xff1a; 大集群原理 二、服务端集群部署 1、在集群每个节点机器上下载安装包 (建议使用最新稳定版本&#xff09; wget --no-check-certificate https://github.com/sjqzhang/go…

使用 wxPython 在 Windows 11 中实现任务栏通知功能

引言&#xff1a; 随着 Windows 11 的发布&#xff0c;用户对于更加智能、个性化的体验有了更高的期望。其中&#xff0c;任务栏通知功能成为了一个备受关注的特性。在本篇博客中&#xff0c;我们将介绍如何使用 wxPython 模块&#xff0c;在 Windows 11 中实现任务栏通知功能。…

2023年第二十届中国研究生数学建模竞赛总结与分享

今天是国庆节&#xff0c;祝祖国繁荣富强。正好也学习不下去&#xff0c;就想着写写博客&#xff0c;总结一下自己在参加2023年第20届中国研究生数学建模比赛的一些感受。 目录 1.基本介绍 2.比赛分享 1.基本介绍 1. 竞赛时间&#xff1a;竞赛定于2023年9月22日8:00至2023年9…

26 docker前后端部署

[参考博客]((257条消息) DockerNginx部署前后端分离项目(SpringBootVue)的详细教程_在docker中安装nginx实现前后端分离_这里是杨杨吖的博客-CSDN博客) (DockerNginx部署前后端分离项目(SpringBootVue)) 安装docker # 1、yum 包更新到最新 yum update # 2、安装需要的软件包…

Hudi第二章:集成Spark(二)

系列文章目录 Hudi第一章&#xff1a;编译安装 Hudi第二章&#xff1a;集成Spark Hudi第二章&#xff1a;集成Spark(二) 文章目录 系列文章目录前言一、IDEA1.环境准备2.代码编写1.插入数据2.查询数据3.更新数据4.指定时间点查询5.增量查询6.删除数据7.覆盖数据 二、DeltaStre…

【sql注入】如何通过SQL注入getshell?如何通过SQL注入读取文件或者数据库数据?一篇文章告诉你过程和原理。sql注入【二】

前言 本篇博客主要是通过piakchu靶场来讲解如何通过SQL注入漏洞来写入文件&#xff0c;读取文件。通过SQL输入来注入木马来getshell等&#xff0c;讲解了比较详细的过程&#xff1b; 如果想要学习SQL注入原理以及如何进行SQL注入&#xff0c;我也写了一篇详细的SQL注入方法及…

国庆作业 day 10.1

使用select完成TCP并发服务器 #include "myhead.h" #define ERR_MSG(msg) do{\printf("%d\n",__LINE__);\perror(msg);\ }while(0) #define PORT 3696 #define IP "192.1168.10.22" int main(int argc, const char *argv[]) { //套接字int sfd…

使用 sonarqube 进行代码质量检查

Docker 环境准备 参考官方文档先对 Docker Server 进行参数调整 Because SonarQube uses an embedded Elasticsearch, make sure that your Docker host configuration complies with the Elasticsearch production mode requirements and File Descriptors configuration. # …