scrapy框架案例:下载zcool网图片

下载图片文件

1, scrapy 框架下载文件(包括图片)有自己的一套解决方案,比我们使用 urlretrieve 更加优势
2. 避免重新下载最近已经下载的文件,指定过期时间,比如一天,一天以内就不会再重复下载了
3. 可以方便的指定文件储存的路径
4. 可以将下载的图片转换成通用的格式,比如PNG JPEG
5. 可以方便的检测图片的宽与高,确保他们满足最小的限制。
6. 可以方便的生成缩略图
7. 异步下载,效率max
8. 更多参考官方文档吧脑部链接

案例:站酷图片下载

  1. 定义item 上面有两个字段,一个是image_urls,一个是images.其中image_urls 是用来储存图片的链接,有开发者吧数据爬下来后添加的。
  2. 使用scrapy.pipelines.images.ImagesPipeline 来作为数据保存pipline
  3. 再 settings.py文件中设置 IMAGES_SOTRE来定义图片下载的路径
  4. 如果想要有更复杂的图片保存路径需要,可以重写ImagePipeline 的 file_path方法,这个方法用于返回每个图片的保存路径。

然后创建项目开写,,,

  1. item
import scrapy

class ZcoolItem(scrapy.Item):
    image_urls = scrapy.Field()    # 这两个是必须的,第一个用来保存这个item上的图片的链接
    image = scrapy.Field()         # 在图片下载完后,形成image对象在保存到这个上面
    title = scrapy.Field()
  1. spider
import scrapy
from scrapy.spiders.crawl import CrawlSpider,Rule    # 如果忘记了路径可以按两下shift再整个项目里搜索
from scrapy.linkextractors import LinkExtractor       # 这里还是把普通的改成crawlspider好,,
from ..items import ZcoolItem

class ZcoolSpiderSpider(CrawlSpider):
    name = 'zcool_spider'
    allowed_domains = ['zcool.com.cn']
    start_urls = ['http://zcool.com.cn/']
    rules={
        Rule(LinkExtractor(allow=r'https://www.zcool.com.cn/?p=\d+#tab_anchor'),follow=True), # 翻页的url
        Rule(LinkExtractor(allow=r'https://www.zcool.com.cn/work/.+html'),follow=False,callback='parse_detail')
    }
    # 如果使用的是CrawlSpider 这个类就不能重写parse方法,因为外再底层会自动调用这个方法,如果重写了就会报错。
    def parse_detail(self, response):
        image_urls = response.xpath(r'//div[@class="work-show-box js-work-content"]//img/@src').getall()
        title = response.xpath(r'//div[@class="details-contitle-box"]/h2/text()').get().strip()
        item = ZcoolItem(title=title,image_urls=image_urls)  # image 不用我们管,scrapy自己帮我设置
        yield item
  1. settings
    除了请求头,不遵守协议,这里由于是要保存图片,直接用’scrapy.pipelines.images.ImagesPipeline’这个已经给我们写好的管道就行(也就是说我们不用再自己写pipeline了。。。。)
import os
ITEM_PIPELINES = {
   'zcool.pipelines.ZcoolPipeline': 300,
    'scrapy.pipelines.images.ImagesPipeline': 1 # 其实这只有一个队列,优先级多少都一样
} 
IMAGES_STORE = os.path.join(os.path.dirname(os.path.dirname(__file__)),'image')
# __file__代表了这个settings文件,找到他爷爷那层目录。。在拼接成我们想保存的路径。其实'D:\scrapy 框架\zcool\image' 也一样

虽然不用写pipeline感觉不错,但是这个方法的问题就是所有的图片都保存再了full 这个文件里,,但是我们想分类的。所有我们就需要重写ImagePipeline 的 file_path方法

    def file_path(self, request, response=None, info=None):   # 这是源码
        image_guid = hashlib.sha1(to_bytes(request.url)).hexdigest()
        return 'full/%s.jpg' % (image_guid)     # 可以看出所有图片都是保存再full这个文件夹里

首先来修改下settings

import os
ITEM_PIPELINES = {
   'zcool.pipelines.ZcoolPipeline': 300, # 因为我们要重写pipeline,所以使用我们自己的就行
} 
IMAGES_STORE = os.path.join(os.path.dirname(os.path.dirname(__file__)),'image')
# 这个参数是必须的,因为ImagesPipeline 还是要从settings 里提取这个

pipeline

from scrapy.pipelines.images import ImagesPipeline
import os,re

class ZcoolPipeline(ImagesPipeline):

	# 我们要分类,就需要title,title就从item来,但是file_path传不进去item,,就把item和request绑定一起
	# def get_media_requests(self, item, info): # 源码,再请求发送之前调用
    #     return [Request(x) for x in item.get(self.images_urls_field, [])]
    
    def get_media_requests(self, item, info):    # 把item与request绑定,
        media_requests = super(ZcoolPipeline, self).get_media_requests(item,info)
        for media_request in media_requests: # 这是把每个图片的请求都绑定上item
            media_request.item = item
        return media_requests

    def file_path(self, request, response=None, info=None): # 再图片下载之后调用
        origin_path = super().file_path(request,response,info) # 父类的路径
        title = request.item['title']
        title = re.sub(r'[\\/:\*\?<>\|"]','',title) # 文件名格式嘛,,不能有\/:*?<>|
        save_path = os.path.join('D:\scrapy 框架\zcool\image','image'),title)
        if not os.path.exists(save_path):
            os.mkdir(save_path)
        image_name = origin_path.replace('full/','') # 需要图片的文件名,,
        return os.path.join(save_path,image_name)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值