php-for循环重复自身/不按顺序进行

时间:2018-11-15 18:18:48

标签: php json for-loop fwrite

我对PHP还是很陌生,经常出错和学习。请温柔! :)

我想从Blizzard.com的API访问一些数据。对于此特定数据集,它不是JSON中的数据块,而是每个对象都有其自己的URL可以访问。我估计大约有150000个对象,但是我不知道数字范围的起点或终点。所以我必须假设1并超过我知道的最高数字(269065)

要获取数据,我需要通过读取的JSON文件访问每个对象的数据,获取&的内容并拖放到文本文件中(也可以将其插入SQL db中,因为如果是文本文件,我就能做到)。但老实说,我很想深入了解为什么发生如此之多的事情!

我不会尝试在for循环中运行〜250000次迭代,我想我会尝试一些我认为很小的东西,2000年。

for循环以$ a为1开头,使用$ a作为URL的一部分,加载并解码JSON,检查是否设置了对象中的第一个字段(ID),如果是,它将写入data.txt的几个字段&如果未设置第一个字段(ID),它只会将$ a写入data.txt(因此我知道,出于其他目的(此处未列出),它为null)。

简单!或者我以为,经过大约183次迭代之后,写入文本文件的数据出现了问题,如下面的引用所示。它是乱序的,再次从1开始,然后回到184 ad nauseam。然后,该循环似乎被锁定在某种无限的运行循环中,以随机顺序输出,直到我在10-20分钟后关闭页面为止。

我显然犯了一个大错误!但是我不知道造成这个问题的原因是我做错了什么。在尝试过程中,我用新的变量名重写了代码,因此新文本不会与可能在内存中运行的代码冲突。

我尝试在循环结束时将变量重置为空白,以防万一某些东西被重用导致了问题。

如果任何人都可以指出我的代码中的任何错误,或提出一些建议供我参考,以处理更大的循环,那将是非常棒的。我假设我的问题可能是超时或内存问题。但是我不知道从哪里开始,希望能在这里找到一些建议。

如果有必要,我现在将000webhostapp.com用作托管服务提供商,直到获得托管费用为止。

  

1 ... 182183 1 184 2 3 185 4 186 5 187 6 188 7 189 190 8 191

for ($a = 1; $a <= 2000; $a++)      {
    $json = "https://eu.api.battle.net/wow/recipe/".$a."?locale=en_GB&<MYPRIVATEAPIKEY>";
    $contents = file_get_contents($json);
    $data = json_decode($contents,true);

        if (isset($data['id'])) {
            $file = fopen("data.txt","a");
            fwrite($file,$data['id'].",'".$data['name']."'\n");
            fclose($file);
        } else {    
            $file = fopen("data.txt","a");
            fwrite($file,$a."\n");
            fclose($file);  
        }
}   

我要访问的文件的内容是

  

{“ id”:33994,“名称”:“精确打击”,“专业”:“迷人”,“图标”:“ spell_holy_greaterheal”}

我取消了原来的计划,而是写下了这个计划。再次感谢您抽出宝贵的时间来提供帮助和建议!

$b = $mysqli->query("SELECT id FROM `static_recipes` order by id desc LIMIT 1;")->fetch_object()->id;

if (empty($b)) {$b=1;};
$count = $b+101;

$write = [];
for ($a = $b+1; $a < $count; $a++)      {
     $json = "https://eu.api.battle.net/wow/recipe/".$a."?locale=en_GB&apikey=";
     $contents = @file_get_contents($json);
     $data = json_decode($contents,true);
     if (isset($data['id'])) {
     $write [] = "(".$data['id'].",'".addslashes($data['name'])."','".addslashes($data['profession'])."','".addslashes($data['icon'])."')";

 } else {    
   $write [] = "(".$a.",'a','a','a'".")";
 }
} 
$SQL = ('INSERT INTO `static_recipes` (id, name, profession, icon) VALUES '.implode(',', $write));
$mysqli->query($SQL);
$mysqli->close();

3 个答案:

答案 0 :(得分:1)

500

还有,为什么您会认为在几个“ https://eu.api.battle.net/wow/[N]”网址数据中没有重复一些IDS?

如果您是$write = []; for ($a = 1; $a <= 2000; $a++) { $json = "https://eu.api.battle.net/wow/".$a."?locale=en_GB&<MYPRIVATEAPIKEY>"; $contents = file_get_contents($json); $data = json_decode($contents,true); if (isset($data['id'])) { $write [] = $data['id'].",'".$data['name']."'\n"; } else { $write [] = $a."\n"; } } $file = fopen("data.txt","a"); fwrite($file, implode('', $write)); fclose($file); ,请考虑一下I wasn't going to try and run ~250000http://php.net/manual/en/function.curl-multi-init.php

答案 1 :(得分:0)

我真的看不到任何明显的代码错误,尽管我没有JSON,却无法运行

由于您要非常快地打开和关闭同一文件数百次,因此可能存在某种竞争状况。

文件操作似乎是原子的,但不一定如此-这是一个有趣的SO线程:

Does PHP wait for filesystem operations (like file_put_contents) to complete before moving on?

与其他人的建议类似-也许只是在进入循环之前打开文件,然后在循环中断时关闭文件。

我会先尝试一下,看看是否有帮助。

答案 2 :(得分:0)

您的原始代码中没有任何东西会导致这种行为。 PHP不会随意更改变量的值。您正在以追加模式打开此文件,确定要查看的不是旧数据吗?在处理数据时,可能会输出一些调试消息。您可能会遇到API服务器上某些速率限制的情况,因此在其中停顿一下可能会提高可靠性。

我建议对代码进行的唯一实质性更改是一次打开文件,完成后将其关闭。

$file = fopen("data_1_2000.txt", "w");
for ($a = 1; $a <= 2000; $a++)      {
    $json = "https://eu.api.battle.net/wow/recipe/$a?locale=en_GB&<MYPRIVATEAPIKEY>";
    $contents = file_get_contents($json);
    $data = json_decode($contents, true);
    if (!empty($data['id'])) {
        $data["name"] = str_replace("'", "\\'", $data["name"]);
        $record = "$data[id],'$data[name]'";
    } else {
        $record = $a;
    }
    fwrite($file, "$record\n");
    sleep(1);
    echo "$a "; if ($a % 50 === 0) echo "\n";
}
fclose($file);