【发布时间】:2016-10-18 00:54:05
【问题描述】:
我正在尝试创建一个 bash 脚本来从某个网站大量下载文件。
他们的下载链接是连续的 - 例如它只是 id=1, id=2, id=3 一直到 660000。唯一的要求是您必须登录,这使得这有点困难。哦,登录会在几个小时后随机超时,所以我必须重新登录。
这是我当前的脚本,大约 99% 的时间都运行良好。
#!/bin/sh
cd downloads
for i in `seq 1 660000`
do
lastname=""
echo "Downloading file $i"
echo "Downloading file $i" >> _downloadinglog.txt
response=$(curl --write-out %{http_code} -b _cookies.txt -c _cookies.txt --silent --output /dev/null "[sample URL to make sure cookie is still logged in]")
if ! [ $response -eq 200 ]
then
echo "Cookie didn't work, trying to re-log in..."
curl -d "userid=[USERNAME]" -d "pwd=[PASSWORD]" -b _cookies.txt -c _cookies.txt --silent --output /dev/null "[login URL]"
response=$(curl --write-out %{http_code} -b _cookies.txt -c _cookies.txt --silent --output /dev/null "[sample URL again]")
if ! [ $response -eq 200 ]
then
echo "Something weird happened?? Response code $response. Logging in didn't fix issue, fix then resume from $(($i - 1))"
echo "Something weird happened?? Response code $response. Logging in didn't fix issue, fix then resume from $(($i - 1))" >> _downloadinglog.txt
exit 0
fi
echo "Downloading file $(($i - 1)) again incase cookie expiring caused it to fail"
echo "Downloading file $(($i - 1)) again incase cookie expiring caused it to fail" >> _downloadinglog.txt
lastname=$(curl --write-out %{filename_effective} -O -J -b _cookies.txt -c _cookies.txt "[URL to download files]?id=$(($i - 1))")
echo "id $(($i - 1)) = $lastname" >> _downloadinglog.txt
lastname=""
echo "Downloading file $i"
echo "Downloading file $i" >> _downloadinglog.txt
fi
lastname=$(curl --write-out %{filename_effective} -O -J -b _cookies.txt -c _cookies.txt "[URL to download files]?id=$i")
echo "id $i = $lastname" >> _downloadinglog.txt
done
所以基本上我所做的就是在移动到集合中的下一个文件之前尝试下载一个随机文件。如果下载失败,我们假设登录 cookie 不再有效并告诉 curl 让我重新登录。
这很好用,我可以从中获取数千个文件。但是会发生什么——要么我的路由器宕机一两秒钟,要么他们的网站宕机一两分钟,curl 就会坐在那里,以为它正在下载几个小时。我曾经回过头来,实际上花了 24 小时在同一个文件上。它似乎没有能力知道传输是否在中间超时 - 只有当它无法开始传输时。
我知道如果将命令与“sleep”结合使用,有多种方法可以终止命令的执行,但由于这必须是“智能”并从停止的地方重新启动,所以我不能直接杀死整个脚本。
有什么建议吗?如果我可以使用 curl 通过终端命令登录,我愿意使用除 curl 之外的其他东西。
【问题讨论】:
-
一种直接的方法是设置相当于事件循环的内容并将命令生成为子shell。在您的循环中,定期检查任务是否已完成,并在必要时在时间过长时终止它们。
-
@DavidHoelzer 您可能是指后台作业(在命令末尾以控制操作员
&开头),而不是subshells。跨度> -
我不知道你可以用 shell 脚本做到这一点,但是用 python 和 requests 会很简单。
-
好吧,这里的问题是,如果下载失败,我必须让它真正重试下载。类似于“cookie 不起作用”部分,只是它会说“下载超时”并从 i-1 重试。这是最难的部分,让它与其余的逻辑一起工作!