
本文详解 PHP 使用 cURL 请求含西里尔字母(如保加利亚语)的网页时出现乱码(显示为“”)的根本原因及两种可靠解决方案:通过 iconv 或 mb_convert_encoding 正确转换 Windows-1251 编码为 UTF-8。
本文详解 php 使用 curl 请求含西里尔字母(如保加利亚语)的网页时出现乱码(显示为“”)的根本原因及两种可靠解决方案:通过 `iconv` 或 `mb_convert_encoding` 正确转换 windows-1251 编码为 utf-8。
问题本质并非请求头配置错误,而是服务端响应的实际字符编码与客户端默认解析方式不匹配。尽管你设置了 "Content-Type: text/html; charset=UTF-8" 请求头(该头仅告知服务器“你发给我的内容我期望是 UTF-8”,但对服务器返回编码无强制约束力),目标网站 theatrevazrajdane.bg 的真实响应头明确声明:
Content-Type: text/html; charset=windows-1251
这意味着网页 HTML 内容实际以 Windows-1251(一种广泛用于东欧语言的单字节编码)编码传输,而 PHP 默认将 curl_exec() 返回的二进制数据当作原始字节流处理。当直接输出或在 UTF-8 环境下渲染时,未解码的 Windows-1251 字节就被错误解释为 UTF-8,导致西里尔字母(如 Актьори)显示为乱码 ``。
✅ 正确做法是:在获取原始响应后,显式将其从 windows-1251 转换为 UTF-8。以下是两种推荐方案:
方案一:使用 iconv()(轻量、高效)
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://theatrevazrajdane.bg/%D1%82%D0%B2%D0%BE%D1%80%D1%87%D0%B5%D1%81%D0%BA%D0%B8-%D1%81%D1%8A%D1%81%D1%82%D0%B0%D0%B2/%D0%B0%D0%BA%D1%82%D1%8C%D0%BE%D1%80%D0%B8/2",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: application/json"
// 注意:无需设置 Content-Type 请求头(GET 无请求体),且服务器不遵循该头指定的响应编码
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
die("cURL Error #: " . $err);
}
// 关键步骤:将 Windows-1251 响应转换为 UTF-8
$utf8Response = iconv('Windows-1251', 'UTF-8//IGNORE', $response);
// 输出前确保页面编码声明正确(如在 HTML 中)
header('Content-Type: text/html; charset=UTF-8');
echo $utf8Response;
?
//IGNORE参数可跳过无法转换的非法字节,避免iconv()报错中断执行。
CurlShip Directory Submission下载向CurlShip提交产品,这是一个对机器人友好的SaaS目录。只需一条curl命令即可发布产品,支持OG标签抓取、带徽章的dofollow链接及层级升级。
方案二:使用 mb_convert_encoding()(更健壮,支持自动检测)
// 替换上述转换行: $utf8Response = mb_convert_encoding($response, 'UTF-8', 'Windows-1251');
该函数对多字节编码兼容性更好,若需更高容错性(例如响应中混有少量其他编码片段),可启用自动检测:
$utf8Response = mb_convert_encoding($response, 'UTF-8', 'auto');
('auto' 会按 mb_detect_order() 顺序尝试常见编码,但建议明确指定 Windows-1251 以提升准确性和性能)
⚠️ 重要注意事项
-
不要依赖
CURLOPT_ENCODING:该选项用于告知 cURL 接受 哪些压缩编码(如 gzip),与字符编码无关。 -
移除无效的
Content-Type请求头:GET 请求无请求体,Content-Type头无意义,且可能被服务器忽略或引发歧义。 -
验证响应头:可通过
curl_getinfo($curl, CURLINFO_CONTENT_TYPE)获取实际返回的Content-Type,确认编码声明。 -
确保输出环境为 UTF-8:PHP 脚本自身应保存为 UTF-8 无 BOM 格式,并在 HTML 中添加
<meta charset="UTF-8">,或通过header()发送正确的 MIME 类型。
通过以上任一转换方案,即可正确渲染 <title>Актьори | Театър Възраждане</title>,彻底解决问号乱码问题。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











