为什么使用InetGet() 批量下载循环次数多了就无效了呢?
本帖最后由 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)望各位大神赐教! 帮顶
关注中…… 先声明我是初学者,乱说而已。
第一段代码可能一下子耗尽了资源(IP连接数?或其他东东),或达到 InetGet 同一时间存在的极限数?....
第二段代码,只是在循环到 100整数时,有个等待这个网页下载完成的延时,就因为这个等待,多下载了几千文件。
我的想法是,限制InetGet 下载进程数,例如为100个,100以内,直接 InetGet,超过100时,加上个判断之前的InetGet句柄是否完成下载,如果完成1个,就增加一个新的InetGet,完成x个就新增x个InetGet,这样一直保持100个以内的InetGet进程,直到循环完全部网址。
不知道我表达清楚意思没。也不知道是否可行,仅供参考。 回复 3# hnfeng
呵呵,我也是初学者,现在我的思路是定义15个变量,也就是建立15个InetGet,然后while循环直到15个下载完成后再循环。但是这样还是比较慢,像你这样的思路,效率应该比较高,但是完成x个就新增x个InetGet,这样变量不好循环判断,比如同时下载1,2,3,2先完成了,创建4,跟着1完成,创建5,最后3完成,创建6,以此类推,这个4,5,6的顺序创建有点难。 可以试试用coproc多进程,循环分配一定数量任务给几个进程。 本帖最后由 hnfeng 于 2015-12-4 09:12 编辑
回复 4# chamlien
AU3 的许多东东貌似都有一个极限值,例如 ini 文件中的定义参数的数量(其实是字段内支付总数量)、支持文本框的长度 等等。毕竟这是一个微小型脚本语言。
你的思路也可以,代码应该比较简单。速度可能较慢。
我的思路,可能要搞一个数组,记录 InetGet的句柄及状态,然后使用 一个计数器来判断已经完成的句柄数
忙,暂时没时间也没条件来写代码试验 加上这个内存释放函数_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)
DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle)
Else
Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
EndIf
Return $ai_Return
EndFunc ;==>_ReduceMemory 本帖最后由 chamlien 于 2015-12-10 11:06 编辑
先声明我是初学者,乱说而已。
第一段代码可能一下子耗尽了资源(IP连接数?或其他东东),或达到 InetG ...
hnfeng 发表于 2015-12-1 16:40 http://www.autoitx.com/images/common/back.gif
根据你的思路,我完成了一半,使用数组限制在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
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)
DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle)
Else
Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
EndIf
Return $ai_Return
EndFunc ;==>_ReduceMemory
页:
[1]