【问题标题】:Very long (10+ seconds) response time on file_get_contents() call for Instagram content对 Instagram 内容的 file_get_contents() 调用响应时间很长(超过 10 秒)
【发布时间】:2019-10-17 23:57:48
【问题描述】:

我正在对某人的代码进行故障排除,该代码旨在从 Instagram 动态获取图片,然后将它们打印到页面上。

问题是,进程本身基本上是整个页面的瓶颈,导致加载时间出现 10-12 秒的峰值。

我似乎无法找到导致此问题的具体原因。以前的谷歌搜索让我得到了关于使用 file_get_contents() 时连接没有自动关闭的响应,但这不应该是 PhP 5.6 的问题,尤其是 7.1,不是吗?

这是有问题的代码:

<?php

function scrape_insta_hash($tag) {
  $insta_source = file_get_contents('https://www.instagram.com/explore/tags/'.$tag.'/');
  $shards = explode('window._sharedData = ', $insta_source);
  $insta_json = explode(';</script>', $shards[1]);
  $insta_array = json_decode($insta_json[0], TRUE);
  return $insta_array;
}

$tag = "placeholder";
$results_array = scrape_insta_hash($tag);

$limit = 5;
$imgs = array();

for ($i=$limit; $i >= 0; $i--) {                  
  if(array_key_exists($i,$results_array['entry_data']['TagPage'][0]["graphql"]["hashtag"]["edge_hashtag_to_media"]["edges"])) {
    $latest_array = $results_array['entry_data']['TagPage'][0]["graphql"]["hashtag"]["edge_hashtag_to_media"]["edges"][$i]["node"];
    $newPosting = ["image"=>$latest_array['display_url']];
    $imgs[] = $newPosting['image'];
  }
}
?>

【问题讨论】:

  • 如果您连续发送多个请求,您可能会受到 Instagram 服务器的限制。尝试伪造浏览器请求,因为 Instagram 可能会将您标记为机器人,请查看此 so post,如果您在循环中报废(我怀疑您是这样),请尝试在请求之间添加一个小睡眠。
  • 谢谢 - 在您对循环抓取并因此受到限制的评论之后,我尝试将代码加载到一个有一段时间没有向 Instagram 请求任何内容的网站上 - 果然,前几次没有节流,然后是硬节流。这样的用例的解决方案是什么?使用 file_get_contents() 的输出设置缓存,或者?

标签: php instagram file-get-contents php-7.1


【解决方案1】:

我在更新到 PHP 7 后遇到了同样的问题。file_get_contents() 在 PHP 5 中速度惊人,但在 PHP 7 中表现不佳。我通过使用 curl() 代替。你也应该试试。

【讨论】:

    【解决方案2】:

    好的,所以你在评论中证实了我的怀疑,所以这就是我要做的:

    首先我会调整 scraping 方法来模拟浏览器请求。尝试使用标题并在必要时添加更多。

    <?php
    
    function scrape_insta_hash($tag) {
      $opts = [
         "http" => [
            "method" => "GET",
            "header" => "Accept-language: en\r\n" .
                "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36 OPR/60.0.3255.109\r\n"
             ]
      ];
    
      $context = stream_context_create($opts);
    
      $insta_source = file_get_contents('https://www.instagram.com/explore/tags/'.$tag.'/', false, $context);
      file_get_contents('https://www.instagram.com/explore/tags/'.$tag.'/');
      $shards = explode('window._sharedData = ', $insta_source);
      $insta_json = explode(';</script>', $shards[1]);
      $insta_array = json_decode($insta_json[0], TRUE);
      return $insta_array;
    }
    

    因为您获取页面的方式 Instagram 会将您注册为 php 机器人。

    然后在循环发出请求的代码部分添加一个小超时:

    foreach($tags as $tag) {
        $res = scrape_insta_hash($tag);
        ...
    
        // Sleep for half a second
        usleep(500000);
    }
    

    还可以尝试使用睡眠数字,看看您可以设置的最低值是多少。我的意思是这里没有确切的答案,你需要大量的反复试验才能绕过 Instagram 的限制机制。

    另外,使用不同的 IP 地址可能会有用,也许当您受到限制时,您可以使用一些 VPN 作为代理并更改 IP 地址。

    正如您所提到的,缓存机制也不是一个坏主意,但是您需要一种方法来确定页面是否更改,因为乍一看我没有看到任何有用的标题,根据 Instagram 的响应标头,此页面永远不会被缓存,没有任何 etag 可以用作检查。

    【讨论】:

    • 嘿!我现在尝试在调用中添加标头更改和在循环本身中添加一个 usleep,尽管它似乎没有什么效果。我也去获取了一个 API 访问令牌,以防万一是匿名请求被限制的问题。不幸的是,页面加载时间似乎没有任何变化。
    猜你喜欢
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多