从 php cURL 获取正确的编码

Getting correct encoding from php cURL

(请参阅 post 底部的更新)

使用 Chrome 网络记录器,我注意到一个给定的 XHR 请求:

请求Headers

GET ... HTTP/1.1
Host: ...
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Origin: ...
Authorization: Jra45648WwbbQ
Accept: */*
Referer: ...
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-US,en;q=0.8

回复Headers

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization, Origin, Content-Type, Accept, Referer, User-Agent, deportes
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: ...
Access-Control-Expose-Headers: Authorization, x-request-id, x-mlbam-reply-after
Content-Type: application/octet-stream
Date: Sun, 16 Apr 2017 ... GMT
Server: nginx/1.11.3
Vary: Accept
X-Request-ID: ...
Content-Length: 16
Connection: keep-alive

回复内容为@ EqV¡^MSÁ9

完美。这是正确的输出。

现在,我需要使用 cURL 在 PHP 中重新创建这个确切的交换。所以我使用相同的 headers.

复制请求
    $ch = curl_init();
    curl_setopt_array($ch, array(
        CURLOPT_URL => $url,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_ENCODING => 'gzip',
        CURLOPT_RETURNTRANSFER => true
    ));

然而,这里输出的是@ EqV–¡^MSƒÁ’9,明显不同

我需要以原始格式 (@ EqV¡^MSÁ9) 获取它,因为最终 PHP 的输出将提供给 javascript 脚本,并且 charCodeAt 在这两个输出之间有不同的结果。我不确定如何解决这个问题。

可以看到,XHR请求后,Chrome中的响应预览是正确的:

如果我将 PHP 页面输出的编码类型更改为 Western (ISO-8859-15),我会得到 @ EqV¡^MSÁ9.

如果我将该输出粘贴到 Notepad++ 中,我会得到一些与我想要的非常非常相似的东西,但仍略有不同(在这种情况下,只有一个字符不同).所以也许这非常接近我需要的编码?

如何找到我需要的编码? chrome 的默认编码是什么,因为它似乎可以很好地处理响应?

更新: 我用新值 òÝD¶0v¢ÔL·ßÎO Ó 进行了测试,使用 mb_convert_encoding($r, 'utf-8', 'ISO-8859-15') 得到了正确的结果。那么为什么它对特定响应 (@ EqV¡^MSÁ9) 进行编码会给我一个短字符的值?

您可以尝试检测八位字节流的编码,然后将其转换为已知的字符集。

$result = curl_exec($ch);
curl_close($ch);
echo mb_detect_encoding($result);
$resultUTF8 = mb_convert_encoding($result, 'ISO-8859-15', 'utf-8');

Chrome 默认编码为 UTF-8,如果您将其设置为 UTF-8
curl_setopt($ch, CURLOPT_ENCODING, 'UTF-8');,您的文本将正如预期的那样,您可以尝试 here.
检测编码也很痛苦,因为使用 mb_detect_encoding 可能会遇到很多问题,但在这种情况下,如果您像这样指定预期的检测顺序,它会很有帮助:

mb_detect_encoding($val, 'UTF-8,ISO-8859-15');

根据我的个人经验,如果不指定目标并以正确的顺序排列,它是毫无价值的,例如,您需要在 encoding_list 中的 ISO-8859-1 之前列出 UTF-8,否则它将 return ISO-8859-1 在大多数情况下

更新:
docCURLOPT_ENCODING => '' 处理你可以尝试的所有编码,但正如我所说,因为你正在处理一个已知的编码,即 UTF-8 请尝试

$ch = curl_init();
    curl_setopt_array($ch, array(
        CURLOPT_URL => $url,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_ENCODING => 'UTF-8',
        CURLOPT_RETURNTRANSFER => true
    ));