获取带有“br”编码的页面内容并通过php curl对其进行解码

ao218c7q  于 2022-11-13  发布在  PHP
关注(0)|答案(2)|浏览(267)

我想通过php curl获得this page的内容:
My Curl示例:

function curll($url,$headers=null){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,$url);

    if ($headers){

        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }

    curl_setopt($ch, CURLOPT_ENCODING, '');
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0');
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);

    $response = curl_exec($ch);

    $res['headerout'] = curl_getinfo($ch,CURLINFO_HEADER_OUT);
    $res['rescode'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if ($response === false) {
        $res['content'] = $response;
        $res['error'] = array(curl_errno($ch),curl_error($ch));
        return $res;
    }

    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $res['headerin'] = substr($response, 0, $header_size);
    $res['content'] = substr($response, $header_size);

    return $res;

}

回应:

array (size=4)
  'headerout' => string 'GET /wallets HTTP/1.1
Host: www.cryptocompare.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: br
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
Upgrade-Insecure-Requests: 1

' (length=327)
  'rescode' => string '200' (length=3)
  'content' => boolean false
  'error' => 
    array (size=2)
      0 => int 23
      1 => string 'Unrecognized content encoding type. libcurl understands deflate, gzip content encodings.' (length=88)

响应编码为br,响应内容为false
我知道使用gzipdeflate作为编码会得到一个内容。但是,我心目中的内容只显示了br编码。
我在this page上看到Curl V7.57.0支持Brotli Compression功能。我目前安装了7.59.0版本,但Curl在接收br encoding中的内容时遇到错误。
现在我想知道如何获取br编码页面内容,并使用php curl解压缩?

eqfvzcg8

eqfvzcg81#

我也遇到了同样的问题,因为一个服务器只能返回brotli,而我的PHP Curl捆绑版本不支持Brotli。我不得不使用一个PHP扩展:https://github.com/kjdev/php-ext-brotli

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'URL');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output_brized = curl_exec($ch);

$output_ok = brotli_uncompress($output_brized);

我检查了一下,在带有捆绑Curl版本7.70.0的Windows上的PHP 7.4.9中,将CURLOPT_ENCODING选项设置为''(就像您所做的那样),强制捆绑Curl使用一个额外的头部accept-encoding: deflate, gzip来执行请求,这是捆绑Curl可以解码的内容编码。如果我省略了这个选项,只有2个头部:Host: www.google.comaccept: */*中的一个或多个。
实际上,在PHP源代码(https://github.com/php/php-src/search?q=CURLOPT_ENCODING)中搜索CURLOPT_ENCODING选项并没有得到任何结果,这可能会设置默认值或更改PHP的值。PHP将选项值发送到Curl,而不对其进行更改,因此我所观察到的是我捆绑的Curl版本的默认行为。
然后我发现Curl从2018年11月的版本7.57.0(https://github.com/curl/curl/blob/bf1571eb6ff24a8299da7da84408da31f0094f66/docs/libcurl/symbols-in-versions)开始支持Brotli(https://github.com/curl/curl/blob/fd1ce3d4b085e7982975f29904faebf398f66ecd/docs/HISTORY.md),但是需要用一个--with-brotli标志(https://github.com/curl/curl/blob/9325ab2cf98ceca3cf3985313587c94dc1325c81/configure.ac)编译,这可能不用于我的PHP版本。
不幸的是,没有curl_getopt()函数来获取选项的默认值。但是,phpinfo()提供了一个有价值的信息,因为我得到了一个BROTLI => No行,它确认了我的版本没有编译成支持Brotli。您可能需要检查您的phpinfo,看看您的Curl捆绑版本是否应该支持Brotli。如果不支持,请使用我的解决方案。如果支持,还需要进行更多调查,以确定它是一个bug还是一个误用。
如果你想知道你的Curl发送了什么,你必须使用像Charles/Fiddler这样的代理或者使用Curl详细模式。
此外,为了完整起见,在HTTP 1/1规范(https://www.rfc-editor.org/rfc/rfc2616#page-102)中,还指出:

If an Accept-Encoding field is present in a request, and if the
   server cannot send a response which is acceptable according to the
   Accept-Encoding header, then the server SHOULD send an error response
   with the 406 (Not Acceptable) status code.

   If no Accept-Encoding field is present in a request, the server MAY
   assume that the client will accept any content coding.

因此,如果您的PHP版本表现与我的相同,网站应该收到不包含brAccept-Encoding,因此不应该回复br内容,而应该回复gzip或deflate内容,或者,如果无法做到这一点,回复406 Not Acceptable而不是200。

c0vxltue

c0vxltue2#

如果你使用的是cloudflare,那么你可以尝试从cloudflare中禁用brotli扩展。

相关问题