usp 友の会 lt 資料 20130413

24
wget と curl と とととととととと USP ととと LT (2013/04/13) とと とと @hi_saito [email protected] p

Upload: hirofumi-saito

Post on 31-May-2015

2.611 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: USP 友の会 LT 資料 20130413

wget と curl で並列ダウンロード

USP 友の会 LT (2013/04/13)

斉藤 博文 @hi_saito [email protected]

Page 2: USP 友の会 LT 資料 20130413

自己紹介

斉藤 博文 日本 GNU AWK ユーザー会主宰 @hi_saito [email protected] Shell + AWK 最強 !

Page 3: USP 友の会 LT 資料 20130413

サイトから画像を一括並列ダウンロード

ひとつひとつの画像をブラウザから右クリックで保存するのは面倒ですよね。

画像を抜き出して保存する専用アプリもあるようですが、「シェル芸」で十分です。

LL だと並列ダウンロードするのに fork とかを使いますが、使い方が良く分からないという人もいるんじゃないでしょうか。

Page 4: USP 友の会 LT 資料 20130413

使うもの

bash wget

curl でも可能ですが、今回の場合には wget の方が便利です。

tr egrep (grep) sort sed xargs

Page 5: USP 友の会 LT 資料 20130413

手順を記述してみる

1. 画像のあるサイトの HTML を落とす。2. アトリビュートを分割する。3. 画像を抜き出す。4. ダブっていたら無駄なのでダブらいないよう

にする。5. 必要に応じて絶対 URL に変換する。6. 並列に分割して画像を落とす。

Page 6: USP 友の会 LT 資料 20130413

$ wget -O - http://www.usptomo.com/ |\ tr "\"" "\n" |\ egrep "\.(JPG|PNG|GIF)" |\ sort -u |\ sed 's|^|http://www.usptomo.com|' |\ xargs -P0 -n1 wget

コードにしてみる

xargs で -PN で N 並列実行ですが、 -P0 で可能な限り並列実行します。

xargs の -nN で N 個単位で分割しますので、 -n1 だと結果的に全て並列処理になります。

Page 7: USP 友の会 LT 資料 20130413

ちょっとしたコツ

HTML からリンク先を抜き出すには tr で分割すると便利な場合が多いです。

egrep は括弧でグルーピングができるので拡張子をまとめて記述することができます。 もちろん、 tr と egrep を awk でま

とめて記述することもできます。

Page 8: USP 友の会 LT 資料 20130413

並列分割ダウンロード

巨大なファイルをダウンロードしたい。 サーバーが 1 接続あたりの回線速度を制限

しているため十分な速度が出ていない。 並列分割ダウンロードする OSS はあまりな

いよね。

Page 9: USP 友の会 LT 資料 20130413

使うもの

bash curl

今回は wget ではなく curl が必要です。 sed awk etc.

Page 10: USP 友の会 LT 資料 20130413

手順を記述してみる

1. 対象のファイルサイズを取得する。2. サイズを分割数で割る。3. ナンバリングして並列で落とす。4. 親プロセスは落とし終わるまで待つ。5. 分割したものを結合する。

Page 11: USP 友の会 LT 資料 20130413

#! /bin/bashDIV=5URL=$1FILE=$(basename ${URL})PID=$$

CONTENT_LENGTH=$(curl -s --head ${URL} |\ sed 's|\r||' |\ awk '/^Content-Length/ {print $2}')

対象のファイルサイズを取得

curl は --head でヘッダーのみを取得できます。

Page 12: USP 友の会 LT 資料 20130413

for i in `seq 1 ${DIV}`; do START_BYTE=$(echo "${CONTENT_LENGTH} \ / ${DIV} * (${i} - 1)" | bc) END_BYTE=$(echo "${CONTENT_LENGTH} \ / ${DIV} * ${i} - 1" | bc)

if [ ${i} -eq ${DIV} ]; then END_BYTE=${CONTENT_LENGTH} fi

サイズを分割数で割る

分割して落とす先頭バイト数と終了バイト数を計算します。

Page 13: USP 友の会 LT 資料 20130413

TMP_FILE=$(printf "%d-%02d-%s" \ ${PID} ${i} ${FILE})

curl -s --range ${START_BYTE}-${END_BYTE} \ -o ${TMP_FILE} ${URL} &done

ナンバリングして並列で落とす

curl は --range で落とす範囲を指定することができます。

Page 14: USP 友の会 LT 資料 20130413

wait

cat $$-* > ${FILE}

rm -f $$-*

落とし終わるまで待って結合

wait 単独だと全ての子プロセスの終了を待ちます。

Page 15: USP 友の会 LT 資料 20130413

iPhone 用のカレンダー壁紙を作

USP 友の会 LT (2013/04/13)

斉藤 博文 @hi_saito [email protected]

Page 16: USP 友の会 LT 資料 20130413

使うもの

bash bash の記述を使っています。

cal awk convert (ImageMagick)

Page 17: USP 友の会 LT 資料 20130413

$ cal April 2013Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 1314 15 16 17 18 19 2021 22 23 24 25 26 2728 29 30

cal コマンドの基本形

cal コマンドは何も引数がないと今月のカレンダーを表示します。

Page 18: USP 友の会 LT 資料 20130413

$ convert -font Ricty-Bold.ttf \ -pointsize 40 \ -fill black \ -draw "text 120,450 \"$(cal)\"" \ iphone.png calendar.png

ImageMagick で画像に変換

ImageMagick は日本語 TTF も扱えます。

文字列だけでなく、コマンドを埋め込めます。

Page 19: USP 友の会 LT 資料 20130413

$ cal | awk '$0=substr($0, 1, 2)'

Su

7142128

日曜日だけを抜き出す

この awk の使い方分かりますか ? アクションがないのに表示できていますよね。

Page 20: USP 友の会 LT 資料 20130413

アクションレスプログラミング

awk はパターン + アクションですよね。 でも、アクションがない場合は '{print

$0}' が省略されたものと見なれます。 また、 awk では基本的に代入は「真」にな

ります。$0=substr($0, 1, 2)

{ $0 = substr($0, 1, 2); print $0;}

等価 !

Page 21: USP 友の会 LT 資料 20130413

$ cal | awk '$0=sprintf("%20s",substr($0, 19, 2))'

Sa 6 13 20 27

土曜日だけを抜き出す

これもアクションレスプログラミングですね。 ここまでくれば、あとは同じです。

Page 22: USP 友の会 LT 資料 20130413

$ convert -font Ricty-Bold.ttf -pointsize 40 \ -fill black -draw "text 120,450 \ \"$(cal)\"" \ -fill red -draw "text 120,450 \ \"$(cal|awk '$0=substr($0, 1, 2)')\"" \ -fill blue -draw "text 120,450 \ \"$(cal|awk '$0=sprintf("%20s",substr($0,19,2))')\"" \ iphone.png calendar.png

最終形態

ほらね。「シェル芸」でできるでしょ。

Page 23: USP 友の会 LT 資料 20130413

特定の日付だけを出す方法は ?

特定の日付だけを抜き出すことができれば、今日や国民の休日をマーキングすることもできますね。

土日と比べると複雑ですが、やってみてください。$ cal | awk -v day="${DAY}" -v str="@" \

'{ regexp = "(^| )" day "( |$)"; $0 = gensub(regexp, "\\1@\\2", 1, $0);}{gsub(/[^@]/, " ")}{sub(/@/, day)}1'

Page 24: USP 友の会 LT 資料 20130413

最終的には ?

最終的には cron に crontab で登録して毎月 1 日に更新し、メールで iPhone に送るようにすると便利です。