您的位置:首页 > 其它

Windows下Scrapy下载图片,指定图片名报错[WinError32]的解决办法

2017-08-23 20:38 309 查看

问题描述

在学习使用scrapy爬虫框架的时候,我根据一个网上的demo,编写了一个爬取某网站主播头像的spider,并希望爬取的图片以主播的名字来命名。

存储图片的思路是使用scrapy自带的
ImagesPipeline
类下载图片,通过重写
get_media_request()
方法和
item_completed()
方法,来实现下载、保存图片后再重命名的流程。

代码如下:

class ImagePipeline(ImagesPipeline):  # 自定义一个图片下载类
IMAGES_STORE = get_project_settings().get('IMAGES_STORE')

# 将要下载的图片url创建请求提交给引擎
def get_media_requests(self, item, info):
# 一个item只下载一张图片
yield scrapy.Request(item['image_link'])

def item_completed(self, results, item, info):
"""
当一个单独项目中的所有图片请求完成时(要么完成下载,要么因为某种原因下载失败),该方法将被调用。
"""
# 获取图片的下载路径,使用了列表生成式
image = [data['path'] for ok, data in results if ok]  # 一个元组就没有括号了
#              ↑ 这个path指的是result中的key
# 拼接原始图片的路径
old_name = self.IMAGES_STORE + os.sep + image[0]
# 拼接新的路径
new_name = self.IMAGES_STORE + os.sep + image[0].split(os.sep)[0] + os.sep + item['nick_name'] + '.jpg'
os.rename(old_name, new_name)
item['image_path'] = new_name
return item


整段代码在Linux中运行无问题,然而在Windows环境下出现了错误:

Traceback (most recent call last):
File "f:\python\python36\lib\site-packages\twisted\internet\defer.py", line 653, in _runCallbacks
current.result = callback(current.result, *args, **kw)
File "D:\MyProjects\pipelines.py", line 53, in item_completed
os.rename(old_name, new_name)
PermissionError: [WinError 32] 另一个程序正在使用此文件,进程无法访问。: 'D:\\MyProjects\\img_cach\\full/d8c779ea0c9a7a03a09ab05151796977ac5fc738.jpg' -> 'D:\\MyProjects\\img_cach\\full/d8c779ea0c9a7a03a09ab05151796977ac5fc738.jpg\\熙珍爱吃肉.jpg'


bug原因推测是
os.rename
时图片仍未
close()
,Windows不允许两个进程去操作同一个文件。

解决办法

因系统和框架的限制,“先下载好图片在重命名”的思路走不通(或者说屏我的半瓶水走不通了【囧】),那么在保存图片时就设定好图片名即可。

即重写
file_path()
方法。代码如下

class ImagePipeline(ImagesPipeline):
IMAGES_STORE = get_project_settings().get('IMAGES_STORE')

# 将要下载的图片url创建请求提交给引擎
def get_media_requests(self, item, info):
yield scrapy.Request(item['image_link'], meta={"item": item, 'pic_name': item['nick_name']})

def file_path(self, request, response=None, info=None):
"""
重写图片的存储路径。
:param request:
:param response:
:param info:
:return: 字符串形式的文件存储路径,相对于 IMAGES_STORE 的相对路径
"""
pic_name = request.meta['pic_name']
pic_path = pic_name + '.jpg'
return pic_path


这次涉及的三个方法,其调用顺序应为:

get_media_request()




file_path()




item_completed()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐