话题虽然是关于 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);
}
}
AI 帮帮忙
看着这眼花缭乱的条件,我短路了,怎么办?于是也效仿大家,用腾讯元宝进行了提问:“请检查函数有没有错误”
元宝经过一番深度思考(就不贴出来了),然后给出了回复。
AI 之答
该函数存在几个潜在问题,以下是主要错误及改进建议:
1.重复设置 User-Agent
cURL 部分两次设置 CURLOPT_USERAGENT,第二次覆盖为空字符串,导致 User-Agent 头被清空。
修复: 移除第二个 curl_setopt($curl, CURLOPT_USERAGENT, '');。
2.HTTP 认证条件不一致
- cURL 使用 $user !== null || $pass !== null,允许单个参数为 null,可能导致认证头错误(如 "user:")。
- file_get_contents 使用 $user !== null && $pass !== null,要求两者均非空。
修复: 统一条件为两者均非空(&&),确保认证正确性。
3.HTTP 状态码检查过严
cURL 仅接受 200 状态码,忽略了其他成功状态(如 201、204)。
修复: 检查状态码是否为 2xx:
curl_getinfo($curl, CURLINFO_HTTP_CODE) >= 200 && curl_getinfo($curl, CURLINFO_HTTP_CODE) < 300
4.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;
}
}
其他建议:
- 添加 curl_close($curl) 释放资源。
- 在 file_get_contents 使用 @ 抑制警告,并通过返回值判断成功(但无法获取状态码)。
- 考虑强制使用 cURL 或处理 file_get_contents 的错误响应(如检查 $http_response_header)。
无脑抄袭
看着这个长篇大论、有论有据、很负责任的解答,我还是一脸懵逼啊...
不会看还不会抄啊,我直接将这个函数复制、替换、应用。哈哈,没有奇迹,品味苏州的订阅成功获取到了。困扰我数月之久的问题总算得到了圆满解决,感谢 AI !!!!
直接全部代码扔给AI,再把个别的feed再扔给AI,看他怎么说
我现在也是在用AI不断优化我的代码,不过也不十分AI,经常A=>B后,又提示B=>A ☺️
我是用的 fressrss 也总是遇到个别博客订阅失败的问题,一直无解。
各网站配置有差异,如果通过网站检测feed格式正确的话,估计是解析函数漏掉哪一个判断了。
我好像订阅不了你的
我的服务器在国外,有没有对国外服务器有限制啊?
我用的阿里云服务器,没设置过黑名单,应该能够打开订阅链接的话是没问题的,难道我的订阅也有问题? 🥶
用了culr -L feed.html有,culr -L feed提示没有该文件目录或路径。
feed.html 只是我博客一个页面;不过我怎么在电脑上
curl -L https://hollowman.cn/feed
会有订阅的内容呢我能打开你的feed,但是解析不了你的内容。
在服务器上用
curl -L 我的订阅地址
看看有没有正确输出,如果有的话是不是你的解析函数也和我的类似有判定上的问题?我也搞不懂了 😇很奇怪,我也不能订阅PW.的Rss。是不是它输出的Rss格式和正常的格式有一些出入啊。
rss估计也有点小问题,要不然这么多订阅,怎会唯独1个读取不了;但我查了订阅内容一直没发现问题,要说有疑问的话,那就是其他的订阅都是乱码文件名,他的是标准的feed文件名
。后来,我是看到其他网站有订阅成功的才想着去处理的。
这几天也用了一下,感觉简单的东西效果不错;比如给他个SQL查询语句,让他转成HTML查询显示。但要真想用AI生成一整套系统,哪怕是个功能比较简单的,效果也不理想;当然这个和使用的工具和提问的方法都有关系
我用的最多的是给文章检查错别字,哈哈。
这个用法倒是没想到啊,以后可以试试