使用file_get_contents请求SoccerWay API返回404错误排查
问题:PHP请求Soccerway API返回404,但浏览器访问正常
我尝试从Soccerway的一个API获取JSON响应,构建URL的PHP代码如下:
$currentDate = date("Y-m-d"); $timestamp = date("Y-m-d H:m:s"); $url = "https://int.soccerway.com/a/block_home_matches?block_id=block_home_matches_30&callback_params="; $url .= "{\"block_service_id\":\"home_index_block_homematches\",\"date\":\"". $currentDate ."\","; $url .= "\"display\":\"now_playing\",\"timestamp\":\"". $timestamp . "\"}"; $url .= "&action=filterContent&params="; $url .= "{\"display\":\"now_playing\"}";
执行请求的代码:
$html = file_get_contents($url); $json = json_decode($html);
返回错误:
failed to open stream: HTTP request failed! HTTP/1.0 404 Not Found
但直接在浏览器中粘贴该URL能得到正确响应,请问我哪里操作有误?
分析与解决方案
嘿,这个问题我之前帮朋友排查过类似的,主要是两个核心问题导致的:URL未正确编码和请求头缺失,咱们一步步来解决:
1. 修复URL编码问题
你现在是直接把JSON字符串硬拼进URL里,但浏览器会自动对URL中的特殊字符(比如{、}、双引号)做URL编码,而file_get_contents不会帮你做这件事。服务器收到未编码的参数后,可能无法正确解析你的请求,直接返回404。
另外你还有个小bug:日期格式化里的H:m:s写错了,分钟应该用i(H:i:s),不然分钟会显示成月份的数值,这也可能影响接口的有效性。
优化后的URL构建代码:
$currentDate = date("Y-m-d"); $timestamp = date("Y-m-d H:i:s"); // 修正分钟的格式化符 // 用json_encode生成JSON,避免手动拼接的错误 $callback_params = json_encode([ 'block_service_id' => 'home_index_block_homematches', 'date' => $currentDate, 'display' => 'now_playing', 'timestamp' => $timestamp ]); $params = json_encode([ 'display' => 'now_playing' ]); // 对JSON参数做URL编码 $url = "https://int.soccerway.com/a/block_home_matches?block_id=block_home_matches_30&callback_params=" . urlencode($callback_params); $url .= "&action=filterContent¶ms=" . urlencode($params);
2. 添加必要的请求头
浏览器访问接口时,会自动带上User-Agent、Referer等请求头,服务器会通过这些头判断请求是否来自合法的浏览器。而file_get_contents默认的请求头非常简单,很可能被服务器拦截,返回404。
我们可以用stream_context_create给请求添加模拟浏览器的头:
// 创建带请求头的上下文 $options = [ 'http' => [ 'header' => "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36\r\n" . "Referer: https://int.soccerway.com/\r\n" ] ]; $context = stream_context_create($options); // 带上上下文发起请求 $html = file_get_contents($url, false, $context); $json = json_decode($html);
额外小建议
如果上面的方法还是不行,推荐你用cURL库来发起请求,它对HTTP请求的控制更灵活,也更容易调试请求的细节(比如查看请求头、响应头),在处理这类反爬接口时更靠谱。
内容的提问来源于stack exchange,提问作者Charanoglu
相关产品推荐
相关产品推荐

