Scrapy用ImagePipeline爬取网页图片

  之前的那个系列文章只是讲到了如何使用Scrapy来爬取文本数据,今天我们来介绍如何用Scrapy来爬取图片数据。

Scrapy爬取图片数据需要用到ImagePipeline这个类,此类提供一种方便的方式来下载和存储图片,待会大家看例子的时候就可以看到爬取图片要比爬取文本简单的多,这当然要归功于ImagePipeline这个类。

这个类的主要特征如下:

  • 将下载图片转换成通用的JPG和RGB文件格式
  • 避免重复下载
  • 可以生成缩略图
  • 图片大小可以实现自动过滤
下面我们来看一下ImagePipeline的工作流程
  • 爬取一个item,将图片的urls存入image_urls字段
  • 从Spider返回的item,传递到Item Pipeline,
当Item传递到ImagePipeline后,将调用Scrapy调度器和下载器完成image_urls中的URL的调度和下载。ImagePipeline会自动高优先级抓取这些url,与此同时,item会被锁定直到图片抓取完毕才解锁。
  • 这些图片下载完成后,图片下载路径、url和校验等信息会被填充到images字段中。
好了,让我们赶紧开始吧。
启动一个项目,项目名称为douban_img
scrapy startproject douban_img
首先我们来看items.py
# -*- coding: utf-8 -*-

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

import scrapy


class DoubanImgItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    image_urls = scrapy.Field()
    image_paths = scrapy.Field()
爬取图片一定需要image_urls这个字段,否则无法完成图片的抓取。
接下看最主要的spider文件,新建一个文件download_douban.py。
from scrapy.spider import Spider
import re
from scrapy import Request 
from douban_img.items import DoubanImgItem


class download_douban(Spider):
		name = 'download-douban'

		default_headers = {
			'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
			'Accept' : 'gzip, deflate, sdch, br',
			'Accept-Language'	: 'zh-CN,zh;q=0.8,en;q=0.6',
			'Cache-Control' : 'max-age=0',
			'Connection' : 'keep-alive',
			'Host' : 'www.douban.com',
			'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
		}

		def __init__(self, url='1656889999', *args, **kwargs):
			self.allowed_domains = ['douban.com']
			self.start_urls = ['https://www.douban.com/photos/album/%s/' % (url)]
			# self.url = url

		def start_requests(self):
			for url in self.start_urls:
				yield Request(url = url, headers = self.default_headers, callback = self.parse) 

		def parse(self, response):
			list_imgs = response.xpath('//div[@class="photolst clearfix"]//img/@src').extract()#注意这里不能再使用extract()[0]
			# print (list_imgs)
			if list_imgs:
				item = DoubanImgItem()
				item['image_urls'] = list_imgs
				yield item
这里一开始还是引包,看过我之前scrapy系列文章的朋友这里应该很熟悉了。接下来定义一个类download_douban,在里面定义我们的爬虫名称,以及开始爬虫的urls。这里建立了一个default_headers,由于我们只是爬取几张图片,因此简单伪装一下即可,并不需要登录。在parse解析函数中,最主要的就是把得到图片的urls传入item的image_urls字段。这里需要提醒一下大家,ImagePipeline要求['image_urls']字段必须是一个列表,就算只有一个url,也必须是一个列表,因此这里使用extract()而不是extract().[0],我在这里卡了好长时间。
接下来看pipelines.py文件
# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
from scrapy import Request
from scrapy import log

class DoubanImgPipeline(object):
    def process_item(self, item, spider):
        return item

class DoubanDownImgloadPipeline(ImagesPipeline):
	"""docstring for DoubanDownloadPipeline"""
	default_headers = {
		'accept' : 'image/webp,image/*,*/*;q=0.8',
		'accept-encoding' : 'gzip, deflate, sdch, br',
		'accept-language' : 'zh-CN,zh;q=0.8,en;q=0.6',
		'cookie' : 'bid=yQdC/AzTaCw',
		'referer' : 'https://www.douban.com/photos/photo/2370443040/',
		'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
	}
		
	def get_media_requests(self, item, info):
		for image_url in item['image_urls']:
			self.default_headers['referer'] = image_url
			yield Request(image_url, headers = self.default_headers)

	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")
		item['image_paths'] = image_paths
		return item
在这个py文件中,我们定义了DoubanDownImgloadPipeline这个类,这个类继承于ImagesPipeline。在这里定义了两个函数,一个是根据传入的urls来发起请求,请求完成后直接调用item_completed函数来处理得到的图片。get_media_requests函数中,发起请求的时候,不需要指定回调函数,ImagePipeline会自动调用item_completed函数来处理。
最后我们看一个settings.py文件,对该项目进行一些配置。
首先还是配置一个User-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
使用我们自己定义的pipeline
ITEM_PIPELINES = {
   'douban_img.pipelines.DoubanDownImgloadPipeline': 300,
}
设置图片存放的目录以及有效期
IMAGES_STORE = 'D:\\doubanimgs'

IMAGES_EXPIRES = 90
配置结束后保存,返回到命令行运行一下
scrapy crawl download-douban
下面是运行结果截图
Scrapy用ImagePipeline爬取网页图片_第1张图片
这个程序比较简单,我们只是抓取了某个相册中第一页的图片,有兴趣的朋友可以试试把该相册中的所有图片都抓取下来,可以用到上一篇文章提到的结构,当然这种情况就需要登录豆瓣了。
好了,以上就是今天的全部内容。
与您共勉!
 
    
   












你可能感兴趣的:(爬虫)