You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用requests拉取PNG图片时遇UnidentifiedImageError,求有效解决方法

解决requests拉取PNG时的UnidentifiedImageError问题

问题重现

使用requests拉取网页PNG图片时触发UnidentifiedImageError,无法识别损坏、截断类异常图片,且不想通过try语句直接跳过问题文件。

报错详情

UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x7fa8aca13ef0>

报错栈:

Traceback:
File "/home/user/.conda/envs/my_env/lib/python3.8/site-packages/streamlit/script_runner.py", line 333, in _run_script
    exec(code, module.__dict__)
File "/home/user/app/app.py", line 463, in <module>
    img_details, message, title, invalid_file_paths, dates_df = pull_imgs(url=url, user=user, password=password, input_dir=input_dir)
File "/home/user/app/app.py", line 229, in pull_imgs
    img = Image.open(img_bytes)
File "/home/user/.conda/envs/my_env/lib/python3.8/site-packages/PIL/Image.py", line 3023, in open
    raise UnidentifiedImageError(

问题代码片段

for photo in valid_file_paths:

    # PULL PHOTO
    response = requests.get(photo[0], auth=(user, password), stream=True)
    
    # FILENAME
    file = extract_file(photo[0])[1]
    ext = photo[1]
    filename = file + '.' + ext
    
    img_bytes = io.BytesIO(response.content)                
    img = Image.open(img_bytes)
    img.save(os.path.join(input_dir, filename), format=ext, optimize=True)

解决方案

1. 开启PIL的截断图片加载支持

PIL默认拒绝加载截断图片,可通过全局参数强制开启兼容:

from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True

# 之后再执行原代码的Image.open操作

2. 验证响应完整性,避免拉取不完整图片

在处理响应前,先校验请求状态和内容长度,排除因网络问题导致的截断:

response = requests.get(photo[0], auth=(user, password), stream=True)
response.raise_for_status()  # 确保请求返回成功状态码(200-399)

# 校验内容长度匹配
if 'Content-Length' in response.headers:
    expected_len = int(response.headers['Content-Length'])
    actual_len = len(response.content)
    if actual_len != expected_len:
        print(f"图片 {photo[0]} 拉取不完整:预期{expected_len}字节,实际{actual_len}字节")
        # 可在此添加重新请求逻辑,或标记后手动处理

3. 使用更健壮的图片解码库

用pyspng兼容损坏PNG

pyspng对损坏、截断的PNG文件兼容性更强,安装后替换解码逻辑:

pip install pyspng
import pyspng
import numpy as np
from PIL import Image

# 直接解码响应字节
img_data = pyspng.load(response.content)
# 转换为PIL Image对象
img = Image.fromarray(np.array(img_data))

用imageio尝试多后端解码

imageio会自动调用多种解码后端,提升异常图片的识别率:

pip install imageio
import imageio
from PIL import Image

# 读取图片并转换为PIL格式
img_array = imageio.imread(response.content)
img = Image.fromarray(img_array)

4. 手动修复PNG文件头

如果是文件头损坏,可补全标准PNG文件头后再尝试解码:

import io
from PIL import Image

standard_png_header = b'\x89PNG\r\n\x1a\n'
img_content = response.content

if not img_content.startswith(standard_png_header):
    # 补全标准文件头
    fixed_content = standard_png_header + img_content
    img_bytes = io.BytesIO(fixed_content)
    img = Image.open(img_bytes)

5. 借助命令行工具修复复杂损坏

使用pngfix工具修复严重损坏的PNG文件,适合处理复杂异常:

# Ubuntu/Debian安装pngfix
sudo apt install pngfix
import subprocess
import tempfile
import os

# 保存原始字节到临时文件
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp_file:
    tmp_file.write(response.content)
    tmp_path = tmp_file.name

# 执行修复命令
subprocess.run(['pngfix', tmp_path], check=True)
# 读取修复后的文件
img = Image.open(tmp_path)
# 保存到目标路径后清理临时文件
img.save(os.path.join(input_dir, filename), format=ext, optimize=True)
os.unlink(tmp_path)

内容的提问来源于stack exchange,提问作者sar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 05:15:27