使用Curl命令行实用程序并行下载

我想从一个网站下载一些页面,并且使用curl成功地完成了这个工作,但是我想知道是否像下载pipe理器那样一次下载多个页面,这会加速一些事情。 是否有可能在curl命令行工具中做到这一点?

我正在使用的当前命令是

 curl 'http://www...../?page=[1-10]' 2>&1 > 1.html 

我在这里下载从1到10的页面,并将它们存储在一个名为1.html的文件中。

另外, curl可以将每个URL的输出写成单独的文件,如URL.html ,其中URL是正在处理的页面的实际URL。

Solutions Collecting From Web of "使用Curl命令行实用程序并行下载"

那么, 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指示xargs处理一个输入参数。 在这个例子中,数字1 ... 10分别被处理。 并且-P 2告诉xargs保持2个子进程一直运行,每个子进程处理一个参数,直到所有的输入参数都被处理完毕。

你可以把它想象成shell中的MapReduce。 或者也许只是地图阶段。 无论如何,这是一个有效的方式来完成大量的工作,同时确保您不要叉炸机器。 有可能在shell中的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 (ie 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 eg 1.html %.html: curl -C - 'http://www...../?page='$(patsubst %.html,%,$@) -o $@.tmp mv $@.tmp $@ 

注意最后两行应以TAB字符(而不是8个空格)开始,否则make将不接受该文件。

现在你只需运行:

 make -k -j 5 

我使用的curl命令将输出存储在1.html.tmp并且只有在curl命令成功的情况下,它才会被重命名为1.html (通过下一行的mv命令)。 因此,如果某些下载失败,您可以重新运行相同的make命令,它会在第一次恢复/重试下载失败的文件。 一旦所有文件都被成功下载,make会报告没有什么可做的事情,所以运行一个额外的时间是安全的。

-k开关告诉make继续下载其余的文件,即使一次下载失败也是如此。)

我不确定卷曲,但是你可以用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/ 

如果您的系统具有像pidofpgrep这样的命令,那么运行有限数量的过程是很容易的,在给定进程名称的情况下,返回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) 

脚本的卷曲线未经测试。