curl
和两者都wget
提供下载一系列文件([1-100]
in curl
、{1..100}
in wget
)的能力,但它们每个都有一个缺点:curl
在序列中的每次下载之间没有简单的方法来暂停。一些服务器在多次快速下载后会切断下载,无论如何,在下载之间暂停是礼貌和适当的,以成为一名优秀的爬虫公民。如果有人想在每个请求之间暂停 5 秒,我的理解是,如果没有额外的脚本,就没有办法做到这一点,而这些脚本基本上破坏了通过发出单个请求来对顺序范围提供内置支持的意义。
对此的解决方案是使用wget
具有方便--wait=5
标志的which来实现上述所需的结果。不幸的是,wget
还有其他问题。它似乎与 URL 中的特殊字符斗争,并且无法使用 URL 周围的引号,因为该范围{1..100}
似乎无法识别。这意味着有时需要手动转义特殊字符。这是可以管理的,但很烦人。
然而,更重要的是,wget
不支持动态命名输出(-O
这里的标志没有帮助)。尽管curl
提供了方便,-o "#1.jpg"
但似乎无法实现相同的动态结果,wget
除非再次绕过内置的顺序范围支持并制作单个请求的脚本集合,或者rename
在下载后必须或以其他方式编辑文件名。
这让我觉得这是一项相当常见的任务:下载一系列连续的源文件,在每个请求之间礼貌地暂停,并动态重命名输出。我是否缺少一些替代方案curl
并wget
克服了上述两个问题:1)在每个请求之间暂停 2)动态输出文件名。
小智 9
它似乎很难处理 URL 中的特殊字符,并且无法使用 URL 周围的引号,因为 {1..100} 范围似乎无法识别。
这是因为此范围语法实际上不是 的功能wget
,它是您的外壳程序(例如 bash)的功能,它在将参数传递给之前扩展参数wget
,比较:
$ echo abc{1..5}
abc1 abc2 abc3 abc4 abc5
Run Code Online (Sandbox Code Playgroud)
或者
$ ruby -e 'p ARGV' abc{1..5}
["abc1", "abc2", "abc3", "abc4", "abc5"]
Run Code Online (Sandbox Code Playgroud)
如果您引用该参数,则外壳将不会扩展它:
$ echo 'abc{1..5}'
abc{1..5}
Run Code Online (Sandbox Code Playgroud)
但是,您可以引用除范围之外的所有内容:
$ echo 'abc'{1..5}'def'
abc1def abc2def abc3def abc4def abc5def
Run Code Online (Sandbox Code Playgroud)
然而,更重要的是,wget 不支持动态命名输出
wget
没有处理这样的范围的wget
功能,因为这样的范围不是功能。
所以不,似乎您无法使用单个命令完成所有这些。但是您仍然可以将其放入 oneliner 中:
for i in {1..100}; do curl "https://example.com/${i}.jpg" -o "output_${i}.jpg"; sleep 5; done
Run Code Online (Sandbox Code Playgroud)
UNIX 工具被设计为相当专注但易于编写脚本。他们中的一些人增加了许多选项来一次性完成常见任务,但他们永远无法单独涵盖每个用例。