求助:Python实现仅支持文本不加载图片的Web代理问题修复
修复你的Web代理服务器:拦截图片资源并正确转发文本请求
看起来你的代理目前有几个关键问题导致图片请求处理异常,同时也没实现拦截图片的核心需求。咱们一步步来修复:
首先分析现有代码的问题
- 变量名错误:
CLIENT.accept()应该是client.accept()(你定义的socket对象是小写的client),这个错误会直接导致代理无法接受连接。 - 硬编码目标主机:所有GET请求都被转发到
images.mid-day.com,这意味着像gaia.cs.umass.edu的文本请求也会被错误发送到图片服务器,你测试时能看到文本大概率是浏览器缓存的原因。 - 未实现图片拦截逻辑:代码完全没有判断请求的资源类型,自然无法阻止图片加载。
- 异常处理过于宽泛:
except:会掩盖所有错误,比如连接失败、解析错误等,不利于排查问题。
修复后的代码实现
下面是修改后的代码,实现了解析请求目标主机、拦截图片资源、正确转发文本请求的功能:
from socket import * import re def is_image_request(request): # 匹配常见图片后缀的请求路径 image_pattern = re.compile(r'\.(jpg|jpeg|png|gif|bmp|webp)$', re.IGNORECASE) lines = request.split('\n') if lines: first_line = lines[0].strip() if first_line.startswith('GET'): path = first_line.split(' ')[1] return image_pattern.search(path) is not None return False def get_host_from_request(request): # 从请求头中提取Host字段 lines = request.split('\n') for line in lines: if line.strip().lower().startswith('host:'): return line.strip().split(':', 1)[1].strip() # 如果没有Host字段,尝试从请求路径解析(兼容HTTP/1.0) first_line = lines[0].strip() if first_line.startswith('GET'): url_parts = first_line.split(' ')[1].split('/') if len(url_parts) >= 3: return url_parts[2] return None proxy_port = 8880 server_socket = socket(AF_INET, SOCK_STREAM) server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # 允许端口复用,避免重启报错 server_socket.bind(("", proxy_port )) server_socket.listen(10) print(f"代理服务器已启动,监听端口 {proxy_port}...") while True: client_connection, client_address = server_socket.accept() print(f"接收到来自 {client_address} 的连接") try: request = client_connection.recv(102400).decode('utf-8', errors='ignore') if not request: client_connection.close() continue if request.startswith("GET"): # 检查是否是图片请求,如果是则返回403拒绝 if is_image_request(request): print("拦截图片请求") response = "HTTP/1.1 403 Forbidden\r\nContent-Length: 0\r\n\r\n" client_connection.send(response.encode()) client_connection.close() continue # 解析目标主机 host = get_host_from_request(request) if not host: print("无法解析请求的主机") client_connection.close() continue # 连接目标服务器并转发请求 web_socket = socket(AF_INET, SOCK_STREAM) web_socket.connect((host, 80)) web_socket.send(request.encode()) # 循环接收服务器响应,确保完整转发给客户端 while True: reply = web_socket.recv(102400) if not reply: break client_connection.send(reply) web_socket.close() client_connection.close() except Exception as e: print(f"处理请求时出错: {str(e)}") client_connection.close() server_socket.close()
关键修改说明
- 变量名修正:把错误的
CLIENT.accept()改成server_socket.accept()(同时将socket对象重命名为server_socket,语义更清晰)。 - 图片拦截逻辑:新增
is_image_request函数,通过正则匹配请求路径中的图片后缀,匹配到则返回403拒绝请求,直接阻止图片加载。 - 动态解析目标主机:新增
get_host_from_request函数,从请求头的Host字段提取目标主机,确保不同的请求转发到对应的服务器,不再硬编码固定主机。 - 完整响应转发:循环接收服务器的响应数据,避免大响应被截断,保证文本内容完整显示。
- 精准异常处理:捕获具体
Exception并打印错误信息,方便排查连接、解析等环节的问题。 - 端口复用设置:添加
setsockopt(SOL_SOCKET, SO_REUSEADDR, 1),避免重启代理时出现端口被占用的错误。
测试验证
- 启动代理服务器,在Chrome中设置代理为
127.0.0.1:8880。 - 访问
http://gaia.cs.umass.edu/wireshark-labs/HTTP-wireshark-file1.html,应该能正常显示文本内容。 - 访问
http://images.mid-day.com/images/2017/feb/15-salman-khan.jpg,浏览器会显示403禁止访问,图片无法加载,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Deo
相关产品推荐
相关产品推荐

