curl 通过分页从API获取大量数据

hm2xizp9  于 2022-11-13  发布在  其他
关注(0)|答案(3)|浏览(271)

我尝试从API获取大量数据(超过30万条记录)。它有分页(每页25条记录),请求限制为每3分钟50个请求。我使用PHP curl来获取数据。API需要JWT令牌授权。我可以获取一个页面,并将其记录放入数组中。

...
$response = curl_exec($curl);
curl_close($curl);
$result = json_decode($response, true);

问题是我需要从所有页面中获取所有记录并保存到数组或文件中。如何做到这一点?也许我应该用JS做得更好?
祝您愉快,谢谢您。

busg9geu

busg9geu1#

理想情况下使用cron和某种形式的存储、数据库或文件。
重要的是,您要确保在前一个脚本完成之前,不会开始对脚本的新调用,否则它们会开始堆积,几次之后,您将开始出现服务器过载、脚本失败等情况,情况会变得混乱。
1.存储一个值,表示脚本正在启动。
1.运行CURL请求。
1.一旦curl被返回,数据被处理和存储,改变你在开始时存储的值,表示脚本已经完成。
1.在您认为必要的时间间隔内将此脚本作为cron运行。
一个简单的例子:

<?php 

    if ($script_is_busy == 1) exit();

    $script_is_busy = 1;

    // YOUR CURL REQUEST AND PROCESSING HERE
   
    $script_is_busy = 0;

    ?>
ghhkc1vu

ghhkc1vu2#

我会使用一系列请求。一个典型的请求最多需要2秒来完成,因此每300秒50个请求不需要并行请求。如果不想因为DoS而被禁止,您仍然需要测量时间并等待。请注意,即使使用并行,curl就我所记得的支持它,当你达到请求限制时,你必须使用sleep函数等待,直到你可以发送新的请求。对于PHP来说真实的的问题是它是一个长时间运行的作业,所以你需要改变设置,否则它会超时。你可以这样做:Best way to manage long-running php script?至于nodejs,我认为它是一个更好的解决方案,用于这种异步任务,因为所需的特性是nodejs自然附带的,没有扩展之类的东西,尽管我倾向于它。

ssm49v7z

ssm49v7z3#

好吧。我误解了你的意思。我还有问题要问。
你能做一个请求,并立即得到你的50条记录吗?这是假设当你说每3分钟50个请求时,你的意思是50条记录。
你认为为什么会有这个50/3的限制?
您能提供此服务的链接吗?
每个IP地址是否有50条记录?
是否可以选择租用5个或6个IP地址?
你为每一张唱片付费吗?
此服务总共有多少条记录?
记录的有效性是否有时间限制?
我在想,如果你可以使用6个IP地址(或6个进程),你可以同时运行6个请求使用stream_socket_client()
stream_socket_client允许您同时发出请求。
然后创建一个循环,监视每个套接字的响应。
大约10年前,我做了一个评估网页质量的应用程序。

  • W3C标记验证
  • W3C CSS验证
  • W3C移动的确定
  • 网页测试
  • 我自己的表现测试。

我把所有的URL放在一个数组中,如下所示:

$urls = array();
   $path = $url;
   $url = urlencode("$url");
   $urls[] = array('host' => "jigsaw.w3.org",'path' => "/css-validator/validator?uri=$url&profile=css3&usermedium=all&warning=no&lang=en&output=text");
   $urls[] = array('host' => "validator.w3.org",'path' => "/check?uri=$url&charset=%28detect+automatically%29&doctype=Inline&group=0&output=json");
   $urls[] = array('host' => "validator.w3.org",'path' => "/check?uri=$url&charset=%28detect+automatically%29&doctype=XHTML+Basic+1.1&group=0&output=json");

然后我会做插座。

foreach($urls as $path){
    $host = $path['host'];
    $path = $path['path'];
    $http = "GET $path HTTP/1.0\r\nHost: $host\r\n\r\n";
    $stream = stream_socket_client("$host:80", $errno,$errstr, 120,STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT); 
    if ($stream) {
      $sockets[] = $stream;  // supports multiple sockets
      $start[] = microtime(true);
      fwrite($stream, $http);
    }
    else { 
      $err .=  "$id Failed<br>\n";
    }
  }

然后,我监视套接字并从每个套接字检索响应。

while (count($sockets)) {
  $read = $sockets; 
  stream_select($read, $write = NULL, $except = NULL, $timeout);
  if (count($read)) {
    foreach ($read as $r) { 
      $id = array_search($r, $sockets); 
      $data = fread($r, $buffer_size); 
      if (strlen($data) == 0) { 
     //   echo "$id Closed: " . date('h:i:s') . "\n\n\n";
        $closed[$id] = microtime(true);
        fclose($r); 
        unset($sockets[$id]);
      } 
      else {
        $result[$id] .= $data; 
      }
    }
  }
  else { 
 //   echo 'Timeout: ' . date('h:i:s') . "\n\n\n";
    break;
  }
}

我用了很多年,从来没有失败过。
收集记录并将其分页将是很容易的。
关闭所有套接字后,您可以收集页面并将其发送给您的用户。
你认为上述方案可行吗?
JS也不是更好。
或者你是说每3分钟50张唱片?
这就是我如何进行分页。
我会将回复整理成每页25条记录的页面。
在查询结果while循环中,我会这样做:

$cnt = 0;
$page = 0;
while(...){
    $cnt++
    $response[$page][] = $record;
    if($cnt > 24){$page++, $cnt = 0;}
}
header('Content-Type: application/json');
echo json_encode($response);

相关问题