Webサイトからいくつかのページをダウンロードしたいのですが、curl
を使用して正常にダウンロードしましたが、ほとんどのダウンロードマネージャーと同じようにcurl
が一度に複数のページをダウンロードするのではないかと思っていました。少しスピードアップしてください。 curl
コマンドラインユーティリティでそれを行うことは可能ですか?
私が使用している現在のコマンドは
curl 'http://www...../?page=[1-10]' 2>&1 > 1.html
ここでは、1から10までのページをダウンロードして、1.html
という名前のファイルに保存しています。
また、curl
が各URLの出力を別のファイルURL.html
に書き込むこともできます。ここで、URL
は処理中のページの実際のURLです。
まあ、curl
は単なるUNIXプロセスです。これらのcurl
プロセスをいくつでも並行して実行し、それらの出力を異なるファイルに送信できます。
curl
は、URLのファイル名部分を使用してローカルファイルを生成できます。 -O
オプション(man curl
詳細については)。
次のようなものを使用できます
urls="http://example.com/?page1.html http://example.com?page2.html" # add more URLs here
for url in $urls; do
# run the curl job in the background so we can start another job
# and disable the progress bar (-s)
echo "fetching $url"
curl $url -O -s &
done
wait #wait for all background jobs to terminate
私の答えは少し遅いですが、既存の答えはすべて少し足りないと思います。このようなことを行う方法は、サブプロセスで指定された数のコマンドを実行できるxargs
を使用することです。
私が使用するワンライナーは、単に:
$ seq 1 10 | xargs -n1 -P2 bash -c 'i=$0; url="http://example.com/?page${i}.html"; curl -O -s $url'
これはいくつかの説明が必要です。の用法 -n 1
は、一度に1つの入力引数を処理するようにxargs
に指示します。この例では、数字1 ... 10
はそれぞれ個別に処理されます。そして-P 2
は、すべての入力引数が処理されるまで、それぞれが単一の引数を処理する2つのサブプロセスを常に実行し続けるようにxargs
に指示します。
これはシェルのMapReduceと考えることができます。または、おそらくマップフェーズだけかもしれません。とにかく、それはあなたがあなたのマシンをフォーク爆撃しないことを確実にしながら多くの仕事を成し遂げるための効果的な方法です。シェルのforループで同様のことを行うことは可能ですが、最終的にプロセス管理を行うことになります。これは、xargs
のこの非常に優れた使用法がどれほど素晴らしいかを理解すると、かなり無意味に見え始めます。
更新:xargs
を使用した私の例は改善できると思います(少なくともMac OS XとBSDでは-J
国旗)。 GNU Parallelの場合、コマンドも扱いにくくなります。
parallel --jobs 2 curl -O -s http://example.com/?page{}.html ::: {1..10}
Curlは、ファイルを分割してファイルのダウンロードを高速化することもできます。
$ man curl |grep -A2 '\--range'
-r/--range <range>
(HTTP/FTP/SFTP/FILE) Retrieve a byte range (i.e a partial docu-
ment) from a HTTP/1.1, FTP or SFTP server or a local FILE.
以下は、必要な数の並行プロセスでcurlを自動的に起動するスクリプトです。 https://github.com/axelabs/splitcurl
並列コマンドの起動には、由緒あるmake
コマンドラインユーティリティを使用してください。並列実行と依存関係の追跡などをサポートしています。
どうやって?ファイルをダウンロードするディレクトリで、次の内容でMakefile
という新しいファイルを作成します。
# which page numbers to fetch
numbers := $(Shell seq 1 10)
# default target which depends on files 1.html .. 10.html
# (patsubst replaces % with %.html for each number)
all: $(patsubst %,%.html,$(numbers))
# the rule which tells how to generate a %.html dependency
# $@ is the target filename e.g. 1.html
%.html:
curl -C - 'http://www...../?page='$(patsubst %.html,%,$@) -o [email protected]
mv [email protected] $@
[〜#〜] note [〜#〜]最後の2行は(8スペースの代わりに)TAB文字で始まる必要があります。そうでない場合、makeはファイルを受け入れません。
今すぐ実行します:
make -k -j 5
私が使用したcurlコマンドは、出力を1.html.tmp
に格納し、curlコマンドが成功した場合にのみ、1.html
に名前が変更されます(次の行のmv
コマンドによって)。したがって、一部のダウンロードが失敗した場合、同じmake
コマンドを再実行するだけで、初回のダウンロードに失敗したファイルのダウンロードが再開/再試行されます。すべてのファイルが正常にダウンロードされると、makeはそれ以上実行する必要がないことを報告します。そのため、「安全」になるためにもう一度実行しても害はありません。
(-k
スイッチは、1回のダウンロードが失敗した場合でも、残りのファイルをダウンロードし続けるようmakeに指示します。)
システムにpidof
またはpgrep
のようなコマンドがあり、プロセス名を指定するとpidを返す場合、限られた数のプロセスを簡単に実行できます(pidの数は、実行中の数を示します)。
このようなもの:
#!/bin/sh
max=4
running_curl() {
set -- $(pidof curl)
echo $#
}
while [ $# -gt 0 ]; do
while [ $(running_curl) -ge $max ] ; do
sleep 1
done
curl "$1" --create-dirs -o "${1##*://}" &
shift
done
このように呼び出すには:
script.sh $(for i in `seq 1 10`; do printf "http://example/%s.html " "$i"; done)
スクリプトのカールラインはテストされていません。
fmt
とxargs
に基づいたソリューションを思いつきました。アイデアは、中括弧http://example.com/page{1,2,3}.html
内に複数のURLを指定し、xargs
と並行して実行することです。以下は3つのプロセスでダウンロードを開始します:
seq 1 50 | fmt -w40 | tr ' ' ',' \
| awk -v url="http://example.com/" '{print url "page{" $1 "}.html"}' \
| xargs -P3 -n1 curl -o
したがって、ダウンロード可能な4行のURLが生成され、xargs
に送信されます
curl -o http://example.com/page{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}.html
curl -o http://example.com/page{17,18,19,20,21,22,23,24,25,26,27,28,29}.html
curl -o http://example.com/page{30,31,32,33,34,35,36,37,38,39,40,41,42}.html
curl -o http://example.com/page{43,44,45,46,47,48,49,50}.html
7.66.0以降、curl
ユーティリティには、単一の非ブロッキングプロセス内で複数のURLを並行してダウンロードするためのサポートが組み込まれました。これは、xargs
とバックグラウンドのスポーン、ほとんどの場合:
curl -Z 'http://httpbin.org/anything/[1-9].{txt,html}' -o '#1.#2'
これにより、18個のリンクが同時にダウンロードされ、18個の異なるファイルに並列に書き込まれます。 Daniel Stenbergによるこの機能の公式発表はこちらです https://daniel.haxx.se/blog/2019/07/22/curl-goez-parallel/
カールについてはわかりませんが、 wget を使用してそれを行うことができます。
wget \
--recursive \
--no-clobber \
--page-requisites \
--html-extension \
--convert-links \
--restrict-file-names=windows \
--domains website.org \
--no-parent \
www.website.org/tutorials/html/