如何用socket模块获取HTTP请求原始内容并仅打印页面内容
仅提取Socket请求的响应内容(去除HTTP头和分块编码)
我来帮你搞定这个问题~你现在用socket发送请求后拿到的是完整的HTTP响应,里面包含了响应头、分块编码的长度标记,还有你要的目标内容。要只拿到test test1 test2 test3,得做两步处理:先把响应头和正文分开,再解析分块编码的正文内容。
问题原因
服务器返回的响应使用了分块编码(从响应头里的Transfer-Encoding: chunked能看出来),这种编码方式会把正文分成多个块,每个块前会标注块的长度(比如你看到的19),最后用0\r\n\r\n表示所有块结束。另外,HTTP响应的头和正文之间是用\r\n\r\n分隔的,这是拆分的关键。
解决代码
import socket def get_raw_content(host, path): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, 80)) # 发送标准的HTTP 1.1 GET请求,添加Connection: close确保服务器发送完就关闭连接 request = f"GET {path} HTTP/1.1\r\nHost: {host}\r\nConnection: close\r\n\r\n" sock.sendall(request.encode("utf-8")) # 循环接收完整响应(单次recv可能无法获取全部内容) full_response = b"" while True: data = sock.recv(4096) if not data: break full_response += data sock.close() # 拆分响应头和正文部分 header_end = full_response.find(b"\r\n\r\n") body = full_response[header_end+4:] # 解析分块编码的正文内容 decoded_body = b"" remaining = body while remaining: # 定位块长度的结束标记 chunk_len_end = remaining.find(b"\r\n") if chunk_len_end == -1: break # 将十六进制的块长度转为十进制 chunk_len = int(remaining[:chunk_len_end], 16) if chunk_len == 0: break # 提取当前块的内容 chunk = remaining[chunk_len_end+2 : chunk_len_end+2+chunk_len] decoded_body += chunk # 跳过块内容后的换行标记,处理下一个块 remaining = remaining[chunk_len_end+2+chunk_len+2:] return decoded_body.decode("utf-8") # 调用函数获取目标内容 content = get_raw_content("pastebin.com", "/raw/yWmuKZyb") print(content)
代码说明
- 添加
Connection: close请求头,让服务器发送完响应后直接关闭连接,这样我们能确保接收到完整的响应数据。 - 循环调用
recv直到没有数据返回,避免单次接收遗漏部分内容。 - 用
b"\r\n\r\n"精准拆分响应头和正文,只处理我们需要的正文部分。 - 逐块解析分块编码内容:读取每个块的长度,提取对应内容,直到遇到标记结束的0长度块。
运行这段代码后,就能直接输出你想要的test test1 test2 test3啦~
内容的提问来源于stack exchange,提问作者God Himself
相关产品推荐
相关产品推荐

