[PHP] Web上の画像ファイル(連番)にアクセスして、リネーム・保存する

ECサイトに登録した商品画像にブラウザでアクセス→リネームしてローカルに保存、という作業をPHPで効率化したときのメモです。

前提

集めたい画像のURLは次のような感じです。
http://www.sampleshop.com/img/{商品番号}/img-{商品番号}-{連番}.jpg

http://www.sampleshop.com/img/itemA/img-itemA-01.jpg
http://www.sampleshop.com/img/itemA/img-itemA-02.jpg
http://www.sampleshop.com/img/itemA/img-itemA-03.jpg
.
.
.
http://www.sampleshop.com/img/itemA/img-itemA-40.jpg

画像の連番は最小01~最大40までで、商品ごとにバラバラです。

01~40まで順番にアクセスして、ローカルに「{商品番号}-{連番}.jpg」という名前で保存していきます。

完成したPHP

次の内容でindex.phpを作成しました。

<?php

$id = 'itemA'; //商品番号
$urlbase = 'http://www.sampleshop.com/img/'; //画像URL(共通部分)
$ext = '.jpg'; //拡張子
$total = 40; //件数

for($i=1; $i<=$total; $i++){
  //連番1~9のゼロ埋め
  $num = sprintf('%02d', $i);

  //アクセスする画像URL
  //例:http://www.sampleshop.com/img/itemA/img-itemA-01.jpg
  $file_download = $urlbase.$id.'/'.$id.'-'.$num.$ext;

  //保存時のファイル名
  //例:itemA-01.jpg
  $file_save = $id.'-'.$num.$ext;

  //アクセス → download/フォルダへ保存
  $img = file_get_contents($file_download);
  if($img){
    file_put_contents('./download/'.$file_save, $img);
  }
}

なお、最後に指定しているダウンロードフォルダ「download/」はあらかじめ作っておいてください
index.phpにアクセスすると、商品番号「itemA」の画像の保存が始まります。

1商品分保存できたら$id='itemA'を書き換え → index.phpにアクセス…を繰り返して画像を集めました。

info 多少なりとも接続先サーバに負荷をかけることになるので、念のためあまり一度に大量の処理を行わないようにしました。

以下はソースコード内で使った関数の振り返りです。

sprintf()

$num = sprintf('%02d', $i);

for文のループカウンタ$iは 1,2,3 … 39,40 と続いていくのに対し、画像ファイル名に使う連番は 01,02,03 … 39,40 としたいです。このゼロ埋めした連番を$numにセットしています。

ちなみに 001,002,003 … 039,040 と3桁にしたい場合は次のようになります。

$num = sprintf('%03d', $i);

公式ドキュメント:PHP: sprintf – Manual

file_get_contents()

$img = file_get_contents($file_download);

第1引数に指定したファイルの内容を文字列で読み込みます。

公式ドキュメント:PHP: file_get_contents – Manual

file_put_contents()

if($img){
  file_put_contents('./download/'.$file_save, $img);
}

第2引数に指定したデータを、第1引数に指定した場所に書き込みます。

なお今回は「連番は最小01~最大40まで」という条件で、商品によっては画像が40個未満だったり、途中で抜けていたりするケースもありました。
そのような場合にfile_put_contents()を実行すると中身がない破損データが保存されてしまうため、事前にif文で判定を入れています。

ちなみに、file_get_contents()の実行後は$http_response_headerという変数にレスポンスヘッダが自動で格納されます
例えば$http_response_header[0]には「HTTP/1.1 200 OK」のようにステータスコードが入っています。

今回はざっくりとif($img)という判定で動いたのでヨシとしましたが、 $http_response_header で判定させるのがより正しい処理と言えそうです。

公式ドキュメント:PHP: file_put_contents – Manual
公式ドキュメント:PHP: $http_response_header – Manual