Je veux télécharger certaines pages d'un site Web et je l'ai fait avec succès en utilisant curl
mais je me demandais si curl
télécharge plusieurs pages à la fois comme le font la plupart des gestionnaires de téléchargement, il le fera accélérer un peu les choses. Est-il possible de le faire dans l'utilitaire de ligne de commande curl
?
La commande actuelle que j'utilise est
curl 'http://www...../?page=[1-10]' 2>&1 > 1.html
Ici, je télécharge des pages de 1 à 10 et les stocke dans un fichier nommé 1.html
.
De plus, est-il possible que curl
écrive la sortie de chaque URL pour séparer le fichier, par exemple URL.html
, où URL
est l'URL réelle de la page en cours de traitement.
Eh bien, curl
n'est qu'un simple processus UNIX. Vous pouvez avoir autant de ces processus curl
qui s'exécutent en parallèle et envoient leurs sorties à différents fichiers.
curl
peut utiliser la partie nom de fichier de l'URL pour générer le fichier local. Utilisez simplement le -O
option (man curl
pour plus de détails).
Vous pouvez utiliser quelque chose comme le suivant
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
Ma réponse est un peu tardive, mais je pense que toutes les réponses existantes sont un peu courtes. La façon dont je fais des choses comme ça est avec xargs
, qui est capable d'exécuter un nombre spécifié de commandes dans des sous-processus.
Le one-liner que j'utiliserais est simplement:
$ seq 1 10 | xargs -n1 -P2 bash -c 'i=$0; url="http://example.com/?page${i}.html"; curl -O -s $url'
Cela mérite une explication. L'utilisation de -n 1
demande à xargs
de traiter un seul argument d'entrée à la fois. Dans cet exemple, les nombres 1 ... 10
sont chacun traités séparément. Et -P 2
indique à xargs
de maintenir 2 sous-processus en cours d'exécution, chacun traitant un seul argument, jusqu'à ce que tous les arguments d'entrée aient été traités.
Vous pouvez penser à cela comme MapReduce dans le Shell. Ou peut-être juste la phase Carte. Quoi qu'il en soit, c'est un moyen efficace de faire beaucoup de travail tout en vous assurant de ne pas bombarder votre machine. Il est possible de faire quelque chose de similaire dans une boucle for dans un shell, mais finissez par faire de la gestion des processus, qui commence à sembler assez inutile une fois que vous réalisez à quel point cette utilisation de xargs
est incroyablement géniale.
Mise à jour: je soupçonne que mon exemple avec xargs
pourrait être amélioré (au moins sur Mac OS X et BSD avec le -J
drapeau). Avec GNU Parallel, la commande est également un peu moins lourde:
parallel --jobs 2 curl -O -s http://example.com/?page{}.html ::: {1..10}
Curl peut également accélérer le téléchargement d'un fichier en le divisant en plusieurs parties:
$ 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.
Voici un script qui lancera automatiquement curl avec le nombre souhaité de processus simultanés: https://github.com/axelabs/splitcurl
Pour lancer des commandes parallèles, pourquoi ne pas utiliser l'utilitaire de ligne de commande vénérable make
. Il prend en charge l'exécution parallèle et le suivi des dépendances et ainsi de suite.
Comment? Dans le répertoire où vous téléchargez les fichiers, créez un nouveau fichier appelé Makefile
avec le contenu suivant:
# 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 Les deux dernières lignes doivent commencer par un caractère TAB (au lieu de 8 espaces) ou make n'acceptera pas le fichier.
Vous lancez maintenant:
make -k -j 5
La commande curl que j'ai utilisée stockera la sortie dans 1.html.tmp
et seulement si la commande curl réussit, elle sera renommée 1.html
(par la commande mv
sur la ligne suivante). Ainsi, si un téléchargement échoue, vous pouvez simplement réexécuter la même commande make
et il reprendra/réessayera le téléchargement des fichiers qui n'ont pas pu être téléchargés la première fois. Une fois que tous les fichiers ont été téléchargés avec succès, make indiquera qu'il n'y a plus rien à faire, donc il n'y a aucun mal à l'exécuter une fois de plus pour être "sûr".
(Le -k
le commutateur indique à make de continuer à télécharger le reste des fichiers même si un seul téléchargement devait échouer.)
Exécuter un nombre limité de processus est facile si votre système a des commandes comme pidof
ou pgrep
qui, étant donné un nom de processus, retournent les pids (le nombre de pids indique combien sont en cours d'exécution).
Quelque chose comme ça:
#!/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
appeler comme ça:
script.sh $(for i in `seq 1 10`; do printf "http://example/%s.html " "$i"; done)
La ligne de bouclage du script n'est pas testée.
J'ai trouvé une solution basée sur fmt
et xargs
. L'idée est de spécifier plusieurs URL entre accolades http://example.com/page{1,2,3}.html
et exécutez-les en parallèle avec xargs
. Ce qui suit commencerait le téléchargement en 3 processus:
seq 1 50 | fmt -w40 | tr ' ' ',' \
| awk -v url="http://example.com/" '{print url "page{" $1 "}.html"}' \
| xargs -P3 -n1 curl -o
donc 4 lignes d'URL téléchargeables sont générées et envoyées à 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
Depuis la version 7.66.0, l'utilitaire curl
prend enfin en charge les téléchargements parallèles de plusieurs URL au sein d'un même processus non bloquant, ce qui devrait être beaucoup plus rapide et plus efficace en termes de ressources que xargs
et le frai de fond, dans la plupart des cas:
curl -Z 'http://httpbin.org/anything/[1-9].{txt,html}' -o '#1.#2'
Cela va télécharger 18 liens en parallèle et les écrire dans 18 fichiers différents, également en parallèle. L'annonce officielle de cette fonctionnalité par Daniel Stenberg est ici: https://daniel.haxx.se/blog/2019/07/22/curl-goez-parallel/
Je ne suis pas sûr de curl, mais vous pouvez le faire en utilisant 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/