利用scrapy框架爬取图片并重命名
https://blog.csdn.net/qq_42164596/article/details/102516252?spm=1001.2101.3001.6650.5&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-5.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-5.no_search_link
前言
Scrapy提供了一个 item pipeline ,来下载属于某个特定项目的图片。这条管道,被称作图片管道,在 ImagesPipeline 类中实现,提供了一个方便并具有额外特性的方法,来下载并本地存储图片。
开发环境及工具介绍
python 3.7
scrapy 1.7.3
xpath选择器
软件:pycharm
一、创建项目
在terminal里输入
scrapy startproject image    #创建爬虫项目
scrapy genspider photo meishij.com  #创建爬虫文件
- 1
- 2
这样项目就建好了。
项目结构如下:
二、编写 item.py
Item使用简单的class定义语法以及 Field 对象来声明。
import scrapy
class ImageItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    image_urls = scrapy.Field()
    image_name = scrapy.Field()
三、编写爬虫文件 photo.py
Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。
import scrapy
from image.items import ImageItem
class PhotoSpider(scrapy.Spider):
    name = 'photo'
    allowed_domains = ['meishij.net']
    start_urls = ['https://www.meishij.net/china-food/caixi/qingzhencai/'
    
    def parse(self, response):
        item = ImageItem()
        image_urls = response.xpath('//*[@id="listtyle1_list"]/div/a/img/@src').extract()
        image_name = response.xpath('//*[@id="listtyle1_list"]/div/a/div/div/div[1]/strong/text()').extract()
        for i in range(0, len(image_name)):
            item['image_urls'] = image_urls[i]
            item['image_name'] = image_name[i]
            yield item
四、编写管道文件pipelines.py
import scrapy
import re
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
class ImagePipeline(ImagesPipeline):
    def get_media_requests(self, item, info):
        image_url = item['image_urls']
        yield scrapy.Request(image_url,meta={'name':item['image_name']})
    def item_completed(self, results, item, info):
        image_paths = [x['path'] for ok, x in results if ok]
        if not image_paths:
            raise DropItem("Item contains no images")
        return item
    def file_path(self, request, response=None, info=None):
        name = request.meta['name']    # 接收上面meta传递过来的图片名称                                        
        name = re.sub(r'[?\\*|“<>:/]', '', name)    # 过滤windows字符串,不经过这么一个步骤,你会发现有乱码或无法下载
        filename= name +'.jpg'          #添加图片后缀名
        return filename
方法解析:
- get_media_requests(item, info)
 在工作流程中可以看到,管道会得到图片的URL并从项目中下载。为了这么做,你需要重写 get_media_requests() 方法,并对各个图片URL返回一个Request。
- item_completed(results, items, info)
 当一个单独项目中的所有图片请求完成时, ImagesPipeline.item_completed() 方法将被调用。默认情况下, item_completed() 方法返回item。
- file_path(self, request, response=None, info=None)
 通过重写file_path方法,可以将图片以原来的格式和原图片名称进行保存。
 说明:我这里是爬取了网页中与图片对应的名字!
五、配置文件 settings.py
IMAGES_STORE ='images'#保存图片的路径,这里保存在项目里的images文件夹(自动创建)
ITEM_PIPELINES = {
    'image.pipelines.ImagePipeline': 300,  #开始pipelines
}
六、启动项目
scrapy crawl photo
我们就可以看到项目里多了一个images的文件夹
爬取图片的全过程就结束了!
当然你也可以爬取多页的图片
只需要修改pohot.py文件就可以了
import scrapy
from image.items import ImageItem
class PhotoSpider(scrapy.Spider):
    name = 'photo'
    allowed_domains = ['meishij.net']
    start_urls = ['https://www.meishij.net/china-food/caixi/qingzhencai/']
	page = 1
    def parse(self, response):
        item = ImageItem()
        image_urls = response.xpath('//*[@id="listtyle1_list"]/div/a/img/@src').extract()
        image_name = response.xpath('//*[@id="listtyle1_list"]/div/a/div/div/div[1]/strong/text()').extract()
        for i in range(0, len(image_name)):
            item['image_urls'] = image_urls[i]
            item['image_name'] = image_name[i]
            yield item
		self.page +=1
        if self.page<5:  #只爬前5页
            url="https://www.meishij.net/china-food/caixi/qingzhencai/?&page="+str(self.page)
            yield scrapy.Request(url,callback=self.parse)
运行项目
scrapy crawl photo
- 1


 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号