Scrapy Images Pipeline处理特定链接出现File Not Found错误求助
问题原因
- 文件名长度超出系统限制:本次报错对应的商品名称本身长度已经超过200字符,叠加你拼接的多段随机数后缀后,总路径长度超出Windows系统默认的260字符路径长度限制,系统无法创建对应路径的文件,因此抛出
FileNotFoundError。 - 路径拼接不规范:代码中手动拼接文件路径时混用了正反斜杠,从报错信息中的
images/full\\可以看出跨系统路径适配有问题,也会导致路径识别失败。 - 逻辑漏洞:当判断目标文件已存在时,你给
path_img赋值的路径缺失.png后缀,也会导致后续文件读写逻辑异常。
解决方案
1. 新增文件名预处理逻辑
清理文件名中的系统非法字符,同时限制文件名最大长度,避免路径超限:
import re from pathlib import Path def clean_filename(filename, max_len=100): # 替换Windows系统非法文件名符号 filename = re.sub(r'[\\/:*?"<>|]', '_', filename) # 截断过长的文件名,预留后缀和随机数的长度空间 if len(filename) > max_len: filename = filename[:max_len].rstrip('. ') return filename
2. 修正图片管道代码
使用Path统一处理路径拼接,修正文件存在判断的逻辑漏洞:
class MyImagesPipeline(ImagesPipeline): def get_media_requests(self, item, info): for image_url in item['image_urls']: # 提前预处理文件名 clean_name = clean_filename(item["image_names"]) yield scrapy.Request(image_url, meta={'image_names': clean_name}) def image_downloaded(self, response, request, info): checksum = None image_name = response.meta['image_names'] for path, image, buf in self.get_images(response, request, info): if checksum is None: buf.seek(0) checksum = md5sum(buf) width, height = image.size # 用Path处理路径,避免斜杠混用 base_dir = Path("images") / "full" # 先判断基础名称的文件是否存在 exist_file = base_dir / f"{image_name}.png" if exist_file.exists(): # 存在就用随机后缀拼接 random_suffix = ''.join([str(random.randint(1,10000)) for _ in range(5)]) path_img = base_dir / f"{image_name}_{random_suffix}.png" else: path_img = base_dir / f"{image_name}.png" self.store.persist_file( path_img.as_posix(), buf, info, meta={'width': width, 'height': height}, headers={'Content-Type': 'image/png'} ) return checksum
3. 可选配置(Windows系统)
如果确实需要使用超长路径,可以开启Windows的长路径支持:按下Win+R输入regedit打开注册表,定位到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem,将LongPathsEnabled的值修改为1,重启系统后生效。
内容的提问来源于stack exchange,提问作者Ibtsam Ahmad
相关产品推荐
相关产品推荐

