Python http.client response.read().decode()空串及全量响应获取问题
问题修复方案
1. 第二次调用read()返回空字符串的原因
http.client的响应对象是基于字节流实现的,read()方法会从当前流指针位置开始读取剩余所有内容,读完之后指针直接移动到流的末尾:
- 第一次执行
print(response.read())时,已经把响应里的所有字节都读完了 - 第二次再调用
response.read(),流里已经没有剩余内容,自然返回空字节,decode之后就是空字符串
修复方法非常直接:只调用一次read(),把读取到的字节内容存到变量里,后续所有解码、解析操作都基于这个变量处理,不要重复调用响应对象的read()方法。
2. 仅返回20条结果、拉取全量数据的方法
这个接口默认采用分页返回机制,不会一次性把2万多条匹配结果全部返回,默认单页大小就是20条。要拿全量数据需要按接口规则循环传分页参数拉取:
- 接口支持在POST请求体中传入
page(页码,从1开始计数)、pageSize(单页返回条数)两个分页参数 - 第一页请求返回结果中会携带总匹配条数字段,根据总条数计算总页数后逐页拉取,把每页的结果拼接起来就是全量数据
- 拉取过程中建议加小幅延时,避免请求过频被接口拦截
修复后单次请求正确读取响应的示例代码
import http.client import json host = 'jooble.org' key = 'API_KEY' connection = http.client.HTTPConnection(host) headers = {"Content-type": "application/json"} # 不要手动拼接JSON字符串,用json.dumps生成避免转义错误 body = json.dumps({ "keywords": "sales", "location": "MA" }) connection.request('POST', f'/api/{key}', body, headers) response = connection.getresponse() print(response.status, response.reason) # 只读一次,内容存入变量 raw_response = response.read() # 后续解码、解析都用这个变量 json_result = json.loads(raw_response.decode('utf-8')) print(json_result) connection.close()
全量拉取所有结果的示例代码
import http.client import json import time host = 'jooble.org' key = 'API_KEY' # 单页拉取条数,可根据接口限制调整,不要设置过大避免超时 SINGLE_PAGE_SIZE = 100 all_result = [] conn = http.client.HTTPConnection(host) headers = {"Content-type": "application/json"} # 拉取第一页,获取总结果数 first_page_body = json.dumps({ "keywords": "sales", "location": "MA", "page": 1, "pageSize": SINGLE_PAGE_SIZE }) conn.request('POST', f'/api/{key}', first_page_body, headers) first_resp = conn.getresponse() first_page_data = json.loads(first_resp.read().decode('utf-8')) first_resp.close() total_count = first_page_data.get('totalCount', 0) all_result.extend(first_page_data.get('jobs', [])) print(f"总匹配结果共{total_count}条,已拉取第1页,当前累计获取{len(all_result)}条") # 计算总页数,逐页拉取剩余内容 total_page = (total_count + SINGLE_PAGE_SIZE - 1) // SINGLE_PAGE_SIZE for page_num in range(2, total_page + 1): page_body = json.dumps({ "keywords": "sales", "location": "MA", "page": page_num, "pageSize": SINGLE_PAGE_SIZE }) conn.request('POST', f'/api/{key}', page_body, headers) page_resp = conn.getresponse() page_data = json.loads(page_resp.read().decode('utf-8')) page_resp.close() all_result.extend(page_data.get('jobs', [])) print(f"已拉取第{page_num}页,当前累计获取{len(all_result)}条") # 加0.5秒延时,避免触发接口频率限制 time.sleep(0.5) conn.close() print(f"全量拉取完成,共获取{len(all_result)}条结果") # 需要完整JSON字符串直接序列化全量结果即可 full_json_string = json.dumps(all_result, ensure_ascii=False)
注意事项
- 生成JSON请求体不要手动拼接字符串,用标准库
json.dumps()方法自动处理转义,避免格式错误 - 复用HTTP连接发起多次请求时,每次读取完响应内容要调用
close()方法释放连接,否则下一次请求可能抛出异常 - 如果拉取过程中出现429状态码(请求过频),可以适当调大延时时间、调小单页拉取条数
内容的提问来源于stack exchange,提问作者Mohammad Haris
相关产品推荐
相关产品推荐

