


























话题虽然是关于 AI 的,但解决的问题还是关于订阅。
我这个订阅功能是基于一个开源的rssphp 库而写出来的,时至今日个人感觉基本趋于稳定,可唯独因为不能读取品味苏州的订阅算是一个小小的遗憾。而且,我苦这个问题久矣!
晚上,我将代码进行了一下复盘,问题回到这个库上面,然后通过设置一个一个的校验代码,最终将问题定位到了下面这个函数
private static function httpRequest($url, $user, $pass)
{
if (extension_loaded('curl')) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
if ($user !== null || $pass !== null) {
curl_setopt($curl, CURLOPT_USERPWD, "$user:$pass");
}
curl_setopt($curl, CURLOPT_USERAGENT, self::$userAgent); // some feeds require a user agent
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_TIMEOUT, 20);
curl_setopt($curl, CURLOPT_ENCODING, '');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // no echo, just return result
curl_setopt($curl, CURLOPT_USERAGENT, '');
if (!ini_get('open_basedir')) {
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); // sometime is useful :)
}
$result = curl_exec($curl);
return curl_errno($curl) === 0 && curl_getinfo($curl, CURLINFO_HTTP_CODE) === 200
? $result
: false;
} else {
$context = null;
if ($user !== null && $pass !== null) {
$options = [
'http' => [
'method' => 'GET',
'header' => 'Authorization: Basic ' . base64_encode($user . ':' . $pass) . "\r\n",
],
];
$context = stream_context_create($options);
}
return file_get_contents($url, false, $context);
}
}看着这眼花缭乱的条件,我短路了,怎么办?于是也效仿大家,用腾讯元宝进行了提问:“请检查函数有没有错误”
元宝经过一番深度思考(就不贴出来了),然后给出了回复。
该函数存在几个潜在问题,以下是主要错误及改进建议:
1.重复设置 User-Agent
cURL 部分两次设置 CURLOPT_USERAGENT,第二次覆盖为空字符串,导致 User-Agent 头被清空。
修复: 移除第二个 curl_setopt($curl, CURLOPT_USERAGENT, '');。
2.HTTP 认证条件不一致
修复: 统一条件为两者均非空(&&),确保认证正确性。
3.HTTP 状态码检查过严
cURL 仅接受 200 状态码,忽略了其他成功状态(如 201、204)。
修复: 检查状态码是否为 2xx:
curl_getinfo($curl, CURLINFO_HTTP_CODE) >= 200 && curl_getinfo($curl, CURLINFO_HTTP_CODE) < 3004.file_get_contents 未处理错误
当使用 file_get_contents 时,无法检测 HTTP 错误状态码,可能返回错误内容。
修复建议: 尽量统一使用 cURL,或在 file_get_contents 后解析响应头(复杂,推荐优先使用 cURL)。
5.User-Agent 不一致
file_get_contents 部分未设置 User-Agent,而 cURL 部分尝试设置但被覆盖。
修复: 在 file_get_contents 的 header 中添加 User-Agent。
改进后的代码示例:
private static function httpRequest($url, $user, $pass) {
if (extension_loaded('curl')) {
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_HEADER => false,
CURLOPT_TIMEOUT => 20,
CURLOPT_ENCODING => '',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERAGENT => self::$userAgent, // 统一设置User-Agent
]);
// 仅当两者均非空时设置认证
if ($user !== null && $pass !== null) {
curl_setopt($curl, CURLOPT_USERPWD, "$user:$pass");
}
if (!ini_get('open_basedir')) {
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
}
$result = curl_exec($curl);
$statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$success = curl_errno($curl) === 0 && $statusCode >= 200 && $statusCode < 300;
curl_close($curl);
return $success ? $result : false;
} else {
$options = ['http' => ['method' => 'GET']];
// 统一认证条件
if ($user !== null && $pass !== null) {
$options['http']['header'] = "Authorization: Basic " . base64_encode("$user:$pass") . "\r\n";
}
// 添加User-Agent
if (self::$userAgent) {
$options['http']['header'] .= "User-Agent: " . self::$userAgent . "\r\n";
}
$context = stream_context_create($options);
$result = @file_get_contents($url, false, $context);
// 简单检测是否出错(无法精确检查状态码)
return $result !== false ? $result : false;
}
}其他建议:
看着这个长篇大论、有论有据、很负责任的解答,我还是一脸懵逼啊...
不会看还不会抄啊,我直接将这个函数复制、替换、应用。哈哈,没有奇迹,品味苏州的订阅成功获取到了。困扰我数月之久的问题总算得到了圆满解决,感谢 AI !!!!
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。