Scrapy爬取图片

Scrapy爬取图片

简介

Scrapy用ImagesPipeline类提供一种方便的方式来下载和存储图片,包括以下要点

  • 需要PIL库支持
  • 将下载图片转换成通用的JPG和RGB格式
  • 避免重复下载
  • 缩略图生成
  • 图片大小过滤

前面已经介绍过scrapy的流程,这里主要分为以下几步:

  • 在spider中爬取一个Item,将图片的URLs放入image_urls 字段
  • 在pipeline中重载get_media_requestsitem_completed函数调用Scrapy 调度器和下载器完成urls包含图片的下载
  • 下载成功结束后,图片下载路径、url和校验和等信息会被填充到images字段中

爬取代码

  • 在spider.py中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import scrapy
from scrapy import Request
from DoubanBookSpider.items import DoubanImageItem

class ImageSpider(scrapy.Spider):
name = 'download_image'

default_headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding': '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 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
}

def __init__(self, url='1638835355', *args, **kwargs):
super().__init__(**kwargs)
self.allowed_domains = ['douban.com']
self.start_urls = [
'http://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()
if list_imgs:
item = DoubanImageItem()
item['image_urls'] = list_imgs
yield item
  • 在items.py中配置字段
1
2
3
4
class DoubanImageItem(scrapy.Item):
image_urls = scrapy.Field()
images = scrapy.Field()
image_paths = scrapy.Field()
  • 主要任务放在了pipelines.py中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
from scrapy import Request

class DoubanImgDownloadPipeline(ImagesPipeline):
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 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
}
# 重载函数
# 发送下载请求,结束后 传递返回值给item_completed()
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
  • 在settings.py中加入配置
1
2
3
4
5
6
7
8
ITEM_PIPELINES = {
'DoubanBookSpider.pipelines.MyImagesPipeline':300 # 这个名字要和pipeline中一致
}

IMAGES_STORE = 'E:\\PyCharm\\scrapyDemo\\imgs'
IMAGES_EXPIRES = 90 # 过期天数
IMAGES_MIN_HEIGHT = 100
IMAGES_MIN_WIDTH = 100 # 图片尺寸限制

可以发现,大部分的细节实现scrapy已经封装好了,这更像是一个调用模板,我们只需要根据自己的要求做一些配置即可!

如果你没有运行成功这些代码,可能是网络的问题,或者是反爬机制的问题,亦可能是框架的更新!由于反爬技术的升级,如果你想爬取自己喜欢的数据还是需要花很多功夫的。

------ ���Ľ���------