素敵な写真を一括で取得したい☆彡

某最新音楽ニュースサイトの写真は素敵なものばかりで、いつも保存させてもらっていた。
一つ一つポチポチと保存していたのだが、全部保存したいし保存してない写真があるかもしれない、と常々思っていた。
ちょっと。。。何これ。。。何枚あるのよ面倒くさい!自動化出来ないかなーと思っていて調べたら、curlという素敵コマンドがあるらしいので色々試してみた。

取り敢えず -O オプション

-O[0000-1000] のようにして連番を生成すればコマンド一つで大量のファイルを取得出来る!すごい。
早速やってみる。(※urlは仮)

curl -O http://example.com/image/DSC_[0000-1000].jpg

[1/1001]: http://example.com/image/DSC_0000.jpg --> news_large_DSC_0000.jpg
--_curl_--http://example.com/image/DSC_0000.jpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  9630    0  9630    0     0  14750      0 --:--:-- --:--:-- --:--:-- 14747

ダウンロードを開始している表示が延々と流れる。成功か?
数分待って1000までの画像ダウンロード終了。
中身を確認してみると。。
10KBの画像ファイルが大量にできている。404だったものが10KBのファイルとして残っているようだ。
404のファイルは保存したくない。。オプションで指定できない??
不要なので一括削除!

$ find . -size -10k | xargs rm

curlのオプションを調べたが、存在しないファイルを保存しないオプションはないみたい。

HTTPヘッダの取得

シェルスクリプトを書けば、HTTPヘッダを取得して処理を分けたり出来るらしい。

Helix Melody:Livedoorクリップのリンク切れを一括チェックする方法 - livedoor Blog(ブログ)

を参考にさせていただき、HTTPヘッダの取得からやってみる。

$ curl -I http://example.com/image/DSC_0000.jpg
HTTP/1.1 404 Not Found

きた!HTTPステータスコードを見て、404だった場合にファイルを保存しないように出来そう。
複数ファイルの場合は?

$ curl -I http://example.com/image/DSC_[0-10].jpg

[1/11]: http://example.com/image/DSC_0.jpg --> <stdout>
--_curl_--http://example.com/image/DSC_0.jpg
HTTP/1.1 404 Not Found

できてる!けど、一回一回判断出来るのか?シェルスクリプトの中で繰り返しをするか?

ステータスコードの抜き出し

404 だけ取る場合

$ curl -s -I http://example.com/image/DSC_0000.jpg | grep HTTP/ | cut -d' ' -f2 > test.txt

HTTP/1.1 404 Not Found だけ取る場合

$  curl -s -I  http://example.com/image/DSC_0000.jpg | grep HTTP/

grepコマンドは最近勉強したから理解出来るが、cut -d' ' -f2 がわからない。

cutコマンド

Linuxコマンド一覧 [cut] より

テキストファイルの各行から指定した部分の文字列を切り出して表示します。

コマンドの名前から想像出来る。で、 -d オプションは。

[-d 文字] フィールドの区切り文字を指定します。デフォルトのフィールド区切り文字は「TAB」です。

-d’ ‘ で、半角空白を区切り文字にしてるようだ。
-fオプションは

[-f位置] フィールド単位で切り出します。フィールド位置を下記のように指定します。 -f5  : 5番目のフィールド

なので、
-f2で2番めのフィールドを切り出す
HTTP/1.1 404 Not Found を ‘ ‘(半角空白)で区切って、2番めを取得
404
なるほど!

他のやり方

$ curl -s http://example.com/image/DSC_0000.jpg -w "status:%{http_code}" | grep 'status:' > test2.txt

$ cat test2.txt 
status:404

これでもHTTPステータスコードだけ取れる

$ curl -s http://example.com/image/DSC_0000.jpg -w "status:%{http_code}" | grep 'status:' | cut -d':' -f2 > test3.txt

作ってみた(1)

  • 指定したURLに対して
  • 指定した回数(ファイル名?)
  • 繰り返して curl -w を実行し、 http_code404 じゃないものをファイルに保存(curl -O)

という方針で作る!

http_codeを使うと、存在するファイルの時に

$ curl -s http://example.com/image/DSC_0000.jpg -w "status:%{http_code}" | grep 'status:' | cut -d':' -f2
Binary file (standard input) matches

が返ってきてしまい都合が悪い。。
なので、やはりヘッダからコードを取ることに!
今のままだとカレントディレクトリに保存されるので、引数で指定出来るようにした。
引数がない場合はカレントディレクトリに保存。

#!/bin/bash

# 画像のベースURL
URL="http://example.com/image/"
PREFIX="DSC_"
SUFFIX=".jpg"

start=$1
end=$2

# saveするがない場合はカレント
if [ -z "$3" ]
then
    dir=`pwd`
else
    dir=$3
fi

echo "${dir}"


# ディレクトリかどうかチェック。なかったら作る
if [ ! -d "${dir}" ]
then
    echo "ディレクトリ作る: ${dir}"
    mkdir "${dir}"
fi

# 保存先へ移動
cd "${dir}"

echo "==========================="
echo "${URL}の"
echo "${start}から${end}までのファイルをゲットしにいくよ"
echo "保存先は:${dir}"
echo "==========================="

echo "[http_code] URL" > get.txt

for i in `seq ${start} ${end}`
do
    geturl=${URL}${PREFIX}${i}${SUFFIX}
    #echo ${geturl} >> get.txt
    # 1つずつHTTP STATUS をチェック
    #code=`curl -s ${geturl} -w "status:%{http_code}" | grep 'status:' | cut -d':' -f2`
    code=`curl -s -I ${geturl} | grep HTTP/ | cut -d' ' -f2`
    echo [${code}] ${geturl} >> get.txt

    sleep 1.5s

    # 404じゃなかったらファイルを保存
    if [ ${code} -eq 200 ]
    then
        echo "download $geturl} ..."
        `curl -O ${geturl}` 
        echo "saved..." >> get.txt
    fi
done

exit 0

curl200ステータスのファイルのリストを作りwgetしたほうがいいのかな?
それか、curlで連番ダウンロードをして指定サイズ以下のファイルを後で消す方がいいかもしれない。
↑のやり方だと、ステータス確認→ファイル取得で2回のリクエストが発生する。
404かどうかは確認せずに、全て取得した後にサイズが10KB以下のファイルを消そう。そうしよう。

作ってみた(2)

UNIX & Linux コマンド・シェルスクリプト リファレンス を参考にしつつ、書き方の修正&コメントを追加。改良版

指定URLから連番のファイルを取得するスクリプト作ってみた

コメントに@(#)をつけるとこんな感じで出るようだ。すごい。

$ what download.sh
download.sh
     download.sh ver.1.0.1 2014.03.12

HP コミュニティ - whatコマンドについて - エンタープライズ・ビジネス・コミュニティ