WEBP图片下载后显示异常问题:原因分析与修复方案
问题描述
我的代码如下:
# Extract the images images = product_soup.find_all('div', class_='woocommerce-product-gallery__image') for i, image in enumerate(images): img_src = image.find('img')['src'] print(img_src) # Download the image img_r = r.get(img_src, stream=True) # Save the image with the title and a number as the file name with open(f'{title}_{i}.jpg', 'wb') as f: for chunk in img_r: f.write(chunk)
运行后部分图片无法正常显示,观察发现这些图片实际为WEBP格式,但手动保存为JPG格式可正常显示。
问题原因
- 直接将WEBP格式的二进制数据保存为
.jpg后缀文件,文件实际格式与后缀名不匹配,部分图片查看器或系统无法自动识别这种不匹配的文件,导致显示异常。 - 部分网站会根据请求头返回更优格式(如WEBP以节省带宽),你的请求未指定接受的图片格式,因此拿到WEBP数据却按JPG保存,引发兼容性问题。
修复方案
方案1:根据真实格式命名文件
通过响应头获取图片实际格式,对应命名文件:
# Extract the images images = product_soup.find_all('div', class_='woocommerce-product-gallery__image') for i, image in enumerate(images): img_src = image.find('img')['src'] print(img_src) # Download the image img_r = r.get(img_src, stream=True) img_r.raise_for_status() # 确保请求成功 # 从响应头获取图片格式 content_type = img_r.headers.get('Content-Type') if content_type == 'image/webp': ext = 'webp' elif content_type == 'image/jpeg': ext = 'jpg' elif content_type == 'image/png': ext = 'png' else: # 从URL提取后缀作为备选 ext = img_src.split('.')[-1].split('?')[0] # 按真实格式保存文件 with open(f'{title}_{i}.{ext}', 'wb') as f: for chunk in img_r: f.write(chunk)
方案2:将WEBP转换为JPG保存
使用PIL库(需先执行pip install pillow安装)将WEBP格式转换为JPG后保存:
from PIL import Image import io # Extract the images images = product_soup.find_all('div', class_='woocommerce-product-gallery__image') for i, image in enumerate(images): img_src = image.find('img')['src'] print(img_src) # Download the image img_r = r.get(img_src, stream=True) img_r.raise_for_status() # 读取并转换图片 img_data = io.BytesIO(img_r.content) try: img = Image.open(img_data) # WEBP格式需转RGB才能保存为JPG if img.format == 'WEBP': img = img.convert('RGB') img.save(f'{title}_{i}.jpg', 'JPEG') except Exception as e: print(f"处理图片{i}失败: {e}")
额外优化:请求时指定优先获取JPG
在请求头中添加Accept字段,让服务器优先返回JPG格式:
headers = { 'Accept': 'image/jpeg, image/png' } img_r = r.get(img_src, headers=headers, stream=True)
内容的提问来源于stack exchange,提问作者Rayly Esta
相关产品推荐
相关产品推荐

