Python中requests库无法下载指定URL图片,浏览器却可以,原因何在?
解决requests.get爬取Mr Porter图片时挂起的问题
我之前处理过类似的电商网站爬取问题,这种情况基本都是网站的反爬机制在拦截你的请求——毕竟像Mr Porter这类平台会严格限制非浏览器的爬虫访问,保护自己的资源。
核心原因:请求标识被识别为爬虫
requests库默认发送的请求头里,User-Agent字段是类似python-requests/2.31.0这样的标识,网站的服务器一眼就能判断出这不是正常用户的浏览器请求,所以会故意卡住连接(甚至不返回任何响应),导致你的请求要么挂起,要么触发超时异常。而浏览器发送的请求会带上符合标准的User-Agent,所以能正常加载图片。
快速解决方法:模拟浏览器请求头
给requests.get添加浏览器风格的请求头,尤其是User-Agent字段,就能绕过这个基础反爬验证。这里给你一个可用的示例代码:
import numpy as np from PIL import Image import requests # 模拟Chrome浏览器的请求头 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', 'Accept': 'image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8' } try: response = requests.get( "https://cache.mrporter.com/images/products/908290/908290_mrp_in_l.jpg", headers=headers, timeout=5 ) response.raise_for_status() # 抛出HTTP状态码异常 # 保存并验证图片 with open("downloaded_image.jpg", "wb") as f: f.write(response.content) img = Image.open("downloaded_image.jpg") print(f"图片下载成功,尺寸:{img.size}") img.show() except requests.exceptions.RequestException as e: print(f"请求失败:{e}")
其他可能的排查方向
如果添加请求头后还是有问题,可以试试这两个方向:
- 会话保持:有些网站会在首次访问时设置Cookie,后续请求需要携带这些Cookie才能正常获取资源。可以用
requests.Session()来维持会话,自动处理Cookie。 - TLS协议版本:部分网站只支持特定版本的TLS协议,
requests默认的版本可能不匹配。你可以自定义适配器指定TLS版本(比如TLSv1.2),代码示例如下:
import requests from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager import ssl class TLS12Adapter(HTTPAdapter): def init_poolmanager(self, connections, maxsize, block=False): self.poolmanager = PoolManager( num_pools=connections, maxsize=maxsize, block=block, ssl_version=ssl.PROTOCOL_TLSv1_2 ) # 创建会话并挂载适配器 session = requests.Session() session.mount('https://', TLS12Adapter()) session.headers.update(headers) # 复用之前的headers response = session.get("https://cache.mrporter.com/images/products/908290/908290_mrp_in_l.jpg", timeout=5)
注意事项
这类电商网站的反爬规则会持续更新,建议不要频繁发送请求,尽量模拟正常用户的访问频率,避免IP被封禁。
内容的提问来源于stack exchange,提问作者London guy
相关产品推荐
相关产品推荐

