我想从网站下载一些页面并使用curl
成功完成,但我想知道是否某种方式curl
一次下载多个页面,就像大多数下载管理器一样,它会加速一点点。是否可以在curl
命令行实用程序中执行此操作?
我正在使用的当前命令是
curl 'http://www...../?page=[1-10]' 2>&1 > 1.html
这里我从1到10下载页面并将它们存储在名为1.html
的文件中。
此外,curl
是否可以将每个网址的输出写入单独的文件URL.html
,其中URL
是正在处理的网页的实际网址。
答案 0 :(得分:39)
我的回答有点迟了,但我相信所有现有的答案都会有点短暂。我这样做的方式是使用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和带有-J
标志的BSD上)。使用GNU Parallel,命令也不那么笨拙:
parallel --jobs 2 curl -O -s http://example.com/?page{}.html ::: {1..10}
答案 1 :(得分:24)
嗯,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
答案 2 :(得分:5)
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
答案 3 :(得分:4)
对于启动并行命令,为什么不使用古老的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 $@
注意最后两行应以TAB字符(而不是8个空格)开头,否则make将不接受该文件。
现在你运行:
make -k -j 5
我使用的curl命令将输出存储在1.html.tmp
中,并且只有当curl命令成功时,它才会被重命名为1.html
(通过下一行的mv
命令) 。因此,如果某些下载失败,您只需重新运行相同的make
命令,它将恢复/重试下载第一次无法下载的文件。一旦成功下载了所有文件,make将报告没有其他任何工作要做,所以再运行一次是“安全”没有任何害处。
(-k
开关告诉make继续下载其余文件,即使单个下载失败也是如此。)
答案 4 :(得分:2)
如果您的系统具有pidof
或pgrep
之类的命令,则运行有限数量的过程很容易,在给定进程名称的情况下,返回pids(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)
脚本的卷曲线未经测试。
答案 5 :(得分:2)
curl
和 wget
不能以并行块下载单个文件,但有替代方案:
答案 6 :(得分:1)
我想出了一个基于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 :(得分:1)
从 7.68.0
开始 curl 可以并行获取多个 url。此示例将从具有 3 个并行连接的 urls.txt
文件中获取网址:
curl --parallel --parallel-immediate --parallel-max 3 --config urls.txt
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"
答案 8 :(得分:0)
我不确定卷曲,但你可以使用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/
答案 9 :(得分:0)
从7.66.0开始,curl
实用程序最终内置了对在单个非阻塞过程中并行下载多个URL的支持,与{{ 1}}和背景生成,在大多数情况下:
xargs
这将并行下载18个链接,并将它们写到18个不同的文件中,也同时进行。 Daniel Stenberg对此功能的正式公告在这里:https://daniel.haxx.se/blog/2019/07/22/curl-goez-parallel/