wget
ファイルのダウンロードに使用されます。例:
# サイトのトップページhtmlをダウンロード
wget http://ayqy.net
# 複数のファイルをダウンロード
wget http://www.example.com http://ayqy.net
上の例で www なしのドレスは 301 を返し、wget は自動的にリダイレクト先を追いかけ、index.html をダウンロードして現在のディレクトリに保存します。デフォルトではファイル名は同じになりますが、既に存在する場合は自動的にサフィックスが追加されます。
2種類のURL形式をサポートしています:
# http
http://host[:port]/directory/file
# ftp
ftp://host[:port]/directory/file
# ユーザー名とパスワードの認証付き
http://user:password@host/path
ftp://user:password@host/path
# または
wget --user=user --password=password URL
保存ファイル名は -O オプションで指定します:
# ファイルに出力
wget http://ayqy.net -O page.html
# - は標準出力を表す
wget http://ayqy.net -O -
注意:必ず大文字の O である必要があります。小文字の o は進捗情報やエラー情報を指定されたログファイルに記録することを意味します。指定したファイルが既に存在する場合は上書きされます。
その他のよく使われるオプション:
# POSTリクエスト
wget --post-data 'a=1&b=2' http://www.example.com
# または
wget --post-file post-body.txt http://www.example.com
# レジューム(中断したダウンロードの再開)
wget -c http://www.example.com
# エラー時の再試行を3回行う
wget -t 3 http://www.example.com
# ダウンロード速度を 1k に制限し、帯域幅を占有しないようにする
wget --limit-rate 1k http://www.example.com
# 総ダウンロード量を制限し、ディスク容量を使いすぎないようにする
wget -Q 1m http://www.example.com http://www.example.com
P.S. 総ダウンロード量の制限は、サーバーが提供する Content-Length に依存します。提供されない場合は制限できません。
また、wget には非常に強力なクローラー機能もあります:
# すべてのページを再帰的にクロールし、一つずつダウンロードする
wget --mirror http://www.ayqy.net
# 階層の深さを1に指定します。-r 再帰オプションと一緒に使用する必要があります
wget -r -l 1 http://www.ayqy.net
また、増分更新も可能で、新しいファイル(ローカルに存在しないもの、または最終更新日時が新しいもの)のみをダウンロードできます:
# -N はタイムスタンプを比較して増分更新を行い、新しいファイルのみをダウンロードします
wget -N http://node.ayqy.net
サーバー側のファイルに変更がない場合、次回はダウンロードされず、次のように表示されます:
Server file no newer than local file `index.html' -- not retrieving.
P.S. もちろん、増分更新はサーバーが提供する Last-Modified に依存します。提供されない場合は増分更新ができず、デフォルトでダウンロードして上書きされます。
P.S. wget に関する詳細は、GNU Wget 1.18 Manual を参照してください。
curl
wget よりも強力で、ファイルのダウンロードだけでなく、リクエスト(GET/POST/PUT/DELETE/HEAD など)の送信、リクエストヘッダーの指定などが可能です。HTTP、HTTPS、FTP などのプロトコルに対応し、Cookie、UA、認証などもサポートしています。
RESTful API のテストによく使われます:
# 作成 (POST)
curl -X POST http://localhost:9108/user/ayqy
# 削除 (DELETE)
curl -X DELETE http://localhost:9108/user/ayqy
# 更新 (PUT)
curl -X PUT http://localhost:9108/user/ayqy/cc
# 取得 (GET)
curl -X GET http://localhost:9108/user/ayqy
POST によるフォームの送信:
# フォーム送信のシミュレート
curl -d 'a=1&b=2' --trace-ascii /dev/stdout http://www.example.com
# リクエストヘッダーとリクエストボディ
=> Send header, 148 bytes (0x94)
0000: POST / HTTP/1.1
0011: Host: www.example.com
0028: User-Agent: curl/7.43.0
0041: Accept: */*
004e: Content-Length: 7
0061: Content-Type: application/x-www-form-urlencoded
0092:
=> Send data, 7 bytes (0x7)
0000: a=1&b=2
-d は --data-ascii を表します。他に --data-raw、--data-binary、--data-urlencode の3つの方法があり、そのうち --data-urlencode はパラメータ値をエンコードします。
--trace-ascii は、リクエスト/レスポンスヘッダー、リクエスト/レスポンスボディを出力したり、プロキシツールを介してリクエスト内容を確認したりするために使用されます:
# -x または --proxy でプロキシを経由させます。そうしないとキャプチャできません
curl -d 'a=1&b=2' -x http://127.0.0.1:8888 http://www.example.com
wget のようにファイルをダウンロードすることもできますが、デフォルトではファイルに書き込むのではなく標準出力に出力されます:
# レスポンス内容を直接出力する
curl http://ayqy.net
301 の簡単なページが返されます。curl は自動的にリダイレクト先を追いかけないため、これを利用してリダイレクトを追跡できます(もちろん、直接パケットキャプチャを見るほうが簡単で確実です)。
ファイルのダウンロードは、出力リダイレクトまたは -o オプションを使用して行います:
# ファイルに書き込みます。デフォルトでは進捗情報が出力されます
curl http://ayqy.net > 301.html
# または
curl http://ayqy.net -o 301.html
# URL内のファイル名を使用する
curl http://ayqy.net/index.html -O
# URLにファイル名が含まれていない場合はダウンロードできません
curl http://ayqy.net -O
# サイレントダウンロード。進捗情報を出力しません
curl http://ayqy.net --silent -o 301.html
面白いコマンドを紹介します:
# curlによるnvmのインストール
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.1/install.sh | bash
引数 o の値が - であることは、標準出力へのリダイレクトを意味します。その後、パイプで bash コマンドに渡され実行されます。この行全体の役割は、オンラインの bash スクリプトを取得して実行することです。
wget の場合も同様です:
# wgetによるnvmの���ンストール
wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.1/install.sh | bash
-q オプションで出力を抑制して結果をクリーンに保ち、-O - で標準出力にリダイレクトして bash コマンドに渡します。
curl の強力な点は、リクエストヘッダーのフィールド値を変更できることです:
# refererフィールドを指定する
curl --referer http://ayqy.net http://node.ayqy.net
# Cookieを設定する
curl -v --cookie 'isVisted=true' http://localhost:9103
# または、-Hで任意のヘッダーフィールドを設定する
curl -v -H 'Cookie: isVisted=true' http://localhost:9103
curl -v -H 'Cookie: isVisted=true' -H 'Referer: http://a.com' http://localhost:9103
# 返されたCookieをファイルに書き込む
curl http://localhost:9103 -c cookie.txt
# UAを設定する
curl -v -A 'hello, i am android' 'http://localhost:9105'
その他の特性およびオプション:
# ダウンロード進捗バーを表示する
curl http://ayqy.net --progress -o 301.html
# レジューム(中断したダウンロードの再開)
# オフセットを手動で指定し、15バイトスキップします。DOCTYPE宣言がスキップされます
curl http://node.ayqy.net -C 15
# オフセットを自動計算する(wget -cと同様)
curl http://node.ayqy.net -C -
# ダウンロード速度制限(ファイルにリダイレクトしない場合、標準出力への出力も制限されます)
curl http://www.ayqy.net > ayqy.html --limit-rate 1k
# 総ダウンロード量を制限する
curl http://node.ayqy.net --max-filesize 100
# ユーザー名とパスワードによる認証
curl -v -u username:password http://example.com
# レスポンスヘッダーのみを出力する
# wwwありの方はフィールドがかなり少なくなります
curl -I http://node.ayqy.net
curl -I http://www.ayqy.net
批量下载图片
curl を利用すれば、同様の簡単な作業を容易に完了できます:
#!/bin/bash
# 画像のバッチダウンロード
# 引数の数のチェック
if [ $# -ne 3 ];
then
echo 'Usage: -d <dir> <url>'
exit 1
fi
# 引数の取得
for i in {1..3};
do
case $1 in
-d) shift; dir=$1; shift;;
*) url=${url:-$1}; shift;;
esac
done
# ベースURLの抽出
baseurl=$(echo $url | egrep -o 'https?://[a-z.]+')
# ソースコードを取得し、imgをフィルタリングして、srcを抽出する
tmpFile="/tmp/img_url_$$.tmp"
curl $url --silent \
| egrep -o '<img\s.*src="[^"]+\"[^>]*>' \
| sed 's/.*src="\([^"]*\)".*/\1/g' \
> $tmpFile
echo "save image urls to $tmpFile"
# ルート相対パスを絶対パスに変換
sed -i '' "s;^/;$baseurl;g" "$tmpFile"
# ディレクトリの作成
mkdir -p $dir
cd $dir
# 画像のダウンロード
while read imgUrl;
do
filename=${imgUrl##*/}
curl $imgUrl --silent > "$filename"
echo "save to $dir/$filename"
done < "$tmpFile"
echo 'done'
以上のスクリプトを実行して、pengfu.com(捧腹)の画像をクロールします:
./imgdl.sh http://www.pengfu.com -d imgs
核心部分は非常に簡単です。ソースコードを取得し、img タグを見つけ、src を抽出して、ループでダウンロードします。引数の取得部分にはちょっとしたテクニックがあります:
# 引数の取得
for i in {1..3};
do
case $1 in
-d) shift; dir=$1; shift;;
*) url=${url:-$1}; shift;;
esac
done
ここで shift コマンドは、コマンド引数($1...n)の先頭要素を取り出すために使用されます。他の言語の配列における shift メソッドと同じ意味で、先頭要素を削除し、残りの要素を前方に移動させます。そのため、ループ内では先頭要素 $1 のみを判定すればよくなります。case でパラメータ名と値をマッチングさせ、一つ読んで一つ削除するという方法で、常に最初の要素を読み取ります。例えば、パラメータが -d <dir> のようなキーと値のペア形式の場合、まず shift で -d を取り除き、次に <dir> を読み取り、最後に読み取った <dir> も shift で削除して、次のパラメータの読み取りに進みます。
このように引数を読み取る利点は、引数の順序を制限しないことです。もちろん、キーと値のペア形式の引数はセットである必要がありますが、各引数間の順序は自由です。
ここで ${url:-$1} は、変数 url が存在し、かつ空でない場合は url の値を取得し、そうでない場合は $1 の値を取得することを意味します。この機能はパラメータ展開(parameter expansion)と呼ばれます:
${parameter:-word}
parameter が未定義または空の場合、word の値を返し、そうでなければ parameter の値を返します。
${parameter:=word}
デフォルト値を設定するために使用されます。parameter が未定義または空の場合、word の値を parameter に代入します。位置パラメータ($0, $1..$n など)や特殊パラメータには、このように代入することはできません(読み取り専用のため)。
${parameter:?word}
変数が未定義または空であることによるエラーをチェックするために使用されます。parameter が未定義または空の場合、word をそのまま標準エラー出力に出力し(例:parameter: word。word が指定されていない場合は parameter null or not set と出力)、対話型でない場合はスクリプトを終了します。parameter が存在し、かつ空でない場合は parameter の値を返します。
${parameter:+word}
変数が存在するかどうかをチェックするために使用されます。parameter が未定義または空の場合は空を返し、そうでなければ word の値を返します。
また、: のつかない4つのバージョンもあり、これらは parameter が空であることを許容します。
P.S. パラメータ展開に関する詳細は、Bash Reference Manual: Shell Parameter Expansion を参照してください。
コメントはまだありません