Linux 使用Curl命令行实用程序并行下载
我想从一个网站上下载一些页面,我使用Linux 使用Curl命令行实用程序并行下载,linux,shell,unix,curl,Linux,Shell,Unix,Curl,我想从一个网站上下载一些页面,我使用curl成功地完成了下载,但我想知道curl是否会像大多数下载管理器那样一次下载多个页面,这样会稍微加快速度。是否可以在curl命令行实用程序中执行此操作 我当前使用的命令是 curl 'http://www...../?page=[1-10]' 2>&1 > 1.html 这里我下载了从1到10的页面,并将它们存储在名为1.html的文件中 另外,curl是否可以将每个URL的输出写入单独的文件,例如URL.html,其中URL是正在处
curl
成功地完成了下载,但我想知道curl
是否会像大多数下载管理器那样一次下载多个页面,这样会稍微加快速度。是否可以在curl
命令行实用程序中执行此操作
我当前使用的命令是
curl 'http://www...../?page=[1-10]' 2>&1 > 1.html
这里我下载了从1到10的页面,并将它们存储在名为1.html
的文件中
另外,
curl
是否可以将每个URL的输出写入单独的文件,例如URL.html
,其中URL
是正在处理的页面的实际URL。我不确定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
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.
$man curl | grep-A2'\--range'
-r/--范围
(HTTP/FTP/SFTP/FILE)检索字节范围(即部分docu-
从HTTP/1.1、FTP或SFTP服务器或本地文件。
下面是一个脚本,它将自动启动curl,并具有所需数量的并发进程:要启动并行命令,为什么不使用古老的
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 $@.tmp
mv $@.tmp $@
注意最后两行应以制表符开头(而不是8个空格),否则make将不接受该文件
现在您只需运行:
make -k -j 5
我使用的curl命令将输出存储在1.html.tmp
中,只有curl命令成功,它才会被重命名为1.html
(通过下一行的mv
命令)。因此,如果某些下载失败,您可以重新运行相同的make
命令,它将恢复/重试下载第一次下载失败的文件。一旦成功下载了所有文件,make将报告没有更多的工作要做,所以为了“安全”再运行一次也没有坏处
(开关告诉make即使一次下载失败也要继续下载其余的文件。)我的答案有点晚了,但我相信所有现有的答案都有点短。我这样做的方式是使用
xargs
,它能够在子流程中运行指定数量的命令
我将使用的一个班轮是:
$ seq 1 10 | xargs -n1 -P2 bash -c 'i=$0; url="http://example.com/?page${i}.html"; curl -O -s $url'
这需要一些解释。使用-n1
指示xargs
一次处理一个输入参数。在本例中,数字1。。。10
分别进行处理。和-p2
告诉xargs
始终保持两个子进程运行,每个子进程处理一个参数,直到处理完所有输入参数
您可以将其视为shell中的MapReduce。或者可能只是地图阶段。不管怎样,这是一个有效的方法来完成大量的工作,同时确保你不会用叉子炸你的机器。可以在shell中的for循环中执行类似的操作,但最终会执行流程管理,一旦您意识到使用xargs
有多么疯狂,这就变得毫无意义了
更新:我怀疑我使用xargs
的示例可以改进(至少在带有-J
标志的Mac OS X和BSD上)。使用GNU Parallel,命令的笨拙程度也会有所降低:
parallel --jobs 2 curl -O -s http://example.com/?page{}.html ::: {1..10}
如果您的系统具有诸如
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)
这样称呼:
#!/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)
脚本的curl行未经测试。我提出了一个基于
fmt
和xargs
的解决方案。其思想是在大括号内指定多个URLhttp://example.com/page{1,2,3}.html
并与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对此功能的官方声明如下:
curl
和wget
无法以并行块形式下载单个文件,但还有其他选择:
- (用C书写,可在Deb回购协议中获得)
axel-n 5
- (用C书写,可在Deb回购协议中获得)
wget2——最大线程数=5
- (用围棋书写)
hget-n5
- (用围棋书写)
pget-p5
aria2c-x5
lftp-n5
7.68.0开始,curl可以并行获取多个URL。此示例将使用3个parall从urls.txt
文件中获取URL
axel -n 5 <url>
wget2 --max-threads=5 <url>
lftp -n 5 <url>
hget -n 5 <url>
pget -p 5 <url>
curl --parallel --parallel-immediate --parallel-max 3 --config urls.txt
url = "example1.com"
output = "example1.html"
url = "example2.com"
output = "example2.html"
url = "example3.com"
output = "example3.html"
url = "example4.com"
output = "example4.html"
url = "example5.com"
output = "example5.html"