Python爬取图片并分类存储

前言

既然想要爬取图片,那咱们就要爬一(成)张(百)两(上)张(千)的了(`・ω・´)。既然这么多的图片如果用传统的方式一张张进行下载,那得等到猴年马月👿。毫无意外Scrapy框架可以帮助实现,让我们事半功倍,下面就让我们实现吧!

分析

网上其他文章爬取的要么是美女、要么是猛男,咱们就没那么庸俗了。我们什么类型都要ヽ(°▽、°)ノ。我们要爬取的地址是美桌一个壁纸图片网站。如下图所示:
样张
我们按照红框标题进行分类,用青色框的名字作为图片名。嗯······大概就是这个亚子:
图片结构
详情
接着我们来看一哈那个网页分析
在这里插入图片描述
各类详情
HTML结构
如图所示每一个分类都是一个div,每个div里面都有ul>li,我们要的信息毫无意外的就保存在这里(废话)。然后我们要提取的信息是<h2></h2>中的分类标题;<img>中的图片地址和<p></p>中的图片标题。对于下面这种220 × 147 的小图片不是我们的目标。
在这里插入图片描述
我们要爬就爬大的!!
1920 × 1200 才是我们的需要,看上去护眼(手动滑稽)

1920* 1200

代码实现

我们分析完了就开撸!

创建一个scrapy项目:scrapy startproject Photo
接着创建一个爬虫:scrapy genspider photo_spider win4000.com

项目已经创建,我们来到items.py来进行字段的定义。这里定义了三个:imgtitleimgnameimgurl。然后我们来到刚刚新建的photo_spider.py爬虫文件中编写逻辑

import scrapy

from Photo.items import PhotoItem

class PhotoSpider(scrapy.Spider):
    name = 'photo_spider'
    allowed_domains = ['win4000.com/']
    start_urls = ['http://www.win4000.com/wallpaper.html']

    def parse(self, response):
        div = response.css('div.list_cont')
        for info in div:
            title = info.css('div.tit h2::text').extract_first()
            for li in info.css('ul li'):
                name = li.css('p::text').extract_first()
                next_url = li.css('a::attr(href)').extract_first()
                yield scrapy.Request(next_url, callback=self.con_url, dont_filter=True,
                						meta={'title': title, 'name': name})

    def con_url(self, response):
        item = PhotoItem()
        item['imgtitle'] = response.meta['title']
        item['imgname'] = response.meta['name']
        item['imgurl'] = response.css('.pic-meinv img::attr(src)').extract_first()
        # print(item)
        yield item

由于我们获取的是大图,所以爬虫是在两个页面之间来回穿梭的,我们保存的信息可以在第一个页面通过Request中meta传参的方式传递到下一个页面的回调函数。回调函数通过response.meta[key]获取信息后,填充到item对象中,在信息都填充完毕之后再yield item回调函数如果不能够生效记得在Request对象中添加dont_filter=True参数,即url去重。

图片的下载还是要在管道中进行的,首先我们来讲讲概念。图片的下载在Scrapy内部是ImagesPipeline类控制的,而我们现在就是要继承ImagesPipeline类。虽然ImagesPipeline类是也是继承了FilesPipeline类,但是ImagesPipeline有自己的特色:过滤掉不符合自定义图片尺寸的(settings中设置),图片转换为RGB格式,默认存储格式是jpg…
那么可以在settings中设置的图片属性有:

IMAGES_STORE = 'D:\Image'  # 图片保存地址,默认是IMAGES_STORE\full\名字.jpg
MIN_WIDTH = 220 		# 图片的最小宽度
MIN_HEIGHT = 147		# 图片的最小高度

查看源码可以发现有两个函数是我们需要重写的:

	# 第一个,通过获取的url进行下载
    def get_media_requests(self, item, info): #
        return [Request(x) for x in item.get(self.images_urls_field, [])]
        
    # 第二个,设置下载路径,图片名字默认是哈希值(字母+数字=毫无逻辑(。_ 。))
    def file_path(self, request, response=None, info=None):
        image_guid = hashlib.sha1(to_bytes(request.url)).hexdigest()
        return 'full/%s.jpg' % (image_guid)

具体代码如下

from scrapy.pipelines.images import ImagesPipeline,FilesPipeline
from scrapy import Request

class PhotoPipeline(ImagesPipeline):

    def get_media_requests(self, item, info):
    	# Request meta传参:图片信息
        yield Request(url=item['imgurl'],meta={'name':item['imgname'],'title':item['imgtitle']})
        # 这里注意,如果item['imgurl']的value是字符串直接yild即可,列表需要循环!

    def file_path(self, request, response=None, info=None):
        title = request.meta['title'] # 获取图片的分类标题
        name = request.meta['name']  # 获取图片的名字
        filename = u'{0}/{1}.jpg'.format(title, name) # 根据源码,拼接地址
        return filename

这里敲完之后去settings.py将设置IMAGES_STORE=保存地址,将ITEM_PIPELINES取消注释,后面的数值越小越优先。

执行 scrapy crawl photo_spider 就可以看到图片乖乖在我们定义的路径里了🤗

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值