2011-12-26 42 views
22

我想從網站上下載一些頁面,並且使用curl成功完成,但是我想知道curl是否以某種方式一次下載多個頁面,就像大多數下載管理器一樣,它會加快一點點。是否有可能在curl命令行工具中執行?使用Curl命令行實用程序並行下載

我使用的電流指令

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

在這裏,我從下載1頁10並將其存儲在一個名爲1.html文件。

另外,curl是否可以將每個URL的輸出寫入單獨的文件,如URL.html,其中URL是正在處理的頁面的實際URL。

+0

預先請求查找內容長度,使用'--range'將單個文件拼接爲多個下載文件,運行多進程捲曲文件,維護塊的順序並在您序列化後立即加入它們,這是大多數開發人員正在做的事情(例如:[htcat項目](https://github.com/eladkarako/htcat)) – 2015-12-02 02:20:12

回答

22

那麼,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 
+3

讓我說我必須下載100頁...你的腳本將同時啓動100個curl實例(可能會扼殺網絡)......我們可以在任何特定時間點執行某些操作,只有curl的X個實例正在運行,只要其中一個完成其作業,該腳本就會啓動另一個實例......某些某種'Job Scheduling'?無論如何, – 2011-12-27 10:14:26

+0

+1。 – 2011-12-27 10:14:57

+0

Ravi ..這變得更加困難。您需要一個由多個進程提供服務的作業隊列。一個簡單的解決方案是將所有作業發送到UNIX批處理命令(嘗試「批處理」)。它在系統負載低於特定閾值時執行作業。所以大部分工作都會排隊,一次只能運行幾個工作。 – nimrodm 2011-12-27 19:02:08

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/ 
4

捲曲也可以通過拆分成零件加速下載的文件:

$ 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. 

下面是一個腳本,將自動啓動捲曲帶並行進程的期望數量:https://github.com/axelabs/splitcurl

2

爲了啓動並行命令,爲什麼不使用可敬的make c ommand line utility ..它支持並行執行和依賴關係跟蹤以及什麼。

怎麼樣?在您下載的文件的目錄下,創建一個名爲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 
# [email protected] is the target filename e.g. 1.html 
%.html: 
     curl -C - 'http://www...../?page='$(patsubst %.html,%,[email protected]) -o [email protected] 
     mv [email protected] [email protected] 

注意最後兩行應以TAB字符開始(而不是8個空格)或make會不接受文件。

現在,你只要運行:

make -k -j 5 

curl命令我用將輸出存儲在1.html.tmp且僅當curl命令,然後成功將在下一行被重新命名爲1.html(由mv命令)。因此,如果某些下載失敗,您可以重新運行相同的make命令,它將恢復/重試下載第一次無法下載的文件。一旦所有文件都被成功下載,make會報告沒有更多的事情要做,所以不需要額外的時間讓它「安全」運行。

(該-k開關告訴make保持下載文件的剩餘部分,即使一個單一的下載應該失敗。)

+0

「-j 5」告訴make最多並行運行5個curl命令。 – 2013-10-06 20:40:33

+0

真的是最好的解決方案,因爲它允許恢復失敗的下載並使用'make',它在任何unix系統上都很強大且可用。 – nimrodm 2015-05-06 18:20:29

31

我的回答是有點晚了,但我相信所有現有的答案的下跌只是一個小短。我這樣做的方式是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可以改善(至少在Mac OS X和BSD -J標誌)。隨着GNU並行,命令是少了幾分笨拙以及:

parallel --jobs 2 curl -O -s http://example.com/?page{}.html ::: {1..10} 
+3

另請注意,如果您擁有xargs的全功能版本,則可以簡單地執行以下操作:'seq 1 10 | xargs -I {} -P2 - curl -O -s'http://example.com/?page {} .html'' – Six 2015-07-27 06:48:23

2

運行過程的有限數量是容易的,如果你的系統有一個像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) 

腳本的捲曲線是未經測試。