Scrapy下载.MPO格式图片报错PIL.UnidentifiedImageError,求解决方案
解决Scrapy下载MPO图片时PIL无法识别的问题
错误原因:Pillow原生不支持MPO(多图片对象)格式,而Scrapy的ImagesPipeline默认会调用Pillow打开下载的图片进行处理,因此触发PIL.UnidentifiedImageError。
以下是两种解决方案:
方案1:跳过MPO图片的Pillow处理,直接保存原始文件
如果仅需要下载保存MPO文件,不需要裁剪、格式转换等处理,可以自定义ImagesPipeline,对MPO格式文件直接保存,跳过Pillow解析步骤:
from scrapy.pipelines.images import ImagesPipeline import os class CustomImagesPipeline(ImagesPipeline): def get_images(self, response, request, info, item=None): # 判断请求URL是否以.mpo结尾 if response.url.lower().endswith('.mpo'): # 生成保存路径,保留原始文件名 path = self.file_path(request, response=response, info=info, item=item) # 返回路径、None(跳过Pillow处理)、原始文件内容 return [(path, None, response.body)] # 非MPO格式按原有逻辑处理 return super().get_images(response, request, info, item=item)
修改项目settings.py中的ITEM_PIPELINES,替换默认的图片管道:
ITEM_PIPELINES = { # 注释掉默认管道,启用自定义管道 # 'scrapy.pipelines.images.ImagesPipeline': 1, '你的项目名.pipelines.CustomImagesPipeline': 1, }
方案2:解析MPO提取图片后再处理
如果需要对MPO中的图片进行格式转换、裁剪等操作,先安装支持MPO解析的第三方库mpo:
pip install mpo
然后自定义管道解析MPO文件,提取其中的图片内容交给Pillow处理:
from scrapy.pipelines.images import ImagesPipeline import mpo from io import BytesIO import os class MPOImagesPipeline(ImagesPipeline): def get_images(self, response, request, info, item=None): if response.url.lower().endswith('.mpo'): # 解析MPO文件 mpo_obj = mpo.MPO(BytesIO(response.body)) # 遍历MPO中的所有图片(MPO可能包含多张图片) for img_idx, img_data in enumerate(mpo_obj.images): img_buffer = BytesIO(img_data) # 生成带序号的文件名,避免覆盖 base_name = os.path.splitext(os.path.basename(request.url))[0] save_path = f"{base_name}_{img_idx+1}.jpg" # 返回路径、Pillow图片对象、图片缓冲 yield (save_path, self._Image.open(img_buffer), img_buffer) else: # 非MPO格式按原有逻辑处理 yield from super().get_images(response, request, info, item=item)
同样在settings.py中替换默认管道为上述自定义管道即可。
内容的提问来源于stack exchange,提问作者user984621
相关产品推荐
相关产品推荐

