如何下载 csv 中的 URL 并根据列值命名输出

Posted

技术标签:

【中文标题】如何下载 csv 中的 URL 并根据列值命名输出【英文标题】:How to download URLs in a csv and naming outputs based on a column value 【发布时间】:2019-07-13 19:04:12 【问题描述】:

1。操作系统:Linux / Ubuntu x86/x64

2。任务:

编写一个 Bash shell 脚本以下载(大)csv 中的 URL(尽可能快/同时)并在列值上命名每个输出。

2.1 示例输入:

一个包含如下行的 CSV 文件:

001,http://farm6.staticflickr.com/5342/a.jpg
002,http://farm8.staticflickr.com/7413/b.jpg
003,http://farm4.staticflickr.com/3742/c.jpg

2.2 示例输出:

文件夹中的文件,outputs,包含以下文件:

001.jpg
002.jpg
003.jpg

3。我的尝试:

我主要尝试了两种风格。

1。使用下载工具的内部支持

ariasc 为例,它支持使用-i 选项导入要下载的URL 文件,并且(我认为)它会以最大速度并行处理它。它确实有--force-sequential 选项来强制按行顺序下载,但我没能找到一种方法来实现命名部分。

2。先拆分

将文件拆分成文件并运行如下脚本来处理它:

#!/bin/bash
INPUT=$1

while IFS=, read serino url
do 
    aria2c -c "$url" --dir=outputs --out="$serino.jpg"
done < "$INPUT"

但是,这意味着对于每一行,它将再次重新启动aria2c,这似乎既费时又降低了速度。 虽然,可以多次在 bash 命令中运行脚本以获得“shell 级”并行性,但这似乎不是最好的方法。

有什么建议吗? 谢谢,

【问题讨论】:

参考:CURL 应该可以帮助你.. ***.com/questions/16362402/… 另见Can aria2c download list of urls with specific file names for each。 【参考方案1】:

aria2c 在输入文件中支持所谓的选项行。来自man aria2c

-i, --input-file= 下载 FILE 中列出的 URI。您可以通过将多个 URI 放在由 TAB 字符分隔的单行上来为单个实体指定多个源。此外,可以在每个 URI 行之后指定选项。选项行必须以一个或多个空格字符(SPACE 或 TAB)开头,并且每行只能包含一个选项。

以后

这些选项与命令行选项中的含义完全相同,但它只适用于它所属的 URI。请注意,对于输入文件中的选项 -- 前缀必须被去除。

您可以将您的 csv 文件转换为 aria2c 输入文件:

sed -E 's/([^,]*),(.*)/\2\n  out=\1/' file.csv | aria2c -i - 

这会将您的文件转换为以下格式并在其上运行aria2c

http://farm6.staticflickr.com/5342/a.jpg
  out=001
http://farm8.staticflickr.com/7413/b.jpg
  out=002
http://farm4.staticflickr.com/3742/c.jpg
  out=003

但是,这不会创建文件001.jpg002.jpg,...而是001002,...因为这是您指定的。指定带有扩展名的文件名或从 URL 中猜测扩展名。

如果扩展名总是 jpg 你可以使用

sed -E 's/([^,]*),(.*)/\2\n  out=\1.jpg/' file.csv | aria2c -i -

要从 URL 中提取扩展名,请使用

sed -E 's/([^,]*),(.*)(\..*)/\2\3\n  out=\1\3/' file.csv | aria2c -i -

警告:当且仅当每个 URL 都以扩展名结尾时才有效。例如,由于缺少扩展,001,domain.tld/abc 行根本不会被转换,导致aria2c 在“URL”001,domain.tld/abc 上失败。

【讨论】:

考虑到实际下载速度,选择这个作为ans。图片的实际数量是 960k,所以当我直接放入包含 URL 的文件时,aria2c 会崩溃。可以使用名为split 的bash 命令将文件按行拆分为小文件。 split -l/5 $FILE,例如。然后一一处理。 你拯救了我的一天。【参考方案2】:

使用所有标准实用程序,您可以并行下载:

tr '\n' ',' < file.csv |
xargs -P 0 -d , -n 2 bash -c 'curl -s "$2" -o "$1.jpg"' -

xargs 中的-P 0 选项允许它并行运行命令(每个核心处理器一个)

【讨论】:

如果 CSV 很大,您希望限制并行任务的数量。如果您同时运行几十个以上,您只会拥塞您的网络。 我认为-P 0 控制它。 ^t 在man xargs 中说If max-procs is 0, xargs will run as many processes as possible at a time 这是 CPU 允许的数量,但它很容易启动,超出您的网络对 I/O 绑定任务的处理能力。 我一直使用 xargs -P 0 对包含 400k-500k 记录的输入文件运行 curl 命令,从未遇到任何阻塞问题。 关系有些复杂。 500 次使用快速网络获取少量连接良好的站点就可以了; 500 次使用快速 CPU 对大量连接性较差的小型站点进行 fetch 会导致您的网络拥塞。

以上是关于如何下载 csv 中的 URL 并根据列值命名输出的主要内容,如果未能解决你的问题,请参考以下文章

我需要计算行的实例并根据多个列值删除重复项

Pandas:如何根据其他列值的条件对列进行求和?

根据 NaN 将列值替换为 0 或 1 [重复]

如何从beeline hive以csv2格式下载数据?

根据列值拆分大型 csv 文本文件

从CSV文件中读取jpg图片的URL地址并多线程批量下载