2017-02-15 2 views
3

Мне нужен эффективный способ загрузки многомиллионных файлов из списка URL-адресов в текстовом файле. Я хочу, чтобы файлы были сохранены с новыми именами (из другого текстового файла или где бы то ни было), поскольку URL-адреса являются длинными, динамически генерируемыми тарабарщинами и могут вызывать проблемы с максимальными длинами имен файлов и т. Д.Загрузите небольшие файлы

Я сначала попробовал wget, но был ограничен тот факт, что вы можете либо указать список URL-адресов из текстового файла, например:

wget.exe -i myURLlist.txt 

или переименовать один загруженный файл с новым именем, например:

wget.exe -O myfilename1.jpg http://www.foo.com/longgibberish976876....2131.jpg 

, но не оба. Поэтому мой скрипт должен был выполнить wget индивидуально (используя второй метод) для каждого файла. Это невероятно медленно из-за перезапуска TCP-соединения каждый раз и других накладных расходов (если вы передаете список URL-адресов в текстовом файле, wget пытается повторно использовать соединение, но тогда я не могу указать имена файлов).

Затем я попробовал завиток, который позволяет передавать несколько URL-адресов и имена файлов с помощью аргументов командной строки. например:

curl.exe 
-o myfilename1.jpg http://www.foo.com/longgibberish976876....2131.jpg 
-o myfilename2.jpg http://www.foo.com/longgibberish324....32432.jpg 
-o ..... 

Это было увеличение скорости, так как завиток будет пытаться повторно использовать то же соединение для все URL, переданного ему. Тем не менее, я был ограничен партиями из 20 URL-адресов, прежде чем он начал пропускать файлы. Я не подтвердил, почему это произошло, но подозреваем, что максимальная длина в командной строке могла быть превышена. В любом случае это, конечно, не будет масштабироваться до миллиона или около того файлов. Я не нашел вариант передать текстовый файл для завивки так же, как вы можете, с помощью wget.

Какие варианты остались? Есть ли какой-то синтаксис для двух программ, которые я уже пробовал, о которых я не знаю, или мне нужен какой-то другой инструмент?

+0

Я боюсь, что вы нажмете на стену, которую вам нужно будет перепрыгнуть с помощью некоторых пользовательских программ. Поскольку SO - это онлайн-сообщество для программистов, отвечающих на вопросы программирования, я предполагаю, что вы не боитесь вникать в программирование собственного решения. Попробуйте это на своем языке выбора и вернитесь, если вы столкнетесь с определенной проблемой программирования. –

ответ

0

С curl вам нужен только файл с форматом

output = filename1.jpg 
url = http://.... 
output = filename2.jpg 
url = http://.... 

и использовать переключатель -K file, чтобы обработать его или динамически генерировать его и прочитать список из стандартного ввода с -K -.

Таким образом, из списка URL-адресов, вы можете попробовать с этим кодом

@echo off 
    setlocal enableextensions disabledelayedexpansion 

    set "count=0" 
    (for /f "usebackq delims=" %%a in ("urlList.txt") do @(
     >nul set /a "count+=1" 
     call echo(output = file%%^^count%%.jpg 
     echo(url = %%a 
    )) | curl -K - 

Или, для действительно больших списков URL (for /f необходимо загрузить полный файл в память), вы можете использовать

@echo off 
    setlocal enableextensions disabledelayedexpansion 

    < urlList.txt (
     cmd /e /v /q /c"for /l %%a in (1 1 2147483647) do set /p.=&&(echo(output = file%%a.jpg&echo(url = !.!)||exit" 
    ) | curl -K - 

отмечает:

  1. Поскольку арифметические операции в пакетных файлах ограничены значениями ниже 2 , эти образцы не сработают, если ваши списки содержат более 2147483647 URL-адресов.

  2. Первый образец не работает с URL-адресами дольше, чем aprox. 8180 символов

  3. Второй образец не работает с URL-адресами длиннее 1021 символов и будет завершен в пустых строках исходного файла.

1

Это латентность что будет делать вам. В нормальном, последовательный процесс, если есть задержка участвует 1-3 секунд на файл, вы будете платить их все, один за другим и тратить 1-3 миллиона секунд на загрузку миллиона файлов.

Хитрость заключается в том, чтобы оплачивать задержки Параллельно - потушить, скажем 64, выполнить параллельные запросы и подождать 1-3 секунды, чтобы они все вернулись - вместо 180 секунд, если они выполняются последовательно.

Я бы по достоинству оценил GNU Parallel к вам, который хотя и относится к Unix, работает под Cygwin. Посмотрите несколько руководств.

Команда будет что-то вроде этого, чтобы сделать 64 кудри в то время:

parallel -j 64 -a filelist.txt curl {} 
0

Вы можете использовать утилиту aria2 скачать с:

  • в -j [NUMBER] вариант для одновременных загрузок
  • параметр -i [FILENAME] для предоставления URL-адресов и имени выходных файлов в текстовом файле

Например, предположим, что files.txt содержит:

http://rakudo.org/downloads/star/rakudo-star-2017.01.tar.gz 
    out=test1.file 
http://rakudo.org/downloads/star/rakudo-star-2017.01.dmg 
    out=test2.file 
http://rakudo.org/downloads/star/rakudo-star-2017.01-x86_64%20(JIT).msi 
    out=test3.file 
http://rakudo.org/downloads/star/rakudo-star-2016.11.tar.gz 
    out=test4.file 

Тогда вы просто запустить, например, aria2c -j4 -i files.txt, чтобы загрузить все эти файлы параллельно. Не уверен, как это работает с миллионами небольших файлов, хотя, но я думаю, это стоит того.

Смежные вопросы