我需要在Linux上下载超过30k的页面,并想象我可以用一个简单的bash脚本+ wget来做到这一点,这就是我想出的:
#!/bin/bash
start_time=$(date +%s)
for i in {1..30802}
do
echo "Downloading page http://www.domain.com/page:$i"
wget "http://www.domain.com/page:$i" -q -o /dev/null -b -O pages/$i
running=$(ps -ef | grep wget | wc -l)
while [ $running -gt 1000 ]
do
running=$(ps -ef | grep wget | wc -l)
echo "Current running $running process."
sleep 1;
done
done
while [ $running -gt 1 ]
do
running=$(ps -ef | grep wget | wc -l)
echo "Waiting for all the process to end..."
sleep 10;
done
finish_time=$(date +%s)
echo "Time duration: $((finish_time - start_time)) secs."
有些网页未完全下载!
由于上面的代码将使1k wget并行运行进程和 等到它降低才能添加更多进程,可能就是我 实际上耗尽了所有可用的互联网链接?
如何确保页面实际可靠性更高 正确下载?
修改
答案 0 :(得分:2)
以下是您可能的解决方案:
1)将您wget
的调用方式更改为:
(wget "http://www.domain.com/page:$i" -q -o /dev/null -O pages/$i || touch $i.bad) &
2)当您的脚本完成后,搜索所有*.bad
个文件,并为每个文件重新启动wget
。在重新尝试之前删除相应的.bad
文件。
3)直到没有*.bad
文件为止。
这是一般的想法。希望有所帮助!
修改强>
对于wget
进程消失,被杀或突然结束的情况,有可能进行改进:
(wget "http://www.domain.com/page:$i" -q -o /dev/null -O pages/$i || touch $i.bad && touch $i.ok) &
然后,您可以分析某个页面是否已完全下载或wget
未能结束。
编辑2:
经过一些测试和挖掘,我发现我以前的建议是有缺陷的。条件的顺序必须互换:
(wget "http://www.domain.com/page:$i" -q -o /dev/null -O pages/$i && touch $i.ok || touch $i.bad) &
所以,
如果wget
正确执行下载(即完成了OK返回码),则必须有两个文件:下载的页面和.ok
文件。
如果下载失败(即wget
返回KO返回码),那么必须有.bad
文件,并且可能部分下载该页面。
在任何情况下,只有.ok
个文件才有意义:他们说下载已正确完成(从wget
的角度来看,我稍后会讨论)。
如果找不到特定页面的.ok
文件,那么肯定它尚未下载,因此必须重试。
然后,我们进入程序中最精细的部分:如果Web服务器作为对大量请求的响应,取消那些无法通过HTTP 200响应和零内容长度服务的服务器会发生什么?这将是一种避免网络复制或某种服务器攻击的好方法。
如果是这种情况,您必须查看回复的模式。将有一个.ok
文件,但下载页面的文件大小可能为零。
您可以使用以下内容检测零长度下载
filesize=$(cat $i.html | wc -c)
然后在.ok
和.bad
文件的前一个过程中添加一些逻辑:
retry=0
if [ -f $i.bad ]
then
retry=1
elif [ -f $i.ok ]
then
if [ $filesize -eq 0 ]
then
retry=1
fi
else
retry=1
fi
if [ $retry -eq 1 ]
then
# retry the download
fi
希望这有帮助!
答案 1 :(得分:0)
我不知道你有什么样的连接,大量的当前连接会导致数据包丢失。还要考虑服务器具有哪种连接。如果这不是内部服务器,托管服务器的一方可能会认为这是拒绝服务攻击并过滤您的IP。一个接一个地做它更可靠。瓶颈几乎总是互联网连接,你不能更快地做到这一点。