綾小路龍之介の素人思考

Services > YourFileHostダウンローダ

エロりましょうぜ奥さんや。それはそれとて何個目の車輪なのかわからんがYourFileHost.comからダウンロードするスクリプトを書いてみた。とりあえず晒してみよう。wgetでは分割ダウンロードに対応して無いようなので、cURLを使ってみた。ダウンロードできないものがたまにあるが、そこは気にせず。


目次


1.1 つかいかた

$ sh your.sh -u "http://www.yourfilehost.com/media.php?cat=video&file=hoge.wmv"

分割ダウンロードする際の分割数はデフォルトで10。yourfilehost側が分割ダウンロードをどう思っているのか判らないが、リクエストヘッダにrangeを含めてもリクエストどおりダウンロードできるようだ。

引数に与えたURIから実際に取得するURIを引っ張るまでにhtmlファイル内容の解析を行っているが、grep等で書いているため、yourfilehost側の仕様変更があるとこのスクリプトは使えなくなる可能性大。

およそ1時間30分で3596308バイト。666KB/sec。


1.2 ソース[2008年 11月 25日 火曜日 19:50:49 JST]

とりあえず下のような感じ。保存してつかってくれい。使い方は上に書いたぞよ。スクリプトの版はこのセクションのタイトルに書いたぞよ。

#!/bin/bash -vx

# Function to get filesize
function FileSize ()
{
  if [ -f "$1" ] ; then
    SIZE=`ls -ld "$1" | awk '{print $5}'`
    echo $SIZE
  else
    echo 0
  fi
}

# Function to output an error message and terminate
function ErrorMessage ()
{
  echo -e "Error: $1"

  exit 1
}

function usage() {
	local CMDNAME=`basename "$0"`
	echo "Usage ${CMDNAME} -u \"URI\" " 1>&2
}

USER_AGENT='Mozilla/4.0 (compatible; MSIE 6.0; Windows XP)'

URI="FALSE"
URIVALUE=

OPT=
while getopts "u:" OPT
do
	case ${OPT} in
		"u" )   URI="TRUE"
			URIVALUE="${OPTARG}" ;;
		* ) usage
			exit 1 ;;
	esac
done
if [ "${URI}" != "TRUE" ] ; then
	usage
	exit 2
fi

CURL='curl -sSv --retry 10'
CURL='curl -sSv --retry 10 -0 -C -'
CURL='curl -sSv --retry 10 -0'
#WGET='wget -t 10 -Sd --keep-session-cookies'
ITERATION=10

URL1=''
FILE=''
i=0
while [ -z "${URL1}" -o -z "${FILE}" ];
do
	${CURL} -A "${USER_AGENT}" -o tmp2.$$ -c cookie2.$$ ${URIVALUE}
	cat tmp2.$$ | grep -e 'param.*embed' > tmp0.$$
	cat tmp0.$$ | cut -d "&" -f3 > tmp0.$$
	cat tmp0.$$ | cut -d "=" -f2 > tmp0.$$
	cat tmp0.$$ | sed 's/%3A/:/g;s/%2F/\//g;s/%3F/?/g;s/%26/\&/g;s/%3D/=/g' > tmp0.$$
	URL1=$(cat tmp0.$$)
	cat tmp0.$$ | cut -d "&" -f5 > tmp0.$$
	cat tmp0.$$ | cut -d "=" -f2 > tmp0.$$
	cat tmp0.$$ | sed 's/%3A/:/g;s/%2F/\//g;s/%3F/?/g;s/%26/\&/g;s/%3D/=/g' > tmp0.$$
	FILE=$(cat tmp0.$$)
	if [ ${i} -lt ${ITERATION} ];
	then
		i=`expr $i + 1`
		sleep 1
	else
		rm tmp2.$$ cookie2.$$ tmp0.$$ tmp3.$$ cookie3.$$
		exit 1
	fi
done
echo "# Successfully set URL1 of path to file including path to flash video and FILE meaning filename"
echo $URL1
echo $FILE

if [ -s "${FILE}" ];
then
	rm tmp2.$$ cookie2.$$ tmp0.$$ tmp3.$$ cookie3.$$
	exit 1
else
	rm -f ${FILE}
fi

URL=''
i=0
while [ -z "${URL}" ];
do
	${CURL} -A "${USER_AGENT}" -o tmp3.$$ -c cookie3.$$ ${URL1}
	cat tmp3.$$ | cut -d "&" -f1 > tmp0.$$
	cat tmp0.$$ | cut -d "=" -f2 > tmp0.$$
	cat tmp0.$$ | sed 's/%3A/:/g;s/%2F/\//g;s/%3F/?/g;s/%26/\&/g;s/%3D/=/g' > tmp0.$$
	URL=$(cat tmp0.$$)
	cat tmp3.$$
	if [ ${i} -lt ${ITERATION} ];
	then
		i=`expr $i + 1`
		sleep 1
	else
		rm tmp2.$$ cookie2.$$ tmp0.$$ tmp3.$$ cookie3.$$
		exit 1
	fi
done
echo "# Successfully set URL to flash video"
echo $URL

FILESIZE=''
i=0
while [ -z "${FILESIZE}" ];
do
	${CURL} -A "${USER_AGENT}" -b cookie3.$$ ${URL} -I 2> /dev/null | sed -e "s/^$//" > "z_${FILE}.header"
	FILESIZE="`grep -i '^\(Content-Length: \)\?[0-9]\+' "z_${FILE}.header" | sed 's/^\(Content-Length: \)\?\([0-9]\+\)/\2/i'`"
	if [ ${i} -lt ${ITERATION} ];
	then
		i=`expr $i + 1`
		sleep 1
	else
		rm tmp2.$$ cookie2.$$ tmp0.$$ tmp3.$$ cookie3.$$
		exit 1
	fi
done
echo "# Successfully set FILESIZE of flash video"
echo ${FILESIZE}

NUM=10
FILESIZE="`echo ${FILESIZE} | sed 's/\r//g;s/\n//g;'`"
WIDTH_BYTE=`expr ${FILESIZE} / ${NUM}`
START_BYTE=0
END_BYTE=${WIDTH_BYTE}
SLEEP_SEC=1;
i=0;
while [ ${i} -lt ${NUM} ];
do
	TEMP_FILE="${FILE}.$i"
	START_BYTE="`expr ${WIDTH_BYTE} '*' ${i}`"
	if [ ${i} -lt `expr ${NUM} - 1` ];
	then
		END_BYTE="`expr ${START_BYTE} + ${WIDTH_BYTE} - 1`"
	else
		END_BYTE=`expr ${FILESIZE} - 1`
	fi
	FILE_BYTE=`expr ${END_BYTE} - ${START_BYTE} + 1`
	TEMP_FILE_BYTE=0;
	(
	while [ ${FILE_BYTE} -ne ${TEMP_FILE_BYTE} ];
	do
		echo "$i / ${NUM} : byte range ${START_BYTE}-${END_BYTE} ${FILE_BYTE}"
		${CURL} -A "${USER_AGENT}" --range ${START_BYTE}-${END_BYTE} -o ${TEMP_FILE} -b cookie3.$$ ${URL}
		TEMP_FILE_BYTE="`FileSize "${TEMP_FILE}"`"
		sleep ${SLEEP_SEC}
	done
	echo "$i / ${NUM} : byte range ${START_BYTE}-${END_BYTE} ${FILE_BYTE} end"
	)&
	i=`expr $i + 1`
done

echo "Waiting for cURLs to finish..."
wait

echo
echo "Assembling ${FILE}... "

i=0;
while [ ${i} -lt ${NUM} ];
do
	TEMP_FILE="${FILE}.$i"
	echo "cat ${TEMP_FILE} >> ${FILE}"
	cat ${TEMP_FILE} >> ${FILE}
	echo rm ${TEMP_FILE}
	rm ${TEMP_FILE}
	i=`expr $i + 1`
done

rm tmp2.$$ cookie2.$$ tmp0.$$ tmp3.$$ cookie3.$$
exit

1.3 呼び出しのリスト

100回も200回も呼び出す場合にはぜんぜん効率的じゃないので、リストを作っておいて、sedで適当に置換して、出来たシェルスクリプトを走らせる。

$ cat yourfilehost.list
http://www.yourfilehost.com/media.php?cat=video&file=02111.wmv
http://www.yourfilehost.com/media.php?cat=video&file=02112.wmv
http://www.yourfilehost.com/media.php?cat=video&file=02113.wmv
http://www.yourfilehost.com/media.php?cat=video&file=02114.wmv
http://www.yourfilehost.com/media.php?cat=video&file=02115.wmv
$ sed 's/^/sh hoge.sh -u "/;s/$/" >>log.txt/;' yourfilehost.list > yourfilehost.list.sh
$ cat yourfilehost.list.sh
sh hoge.sh -u "http://www.yourfilehost.com/media.php?cat=video&file=02111.wmv" >>log.txt
sh hoge.sh -u "http://www.yourfilehost.com/media.php?cat=video&file=02112.wmv" >>log.txt
sh hoge.sh -u "http://www.yourfilehost.com/media.php?cat=video&file=02113.wmv" >>log.txt
sh hoge.sh -u "http://www.yourfilehost.com/media.php?cat=video&file=02114.wmv" >>log.txt
sh hoge.sh -u "http://www.yourfilehost.com/media.php?cat=video&file=02115.wmv" >>log.txt
sh yourfilehost.sh

1.4 呼び出し2

これでもまだ面倒だ、と言う人のために。ダウンロード用のスクリプトを呼び出すスクリプトを作ってみた。

#!/bin/bash

trap 'echo "trapped."; exit 1' 1 2 3 15

declare -r listfile="hoge-list"
declare -r lockfile="${listfile}.lock"

function download
{
	local -r url=$1
	#local num=`expr ${RANDOM} % 100`
	sh hoge.sh -u "${url}"
	#sleep ${num}
}

function process
{
	while [ `find ${listfile} -size +0` ];
	do
		if lockfile -1 ${lockfile}
		then
			url=`head -n1 ${listfile}`
			sed -si 1d ${listfile}
		fi
		rm -f ${lockfile}
		download ${url}
	done
}

function main
{
	local -i i=0
	while [ ${i} -lt 2 ];
	do
		(
			process
		)&
		i=`expr ${i} + 1`
	done
	wait
}

main
exit

こいつを適当な名前(hoge-list.sh)で保存。hoge.sh(ダウンロード用のスクリプト)とhoge-list(URLの書かれたリスト)と同じ場所に保存。

$ sh hoge-list.sh

2つのプロセスを平行に走らせて、同じリストファイルからURLを読んでいる。平行に走らせるプロセスの数は同時にダウンロードする数に対応している。ダウンロード用のスクリプト内における「分割数」と「プロセスの数」の積がホストに対して張るコネクションの数に対応しているので、増やしすぎると302 Foundでエラーページにリダイレクトされる。ダウンロード用のスクリプトの中でcURLに与えるリトライ数を増やしておけば対応可能だが、YourFileHost側からすれば迷惑な話だろう。分割数を減らすかプロセス数を減らすことをお勧めする。2プロセス走らせても2倍のスピードになるわけではない。実際、1.5倍くらいのスピードになった。


1.5 参考

  1. yourfilehostの裏API (Yusukebe::Tech)
  2. 2008-02-03 - 駆け馬に無知
  3. McURL - Multiple cURL
  4. cURL - How To Use (マニュアルページ日本語訳)
  5. cURL - Manual - Japanese Translation
  6. シェルスクリプトのデバッグ - UNIX & Linux コマンド・シェルスクリプト リファレンス
  7. curlの使い方
  8. 【コラム】OS X ハッキング! (33) それにつけてもダウンローダはcurl | パソコン | マイコミジャーナル
  9. curl リクエスト|request ヘッダ|header 保存 - Google 検索
  10. コマンドラインからでもブラウザからでもWgetでダウンロード - SourceForge.JP Magazine
  11. Linuxの使い方 - シェルスクリプトの作り方
  12. man lockfile(1)

1.6 技術情報

ここのセクションはメモ書きですな。IE6.0で動画再生してWireSharkでパケット解析したときの。


1.6.1 ブラウザで動画再生開始した際に流れたリクエストヘッダ

おそらく下に挙げたパケットがフラッシュビデオファイルをダウンロードする際のリクエストヘッダだろう。これと同じヘッダをcurlやwgetで発行できればflvファイルがダウンロードできるはずだ。

GET /unit1/flash8/cd/cd94412311d23d23d447497cdc5f5761.flv HTTP/1.1
Accept: */*
Referer: http://www.yourfilehost.com/flash/flvplayer7.swf?autoStart=0&no_skin_menu=1&video=http%3A%2F%2Fwww.yourfilehost.com%2Fvideo-embed.php%3Fvidl
x-flash-version: 9,0,28,0
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322)
Host: cdn.yourfilehost.com
Connection: Keep-Alive
Cookie: media_views=2; yfh_cids=%7C1227611186%3A3adc5c53ef9234cdc53dc01d0b5d7a1b%7C%7C1227611609%3Acd94412311d23d23d447497cdc5f5761%7C; yfh_views=2; yfh_ac=active; yfh_af=off; __utma=83567518.757577051.1227611203.1227611203.1227611203.1; __utmb=83567518; __utmc=83567518; __utmz=83567518.1227611203.1.1.utmccn=(direct)|utmcsr=(direct)|utmcmd=(none); cdnlock=ip%3D219.126.168.136%7Eexpires%3D1227611913%7Eaccess%3D%2Funit1%2F%2A%7Emd5%3Dd152af2c2fff38e8ba0e9b174ac7ec46; from=noref; lfrom=noref; idcheck=1227611204; count_visits=1

cookieがないと403 Forbiddenが返されてダウンロードできない。また、目的のflvのURL側からないとダウンロードできない。このCookieとURLを取得するのにもう一手間必要。


1.6.2 cookieとURL取得のためのリクエストヘッダ

GET /video-embed.php?vidlink=&cid=3adc5c53ef9234cdc53dc01d0b5d7a1b&adult=1&cat=video&file=rankouplay_part01.wmv&family=off&key=219.126.168&cdn=1&f=flash8&? HTTP/1.1
Accept: */*
Referer: http://www.yourfilehost.com/flash/flvplayer7.swf?autoStart=0&no_skin_menu=1&video=http%3A%2F%2Fwww.yourfilehost.com%2Fvideo-embed.php%3Fvidl
x-flash-version: 9,0,28,0
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322)
Host: www.yourfilehost.com
Connection: Keep-Alive
Cookie: media_views=1; yfh_cids=%7C1227611186%3A3adc5c53ef9234cdc53dc01d0b5d7a1b%7C; yfh_views=1; yfh_ac=active; yfh_af=off; __utma=83567518.757577051.1227611203.1227611203.1227611203.1; __utmb=83567518; __utmc=83567518; __utmz=83567518.1227611203.1.1.utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)

URLは/media.php?cat=video&file=rankouplay_part02.wmvで送られてきた内容にかかれている。これで送られてきた内容を解析してダウンロードするflvのURLを決める。


1.6.3 ブラウザアドレス入力欄に書いたアドレスの取得時に流れたリクエストヘッダ

GET /media.php?cat=video&file=rankouplay_part02.wmv HTTP/1.1
Accept: */*
Accept-Language: ja
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322)
Host: www.yourfilehost.com
Connection: Keep-Alive
Cookie: __utma=83567518.757577051.1227611203.1227611203.1227611203.1; __utmz=83567518.1227611203.1.1.utmccn=(direct)|utmcsr=(direct)|utmcmd=(none)

なぜかcookieがセットされている。あらかじめ消しておいたはずだが。


1.6.4 未ダウンロード部分へのシーク

未ダウンロード部分へのシークができればその際に流れたパケットをみて分割ダウンロード部分を書こうと思ったのだが、yourfilehostの場合シークできるのはダウンロード済みの部分だけ。と言うことで分割ダウンロードはyourfilehost側からすればあまりうれしくないことなのかもしれない。


サイトマップ

  1. CSS > Webサイトのレイアウトの話
  2. DVDリッピングしてaviファイルにするときの計算方法
  3. Debian > インストールメモ
  4. Memo > One Line Diary
  5. Memo > To-Doリスト
  6. Memo > iswebの自動挿入広告の文字コードに関する考察
  7. Memo > リンクとメモ
  8. Memo > 物理屋の独り言
  9. Misc > High Performance Computing(HPC)
  10. PC過去の遺物集
  11. Perl > 1行スクリプト覚書 with Active Perl
  12. Perl > Perl実験室でWeb雑考
  13. Perl > XML::TreePPでXMLサイトマップファイルを生成
  14. Perl > e.cgi のページ ProjectRotation8
  15. Perl > クエリを連想配列で受け取るスマートな方法
  16. Perl > サーバーにアップロードしたcgiのエラーチェック
  17. Perl > ブリコラージュ的 cgi
  18. Programing > プログラムの素人が不思議に思ったこと
  19. Services > Gmail Tips
  20. Services > YourFileHostダウンローダ
  21. Services > twitterはじめました。
  22. Tech > MathMLを使ってみる
  23. Tech > Windows 2000 Professional でLaTeX組版システムを使う
  24. Tech > coLinuxの導入
  25. Tech > サイトのミラーリング
  26. Terapadで作るLaTeX統合環境
  27. Tools > Opera > 設定の諸々
  28. Tools > bashのメモ
  29. Tools > lit2ptoのページ
  30. Tools > vimの設定とtips
  31. Tools > よく使う機能のメモと設定のメモ
  32. VMware > ホストOSがWindows XP Home SP2でゲストOSがVine Linux 4.1
  33. Vine > SSHの暗号化経路を経由してSambaサーバの共有ディレクトリをマウント
  34. Vine Linux > LaTeXでpdf文書作成
  35. Vine Linux > Libretto L1に載せる
  36. Vine Linux > SSH関係の諸々メモ
  37. Vine Linux > サーバを立てたときのメモ
  38. Vine Linux > ソフトウェアRAID
  39. Vine Linux > デスクトップとして使う場合に必要な設定
  40. Wanderlust > inter7でIMAP4
  41. Web Etcetera > サーバー上でファイルを直接編集することについて
  42. Web Etcetera > 検索エンジンが自分のサイトをどのように認識しているか
  43. Web Etcetera > 無料ホームページスペースの広告削除は真か偽か
  44. Winamp > StreamRipperで全自動リッピング
  45. Winamp > タスクマネージャを使って目覚まし時計
  46. Windows > robocopyでフォルダ間同期
  47. Windows > 手動でコーデックをインストールする
  48. gnuplotのプロットギャラリー
  49. rsyncでディレクトリの内容を同期する
  50. wgetのメモ
  51. ネットワーク上にメモ帳を置く
  52. ハードウェア > HDDの再利用
  53. ハードウェア > 安定で快適なマシンはハードから
  54. ブリコラージュ的メールマガジン一括登録解除方法
  55. 初めに
  56. 情報基礎演習UNIX
  57. 窓たちと正く付き合うにはショートカットキーから

コメント


pin

[PR]肢Ղ̗p⏉񖳗:KȌ֓܂{iӒ