找回密码
 加入
搜索
查看: 4120|回复: 7

[网络通信] 为什么使用InetGet() 批量下载循环次数多了就无效了呢?

  [复制链接]
发表于 2015-11-30 15:49:13 | 显示全部楼层 |阅读模式
本帖最后由 chamlien 于 2015-11-30 17:29 编辑

测试下载的文件大小均为1KB,但是批量下载均无法循环完成。
 For $n = 0 To 9999999
    $sData = InetGet("http://test/" & $n, @ScriptDir & "\Temp" & $n & ".txt",1,1)
Next
InetClose($sData)
上方代码只能下载5千个文件,虽然程序没出错还在循环,但是5千个往后的文件就下载不到了。
 For $n = 0 To 9999999
    $sData = InetGet("http://test/" & $n, @ScriptDir & "\Temp" & $n & ".txt",1,1)
    If Mod($n, 100) == 0 Then
        Do
            Sleep(250)
        Until InetGetInfo($sData, 2)
        InetClose($sData)
    Endif
Next
上方代码只能下载8千个文件,虽然程序没出错还在循环,但是8千个往后的文件就下载不到了。

怎样才能实现批量下载且使下载有效呢?
当然, 改成以下能保证下载有效,但不是后台下载且无法批量,效率十分低下。
$sData = InetGet("http://test/" & $n, @ScriptDir & "\Temp" & $n & ".txt",1,0)
望各位大神赐教!
发表于 2015-12-1 15:29:52 | 显示全部楼层
帮顶
关注中……
发表于 2015-12-1 16:40:37 | 显示全部楼层
先声明我是初学者,乱说而已。

第一段代码可能一下子耗尽了资源(IP连接数?或其他东东),或达到 InetGet 同一时间存在的极限数?....

第二段代码,只是在循环到 100整数时,有个等待这个网页下载完成的延时,就因为这个等待,多下载了几千文件。
我的想法是,限制  InetGet 下载进程数,例如为100个,100以内,直接 InetGet,超过100时,加上个判断之前的InetGet句柄是否完成下载,如果完成1个,就增加一个新的InetGet,完成x个就新增x个InetGet,这样一直保持100个以内的InetGet进程,直到循环完全部网址。

不知道我表达清楚意思没。也不知道是否可行,仅供参考。
 楼主| 发表于 2015-12-3 16:27:09 | 显示全部楼层
回复 3# hnfeng

呵呵,我也是初学者,现在我的思路是定义15个变量,也就是建立15个InetGet,然后while循环直到15个下载完成后再循环。但是这样还是比较慢,像你这样的思路,效率应该比较高,但是完成x个就新增x个InetGet,这样变量不好循环判断,比如同时下载1,2,3,2先完成了,创建4,跟着1完成,创建5,最后3完成,创建6,以此类推,这个4,5,6的顺序创建有点难。
发表于 2015-12-3 20:18:42 | 显示全部楼层
可以试试用coproc多进程,循环分配一定数量任务给几个进程。
发表于 2015-12-4 09:11:20 | 显示全部楼层
本帖最后由 hnfeng 于 2015-12-4 09:12 编辑

回复 4# chamlien


    AU3 的许多东东貌似都有一个极限值,例如 ini 文件中的定义参数的数量(其实是字段内支付总数量)、支持文本框的长度 等等。毕竟这是一个微小型脚本语言。

你的思路也可以,代码应该比较简单。速度可能较慢。

我的思路,可能要搞一个数组,记录 InetGet的句柄及状态,然后使用 一个计数器来判断已经完成的句柄数

忙,暂时没时间也没条件来写代码试验
发表于 2015-12-4 13:09:21 | 显示全部楼层
加上这个内存释放函数
_ReduceMemory(@AutoItPID)
Func _ReduceMemory($i_PID = -1)
        If $i_PID <> -1 Then
                Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID)
                Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
                DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
        Else
                Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
        EndIf
        Return $ai_Return[0]
EndFunc   ;==>_ReduceMemory
 楼主| 发表于 2015-12-10 10:58:59 | 显示全部楼层
本帖最后由 chamlien 于 2015-12-10 11:06 编辑
先声明我是初学者,乱说而已。

第一段代码可能一下子耗尽了资源(IP连接数?或其他东东),或达到 InetG ...
hnfeng 发表于 2015-12-1 16:40


根据你的思路,我完成了一半,使用数组限制在100个,等待100完成后再创建,暂时无法做到 完成x个就新增x个InetGet 这样的思路,估计这个效率会更高一点。
贴上自己的源码,看看有没有要优化的地方。源码为遍历某网站的所有手机号码,每个号码返回的文件大小都为1KB,加上7楼的代码释放内存,但执行时间长一点电脑还是比较卡顿,估计是频繁读写硬盘导致。
另外,数组里面的变量要不要释放,怎么样释放?InetGet产生的临时文件在哪?假如要下载100万个文件,难到会生成100万个临时文件?
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <IE.au3>
#include <inet.au3>
#include <Misc.au3>
#include <file.au3>
;#include <date.au3>

Opt("TrayIconHide", 1)
If _Singleton(@ScriptName, 1) = 0 Then
        MsgBox(64, "警告", "您只能运行一个此应用程序!")
        Exit (1)
EndIf


$Form1 = GUICreate("360MobileNumber", 1300, 680, -1, -1)
$oIE = _IECreateEmbedded()
$GUIActiveX = GUICtrlCreateObj($oIE, -1, -1, 1300, 600)
$oButton = GUICtrlCreateButton("开始", 600, 630, 100, 36)
GUICtrlSetFont(-1, 12, 400, 0, "微软雅黑")
GUICtrlSetColor(-1, 0x008B00)
GUISetBkColor(0xCCCCFF)
$label = GUICtrlCreateLabel("", 10, 640, 80, 25)
GUISetState(@SW_SHOW)

_IENavigate($oIE, "http://test", 0)
While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case -3
                        Exit
                Case $oButton
                         _IENavigate($oIE,'about:blank',0)
                        Local $aRecords
                        _FileReadToArray(@ScriptDir & "\Temp\MobileArea.txt", $aRecords)
                        ;Local $file = FileOpen(@ScriptDir & "\Result\FirstRound.txt", 258)
                        Local $sData[]
                        ;Local $x = 0
                        ;Local $time = _NowCalc()
                        For $i = 1 To $aRecords[0]
                                
                                Local $start = $aRecords[$i] * 10000
                                Local $end = $aRecords[$i] * 10000 + 9999
                                DirCreate(@ScriptDir & "\Temp" & $aRecords[$i])
                                For $n = $start To $end
                                
                                        Local $Onestop = 0
                                        For $x = 1 To 100
                                                $sData[$x] = InetGet("http://test/mod/mobileValid/checkMobile/phone/" & $start, @ScriptDir & "\Temp" & $aRecords[$i] & "" & $start & ".txt", 1, 1)
                                                $start += 1
                                                $Onestop = $x
                                                If $start > $end Then ExitLoop
                                        Next
                                        
                                        Local $comPlete = 0
                                        While 1
                                                Sleep(100)
                                                For $x = 1 To $Onestop
                                                        If InetGetInfo($sData[$x], 2) Then
                                                                $comPlete  = 1
                                                        Else
                                                                $comPlete = 0
                                                                ExitLoop
                                                        EndIf
                                                Next
                                                If $comPlete = 1 Then 
                                                        GUICtrlSetData($label,$start)
                                                        For $x = 1 To $Onestop
                                                                InetClose($sData[$x])
                                                        Next
                                                        ExitLoop
                                                EndIf
                                        WEnd
                                        If Mod($start, 1000) == 0 Then _ReduceMemory(@AutoItPID)
                                        
                                        If $start > $end Then ExitLoop
                                Next
                        Next
                        ;MsgBox(0,0,_DateDiff("s", $time, _NowCalc()))
                        ;FileClose($file)
        EndSwitch
WEnd

Func _ReduceMemory($i_PID = -1)
        If $i_PID <> -1 Then
                Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID)
                Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
                DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
        Else
                Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
        EndIf

        Return $ai_Return[0]
EndFunc   ;==>_ReduceMemory
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-4-28 02:54 , Processed in 0.075768 second(s), 21 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表