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

使用Python Socket仅返回响应头而非JS内容的问题求助

问题

我想要从网站的JS文件中提取链接,用Python的Socket模块获取该JS文件,但始终只拿到响应头,无法获取实际的JS内容。我的代码如下:

import socket
import ssl

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cont = ssl.create_default_context()
sock.connect(('blog.clova.line.me', 443))
sock = cont.wrap_socket(sock, server_hostname = 'blog.clova.line.me')
sock.sendall('GET /hs/hsstatic/HubspotToolsMenu/static-1.138/js/index.js HTTP/1.1\r\nHost: blog.clova.line.me\r\n\r\n'.encode())
resp = sock.recv(2048)
print(resp.decode('utf-8'))

返回内容只有响应头:

HTTP/1.1 200 OK
Date: Tue, 06 Sep 2022 12:02:38 GMT
Content-Type: application/javascript
Transfer-Encoding: chunked
Connection: keep-alive
CF-Ray: 74670e8b9b594c2f-SIN
Age: 3444278
...

我试过两种方法:

  • 设置Content-Type: text/plain; charset=utf-8请求头
  • 将请求头修改为GET https://blog.clova.line.me/hs/hsstatic/HubspotToolsMenu/static-1.138/js/index.js HTTP/1.1

别人用Socket能拿到响应头后的HTML/JS数据,但我不行。用requests模块却能正常获取内容:

resp = requests.get('https://blog.clova.line.me/hs/hsstatic/HubspotToolsMenu/static-1.138/js/index.js')
print(resp.text)

不想用第三方模块,怎么用原生Socket实现类似requests的效果?


解决方法

问题核心在于**分块传输编码(Transfer-Encoding: chunked)**和单次recv仅读取了部分数据。服务器返回的响应头标注了Transfer-Encoding: chunked,说明内容是分块返回的,而你只调用了一次recv(2048),只能拿到响应头和少量(或完全拿不到)正文数据。

要完整获取JS内容,需要:

  1. 循环调用recv直到接收完所有数据
  2. 解析分块编码的内容,拼接成完整的JS代码

修正后的代码如下:

import socket
import ssl

def parse_chunked_data(sock):
    full_data = b''
    while True:
        # 读取块大小(十六进制格式)
        chunk_size_line = b''
        while b'\r\n' not in chunk_size_line:
            chunk_size_line += sock.recv(1)
        chunk_size = int(chunk_size_line.strip(), 16)
        if chunk_size == 0:
            # 读取结束标记后的空行
            sock.recv(2)
            break
        # 读取对应大小的块内容
        chunk_content = b''
        while len(chunk_content) < chunk_size:
            chunk_content += sock.recv(chunk_size - len(chunk_content))
        full_data += chunk_content
        # 读取块末尾的换行符
        sock.recv(2)
    return full_data

# 建立SSL连接
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_context = ssl.create_default_context()
sock.connect(('blog.clova.line.me', 443))
sock = ssl_context.wrap_socket(sock, server_hostname='blog.clova.line.me')

# 发送HTTP请求,添加Connection: close让服务器主动关闭连接
request = (
    'GET /hs/hsstatic/HubspotToolsMenu/static-1.138/js/index.js HTTP/1.1\r\n'
    'Host: blog.clova.line.me\r\n'
    'Connection: close\r\n'
    '\r\n'
)
sock.sendall(request.encode())

# 循环接收全部响应数据
response = b''
while True:
    received_part = sock.recv(4096)
    if not received_part:
        break
    response += received_part

# 分离响应头和正文
header_separator = response.find(b'\r\n\r\n')
response_headers = response[:header_separator].decode('utf-8')
body_start = response[header_separator + 4:]

# 根据编码类型处理正文
if 'Transfer-Encoding: chunked' in response_headers:
    # 先处理已接收的分块数据,再读取剩余部分
    temp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    temp_sock = ssl_context.wrap_socket(temp_sock, server_hostname='blog.clova.line.me')
    temp_sock.connect(('blog.clova.line.me', 443))
    temp_sock.sendall(request.encode())
    # 跳过响应头
    while b'\r\n\r\n' not in temp_sock.recv(4096):
        pass
    js_content = parse_chunked_data(temp_sock).decode('utf-8')
    temp_sock.close()
else:
    js_content = body_start.decode('utf-8')

print(js_content)
sock.close()

关键细节说明:

  • 添加Connection: close请求头,让服务器发送完数据后主动关闭连接,便于判断接收结束
  • 循环调用recv直到没有数据返回,确保获取完整响应
  • 实现parse_chunked_data函数解析分块编码:先读取每个块的十六进制大小,再读取对应长度的内容,直到遇到大小为0的结束块
  • 分离响应头和正文,根据是否为分块编码选择对应的解析逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 22:40:42