3

ローカルで XML ファイルを解析し、XML からいくつかの URL を取得し、URL が指すファイルをダウンロードしてデータ (すべて jpg) を保存する自動化スクリプトを作成しました。後続のすべての反復は、次第に時間がかかります。最終的に、スクリプトはハングアップし、何も起こりません。おお、メモリ使用量は一定のままのようです。XML の解析は正常に機能するので、あまり詳しく説明しないでください。スクリプトが完全に停止するゲームでスクリプトを開始すると、スクリプトが実行する最初の保存であるため、1 秒以内にファイルがディスクに保存されます。これは何が原因ですか?コードは次のとおりです。

    <?php

$xml = simplexml_load_file('./playfin.xml', null, LIBXML_NOCDATA);

echo("Getting urls from the XML...\n");
$data = array();
foreach($xml->game as $game) {
  $smlBox = $game->small_boxshot_image->url;
  $lrgBox = $game->large_boxshot_image->url;

  foreach($game->screenshots->screenshot_image as $image) {
    $scrShots[] = array(
      'smlScr' => (string)$image->small_screenshot_image->url,
      'lrgScr' => (string)$image->large_screenshot_image->url  
    );
  }
  $data[] = array(
    'id' => (int)$game->game_id,
    'smlBox' => (string)$smlBox,
    'lrgBox' => (string)$lrgBox,
    'scrShots' => $scrShots
  );
} 
echo("Done pulling urls from XML...\n");

echo("Storing picture data to disk...\n");
$start = time();
$total = 0;
$now = 0;
for($i = 0; $i < count($data); $i++) {
  $total += $now;
  $now = time() - $start - $total;
  echo("Writing game id: ".$data[$i]['id']. 
    ." to disk at time=".(string)$now."          seconds.\n");
  echo("Memory usage: ".(string)memory_get_usage(true)."\n\n");
  $smlBoxStr = '%s_49_60.jpg';
  $lrgBoxStr = '%s_160_189.jpg';
  $smlScrStr = '%s_115_86_%d.jpg';
  $lrgScrStr = '%s_300_300_%d.jpg';

  writeData($data[$i]['smlBox'], sprintf($smlBoxStr, $data[$i]['id']), 'boxshot');
  writeData($data[$i]['lrgBox'], sprintf($lrgBoxStr, $data[$i]['id']), 'boxshot');
  for($j = 0; $j < count($data[$i]['scrShots']); $j++) {
    writeData(
      $data[$i]['scrShots'][$j]['smlScr'], 
      sprintf($smlScrStr, $data[$i]['id'], $j),
      'screenshot'
    );
    writeData(
      $data[$i]['scrShots'][$j]['lrgScr'], 
      sprintf($lrgScrStr, $data[$i]['id'], $j),
      'screenshot'
    );
  }  
}
echo("Done storing!\n");
echo("Done!\n");

function writeData($url, $file, $type) {
  $headers = get_headers($url, 1);
  $awayPic = fopen($url, 'rb');
  $localPic = fopen("./$type/$file", 'wb');
  while($picData = fread($awayPic, (int)$headers['Content-Length'])) {
    fwrite($localPic, $picData);
  }
  fclose($awayPic);
  fclose($localPic);
}  

?>

生成されたログ ファイルは次のとおりです。

XML から URL を取得しています... XML から URL を取得しています... 画像データをディスクに保存しています... ゲーム ID: 671850 を time=0 秒でディスクに書き込みます。メモリ使用量: 77856768

time=0 秒でゲーム ID: 730950 をディスクに書き込みます。メモリ使用量: 77856768

time=1 秒でゲーム ID: 621650 をディスクに書き込みます。メモリ使用量: 77856768

time=1 秒でゲーム ID: 687250 をディスクに書き込みます。メモリ使用量: 77856768

time=7 秒でゲーム ID: 633950 をディスクに書き込みます。メモリ使用量: 77856768

time=2 秒でゲーム ID: 633850 をディスクに書き込みます。メモリ使用量: 77856768

time=2 秒でゲーム ID: 720950 をディスクに書き込みます。メモリ使用量: 77856768

time=3 秒でゲーム ID: 572250 をディスクに書き込みます。メモリ使用量: 77856768

time=3 秒でゲーム ID: 674950 をディスクに書き込みます。メモリ使用量: 77856768

time=3 秒でゲーム ID: 731450 をディスクに書き込みます。メモリ使用量: 77856768

time=4 秒でゲーム ID: 656350 をディスクに書き込みます。メモリ使用量: 77856768

time=4 秒でゲーム ID: 653550 をディスクに書き込みます。メモリ使用量: 77856768

time=4 秒でゲーム ID: 585550 をディスクに書き込みます。メモリ使用量: 77856768

time=5 秒でゲーム ID: 736750 をディスクに書き込みます。メモリ使用量: 77856768

time=5 秒でゲーム ID: 671350 をディスクに書き込みます。メモリ使用量: 77856768

time=5 秒でゲーム ID: 696250 をディスクに書き込みます。メモリ使用量: 77856768

time=6 秒でゲーム ID: 645550 をディスクに書き込みます。メモリ使用量: 77856768

time=6 秒でゲーム ID: 625650 をディスクに書き込みます。メモリ使用量: 77856768

time=6 秒でゲーム ID: 696850 をディスクに書き込みます。メモリ使用量: 77856768

time=7 秒でゲーム ID: 709550 をディスクに書き込みます。メモリ使用量: 77856768

time=7 秒でゲーム ID: 575750 をディスクに書き込みます。メモリ使用量: 77856768

time=7 秒でゲーム ID: 651950 をディスクに書き込みます。メモリ使用量: 77856768

time=8 秒でゲーム ID: 685350 をディスクに書き込みます。メモリ使用量: 77856768

time=9 秒でゲーム ID: 724150 をディスクに書き込みます。メモリ使用量: 77856768

time=8 秒でゲーム ID: 522250 をディスクに書き込みます。メモリ使用量: 77856768

time=10 秒でゲーム ID: 610350 をディスクに書き込みます。メモリ使用量: 77856768

time=9 秒でゲーム ID: 645050 をディスクに書き込みます。メモリ使用量: 77856768

time=9 秒でゲーム ID: 716950 をディスクに書き込みます。メモリ使用量: 77856768

time=10 秒でゲーム ID: 672750 をディスクに書き込みます。メモリ使用量: 77856768

time=11 秒でゲーム ID: 568650 をディスクに書き込みます。メモリ使用量: 77856768

time=11 秒でゲーム ID: 668650 をディスクに書き込みます。メモリ使用量: 77856768

time=11 秒でゲーム ID: 417950 をディスクに書き込みます。メモリ使用量: 77856768

time=13 秒でゲーム ID: 497950 をディスクに書き込みます。メモリ使用量: 77856768

time=12 秒でゲーム ID: 567950 をディスクに書き込みます。メモリ使用量: 77856768

time=13 秒でゲーム ID: 692350 をディスクに書き込みます。メモリ使用量: 77856768

time=13 秒でゲーム ID: 450950 をディスクに書き込みます。メモリ使用量: 77856768

time=14 秒でゲーム ID: 452750 をディスクに書き込みます。メモリ使用量: 77856768

time=14 秒でゲーム ID: 666450 をディスクに書き込みます。メモリ使用量: 77856768

time=15 秒でゲーム ID: 754550 をディスクに書き込みます。メモリ使用量: 77856768

time=15 秒でゲーム ID: 659050 をディスクに書き込みます。メモリ使用量: 77856768

time=15 秒でゲーム ID: 712350 をディスクに書き込みます。メモリ使用量: 77856768

time=16 秒でゲーム ID: 719250 をディスクに書き込みます。メモリ使用量: 77856768

time=15 秒でゲーム ID: 529250 をディスクに書き込みます。メモリ使用量: 77856768

time=17 秒でゲーム ID: 685150 をディスクに書き込みます。メモリ使用量: 77856768

time=17 秒でゲーム ID: 736450 をディスクに書き込みます。メモリ使用量: 77856768

time=17 秒でゲーム ID: 252750 をディスクに書き込みます。メモリ使用量: 77856768

time=17 秒でゲーム ID: 719150 をディスクに書き込みます。メモリ使用量: 77856768

time=18 秒でゲーム ID: 461150 をディスクに書き込みます。メモリ使用量: 77856768

time=18 秒でゲーム ID: 699450 をディスクに書き込みます。メモリ使用量: 77856768

time=18 秒でゲーム ID: 523550 をディスクに書き込みます。メモリ使用量: 77856768

time=20 秒でゲーム ID: 451050 をディスクに書き込みます。メモリ使用量: 77856768

time=19 秒でゲーム ID: 768350 をディスクに書き込みます。メモリ使用量: 77856768

time=20 秒でゲーム ID: 724650 をディスクに書き込みます。メモリ使用量: 77856768

time=21 秒でゲーム ID: 676550 をディスクに書き込みます。メモリ使用量: 77856768

time=21 秒でゲーム ID: 730850 をディスクに書き込みます。メモリ使用量: 77856768

time=22 秒でゲーム ID: 558250 をディスクに書き込みます。メモリ使用量: 77856768

time=22 秒でゲーム ID: 674750 をディスクに書き込みます。メモリ使用量: 77856768

time=22 秒でゲーム ID: 695450 をディスクに書き込みます。メモリ使用量: 77856768

time=22 秒でゲーム ID: 682950 をディスクに書き込みます。メモリ使用量: 77856768

time=24 秒でゲーム ID: 706450 をディスクに書き込みます。メモリ使用量: 77856768

time=24 秒でゲーム ID: 546450 をディスクに書き込みます。メモリ使用量: 77856768

time=24 秒でゲーム ID: 575350 をディスクに書き込みます。メモリ使用量: 77856768

time=25 秒でゲーム ID: 616550 をディスクに書き込みます。メモリ使用量: 77856768

time=26 秒でゲーム ID: 648250 をディスクに書き込みます。メモリ使用量: 77856768

time=25 秒でゲーム ID: 763750 をディスクに書き込みます。メモリ使用量: 77856768

time=26 秒でゲーム ID: 613850 をディスクに書き込みます。メモリ使用量: 77856768

time=25 秒でゲーム ID: 645450 をディスクに書き込みます。メモリ使用量: 77856768

time=33 秒でゲーム ID: 695950 をディスクに書き込みます。メモリ使用量: 77856768

time=27 秒でゲーム ID: 661050 をディスクに書き込みます。メモリ使用量: 77856768

time=27 秒でゲーム ID: 461050 をディスクに書き込みます。メモリ使用量: 77856768

time=29 秒でゲーム ID: 693150 をディスクに書き込みます。メモリ使用量: 77856768

ありがとう!

4

2 に答える 2

3

$scrShots問題は、XML の解析中に外側のループをクリアしていないことです。したがって、各反復には、現在のゲームのスクリーンショットだけでなく、以前のすべてのスクリーンショットも含まれます。(この方法では、最初のゲームから画像をダウンロードし、次に最初のゲームと 2 番目のゲームの画像をダウンロードし、次に 1 番目と 2 番目と 3 番目の画像をダウンロードします。もちろん、時間がかかります。)

次のラウンドを追加する前に、配列をクリアしてみてください。

$scrShots = array();
foreach($game->screenshots->screenshot_image as $image) {
    $scrShots[] = array(
    ...
于 2012-12-19T21:27:37.657 に答える
0

Wolfgang が見つけた問題 (大きな問題) に加えて、あなたは時間を間違って数えています (小さな問題)。

Writing game id: 687250 to disk at time=1 seconds. Memory usage: 77856768
Writing game id: 633950 to disk at time=7 seconds. Memory usage: 77856768
Writing game id: 633850 to disk at time=2 seconds. Memory usage: 77856768

$start が 1000 から始まり、各反復に 1 秒かかると仮定しましょう

for($i = 0; $i < count($data); $i++) {
    $total += $now;
    $now = time() - $start - $total;

次に、これはループの各反復後の値になります

1: $total: 0, $now: 1000 - 1000 - 0 = 0
2: $total: 0, $now: 1001 - 1000 - 0 = 1
3: $total: 1, $now: 1002 - 1000 - 1 = 1
4: $total: 1, $now: 1003 - 1000 - 1 = 2
5: $total: 2, $now: 1004 - 1000 - 2 = 2
6: $total: 2, $now: 1005 - 1000 - 2 = 3
7: $total: 3, $now: 1006 - 1000 - 3 = 3
7: $total: 3, $now: 1007 - 1000 - 3 = 4

これは間違いなくあなたが望むものではありません。$now の計算に合計を使用する理由がわかりません。:)

これはあなたが望むものだと思います。

for($i = 0; $i < count($data); $i++) {
    $now = time() - $start;
    ...
}

$total = $now - $start;
于 2012-12-19T21:34:32.137 に答える