PHP用do-while循环分页调用限次EIA API获取全量数据的问题排查
EIA API 分页拉取全量数据修复方案
问题核心错误点
代码存在5处逻辑错误,导致无法拉取全量数据甚至触发超时:
- URL参数写死:初始定义
$url时PHP就会把当时的$offset=0、$length=5000替换进字符串,后续循环里修改offset不会更新URL里的参数,相当于每次都请求第一页
- URL参数写死:初始定义
- 总数字段读取错误:根据返回结构,总条数字段路径是
$response->response->total,原代码读的$response->total是不存在的字段,拿到的值为空
- 总数字段读取错误:根据返回结构,总条数字段路径是
- offset计算规则完全错误:EIA API的offset参数含义是「跳过前N条记录」,第一页取0-4999条,第二页应该从offset=5000开始取,原代码用总条数减单页长度算offset,第一次循环就算出错误值,直接导致后续请求返回空
- 循环终止条件无效:原条件
$offset == $received逻辑不成立,第一次循环结束就会直接退出,根本不会触发第二次请求
- 循环终止条件无效:原条件
- 无异常兜底逻辑:没有判断接口请求失败、返回空数据的场景,很容易进入死循环导致请求超时
修正后代码
$offset = 0; $length = 5000; $allData = []; $apiKey = 'xxxxxxxxxx'; // 替换为你的实际API Key $ch = curl_init(); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 设置30秒请求超时,避免长时间挂起 do { // 每次循环动态拼接URL,保证offset为最新值 $url = "https://api.eia.gov/v2/international/data/v2/data?api_key={$apiKey}&start=1960&sort[0][direction]=desc&offset={$offset}&length={$length}"; curl_setopt($ch, CURLOPT_URL, $url); $jsonData = curl_exec($ch); // 请求失败直接终止 if ($jsonData === false) break; $response = json_decode($jsonData); // 返回结构不符合预期直接终止 if (!isset($response->response->total, $response->response->data)) break; $total = (int)$response->response->total; $currentPage = $response->response->data; // 当前页无数据直接终止 if (empty($currentPage)) break; // 合并当前页数据到全量数组 $allData = array_merge($allData, $currentPage); // 偏移量累加单页长度,准备请求下一页 $offset += $length; // 已拉取数据量小于总条数时继续循环 } while (count($allData) < $total); curl_close($ch);
逻辑说明
- 针对总条数9517的场景,代码会发起2次请求:第一次offset=0拉取前5000条,第二次offset=5000拉取剩余4517条,拉取完成后自动终止
- 多层异常判断可以避免接口异常时进入死循环,解决之前设置宽松终止条件导致的超时问题
- 不需要额外遍历当前页数据,直接合并接口返回的data数组即可,执行效率更高
- 最后得到的
$allData数组就是完整的全量数据
内容的提问来源于stack exchange,提问作者S.I.
相关产品推荐
相关产品推荐

