素敵な写真を一括で取得したい☆彡
某最新音楽ニュースサイトの写真は素敵なものばかりで、いつも保存させてもらっていた。
一つ一つポチポチと保存していたのだが、全部保存したいし保存してない写真があるかもしれない、と常々思っていた。
ちょっと。。。何これ。。。何枚あるのよ面倒くさい!自動化出来ないかなーと思っていて調べたら、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コマンド
テキストファイルの各行から指定した部分の文字列を切り出して表示します。
コマンドの名前から想像出来る。で、 -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_codeが404じゃないものをファイルに保存(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
curlで200ステータスのファイルのリストを作りwgetしたほうがいいのかな?
それか、curlで連番ダウンロードをして指定サイズ以下のファイルを後で消す方がいいかもしれない。
↑のやり方だと、ステータス確認→ファイル取得で2回のリクエストが発生する。
404かどうかは確認せずに、全て取得した後にサイズが10KB以下のファイルを消そう。そうしよう。
作ってみた(2)
UNIX & Linux コマンド・シェルスクリプト リファレンス を参考にしつつ、書き方の修正&コメントを追加。改良版
コメントに@(#)をつけるとこんな感じで出るようだ。すごい。
$ what download.sh
download.sh
download.sh ver.1.0.1 2014.03.12