找回密码
 加入
搜索
查看: 2087|回复: 9

[网络通信] 为什么GET源码会丢失部分

[复制链接]
发表于 2016-4-21 02:49:01 | 显示全部楼层 |阅读模式
本帖最后由 heavenm 于 2016-4-21 02:50 编辑
#Include <Array.au3>
#include <winhttp.au3>
$_URL = 'http://list.jd.com/list.html?cat=670,677,687&ev=exbrand_18140&page=1&delivery=1&go=0&JL=6_0_0'

$_TempHtml = _WinHTTP_GetRespond(-1, $_URL, 2)
_ArrayDisplay($_TempHtml)
_ClipBoard_SetData($_TempHtml[0])

#include-once
#include <winhttp.au3>
Global Const $tagWINHTTP_PROXY_INFO = "DWORD  dwAccessType;ptr lpszProxy;ptr lpszProxyBypass;"

;~  #FUNCTION# ;===============================================================================

;~  函数名...........: _WinHTTP_GetRespond
;~  描述.............: 完整的HTTP传输过程
;~  函数用法.........: _WinHTTP_GetRespond($hRequest, $ConnectURL [, Mode[,$hTimeOut[,$Context[,$Cookies[,$MoreHeader[,$ProxyServer[, $FuncName[, $ParamArray]]]]]]]])
;~  
;~  参数解释.........: $hRequest - 由 _WinHttpOpen() 函数返回的句柄 或 字符串 (Agent 的描述,也可使用-1,Dafult来创建默认描述)
;~                                         $ConnectURL - 请求的URL地址,其形式可为 http://UserName:UserPassWord@127.0.0.1:8181/winhttp_getrespondUpdate/
;~                                         $Mode - 本函数定义的模式:
;~                                                                 0    GET (默认)
;~                                                                 1    POST
;~                                                                 2    返回服务器返回的内容(禁用检测的话,+256)
;~                                                                 4    返回完整的Header
;~                                                                 8    禁用重定向
;~                                                                 16   禁用SSL的证书检测
;~                                                                 32   使用自定义函数后立即返回
;~                                                                 64   返回Connection句柄(即不关闭Connection句柄)
;~                                                                 128  访问地址为'[0x00000]' + 'http://' 的形式(即使用Connection句柄作为当期连接)
;~                                                                 256  返回内容绝对为二进制
;~                                                                 512  正则解析网址
;~                                         $hTimeOut       - 超时MS(正整数,或一维四元数组)
;~                                         $Context        - 请求需要发送的内容,一般用于POST中        (字符串)
;~                                         $Cookies        - 指定文件头 Cookies (字符串)
;~                                         $MoreHeader     - 指定更多的文件头信息 (单一字符串,字符串内可包含回车符)
;~                                         $ProxyServer    - 代理服务器地址 [UserName:UserPassWord@]127.0.0.1:8181 (字符串)
;~                                         $FuncName       - 用户自定义过程名称 (执行时机为确定请求有效后,优先于本过程的文件头及数据获取过程)
;~                                         $ParamArray     - 用户自定义过程所需参数构成的数组
;~                                         
;~   函数返回值......: 如果成功的话 - 返回一维8元的数组
;~                            0        -        数据内容                ( 二进制的字符串或字符串,要强制使用二进制模式,请使用256模式,并根据需要使用 Binary() 或 BinarytoString() 函数 )
;~                            1        -        服务器状态
;~                            2        -        文件长度
;~                            3        -        Cookies
;~                            4        -        重定向                (该重定向为完整的URL地址)
;~                            5        -        编码类型
;~                            6        -        完整Header
;~                            7        -        Connection 句柄
;~                                                    (无内容时,上述任何一个元素均可能为-1)

;~                                         如果失败的话 - 设置@error,返回最后的错误代码:
;~                                                 @Error:
;~                                                         1        -        打开请求失败
;~                                                         2        -        打开请求失败或无法设置重定向
;~                                                         4        -        无法发送请求
;~                                                         5        -        服务器无回应或超时或使用SSL验证
;~  作者 ............: Republican
;~  注意点 ..........: 如果Header为多行数据,请使用@CRLF为每行非开
;~  相关函数 ........: Winhttp.Au3
;~  链接 ............: http://msdn.microsoft.com/en-us/library/aa384087(VS.85).aspx
;~  有无例子 ........: Yes
;~  日期 ............: 2011.2.19


Func _WinHTTP_GetRespond($hOpen, $ConnectURL, $Mode = Default, $hTimeOut = Default, $Context = Default, $Cookies = Default, $MoreHeader = Default, $ProxyServer= Default, $FuncName = Default, $ParamArray = -1)
        ; ==== 判断基本连接信息 ====
        If $hOpen = "" Or $ConnectURL = "" Then Return SetError(1,0,-1)
;~         MsgBox(0,"",$ConnectURL)
        ; ==== 非句柄时,由函数创建句柄 ====
        Local $SimpleMode = 0
        If IsString($hOpen) Then
                $SimpleMode = 1
                $hOpen = _WinHttpOpen($hOpen)
        ElseIf $hOpen = -1 Or $hOpen = Default Then
                $SimpleMode = 1
                $hOpen = _WinHttpOpen()        
        EndIf
        ; ==== 分解模式 $Mode 设定  ====
        If $Mode = Default Or $Mode = -1 Then $Mode = 0
        $Mode = _NumberToBinary_Winhttp($Mode)        
        If Not IsArray($Mode) Then Return SetError(-1,0,-1)
        ; ==== 提取网址中包含的句柄 ====
        If $Mode[7] = 1 Then
                Local $Distinguish = StringRegExp($ConnectURL,'(.*?)(http.*)',3)
                If IsArray($Distinguish) Then
                        $hConnect = $Distinguish[0]
                        $ConnectURL = $Distinguish[1]
                EndIf
        EndIf
        
        ; ==== 拆分网址 ====
        $ConnectURL=_WinHttpCrackUrl($ConnectURL,$ICU_DECODE)
        If @error Or Not IsArray($ConnectURL) Then Return SetError(1,0,_GetLastError_Winhttp())
        
        ; ==== 重新定义变量,方便阅读 ====
        Local $ServerHost = $ConnectURL[2]
        Local $Port=$ConnectURL[3]
        Local $ObjectFile=$ConnectURL[6]&$ConnectURL[7]

        
        Local $sFlags = Default
        If $ConnectURL[1] = 2 Then $sFlags = $WINHTTP_FLAG_SECURE        ;=====判断是否使用SSL连接
                
        ; ==== 代理服务器设定 ====
        Local $PROXY_CREDITS
        If $ProxyServer <> -1 And $ProxyServer <> Default Then
                $PROXY_CREDITS = StringRegExp($ProxyServer,'(.*?):(.*?)@',3)
                $ProxyServer = StringRegExpReplace($ProxyServer,'(.*?)@',"")
                $tProxyInfo = _WinHttpProxyInfoCreate($WINHTTP_ACCESS_TYPE_NAMED_PROXY, $ProxyServer, "localhost")
                _WinHttpSetOption($hOpen, $WINHTTP_OPTION_PROXY, $tProxyInfo[0])
        EndIf
        
        ; ==== 使用句柄创建连接(128模式下使用) ====
        Switch $Mode[7]
                Case 0
                        $hConnect=_WinHttpConnect($hOpen, $ServerHost,$Port)
        EndSwitch
        
        ; ==== 创建连接 ====
        Switch $Mode[0]
                Case 0
                        $hRequest = _WinHttpOpenRequest($hConnect, "GET", $ObjectFile,Default,Default,Default,$sFlags)
                        If @error Or $hRequest = 0 Then Return SetError(2,0,_GetLastError_Winhttp()) 
                Case 1
                        $hRequest = _WinHttpOpenRequest($hConnect, "POST", $ObjectFile,Default,Default,Default,$sFlags)
                        If @error Or $hRequest = 0  Then Return SetError(2,0,_GetLastError_Winhttp()) 
                EndSwitch
        
        
        ; === 代理服务器身份验证 ====
        If IsArray($PROXY_CREDITS) And UBound($PROXY_CREDITS) = 2 Then
                _WinHttpSetOption($hRequest, $WINHTTP_OPTION_PROXY_USERNAME, $PROXY_CREDITS[0])
                _WinHttpSetOption($hRequest, $WINHTTP_OPTION_PROXY_PASSWORD, $PROXY_CREDITS[1])
        EndIf
        
        ; ==== 关闭SSL中证书的验证 ====
        If $Mode[4] = 1 Then 
                _WinHttpSetOption($hRequest,$WINHTTP_OPTION_SECURITY_FLAGS,$SECURITY_FLAG_IGNORE_UNKNOWN_CA)                ;使用非权威机构签发的证书
                _WinHttpSetOption($hRequest,$WINHTTP_OPTION_SECURITY_FLAGS,$SECURITY_FLAG_IGNORE_CERT_CN_INVALID)                ;使用公共名称无效的证书
                _WinHttpSetOption($hRequest,$WINHTTP_OPTION_SECURITY_FLAGS,$SECURITY_FLAG_IGNORE_CERT_DATE_INVALID)                ;使用过期的证书
;~                 _WinHttpSetOption($hRequest,$WINHTTP_OPTION_SECURITY_FLAGS,$SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE)                ;使用非服务器颁发的证书
        EndIf
        
        ; ==== 设置超时 ====
        If $hTimeOut <> -2 And $hTimeOut <> Default And $hTimeOut <> "" Then 
                If IsArray($hTimeOut) And UBound($hTimeOut) = 4 Then
                        MsgBox(0,"",$hTimeOut)
                        _WinHttpSetTimeouts($hRequest,$hTimeOut[0],$hTimeOut[1],$hTimeOut[2],$hTimeOut[3])        
                ElseIf IsNumber($hTimeOut) Then
                        _WinHttpSetTimeouts($hRequest,$hTimeOut,$hTimeOut,$hTimeOut,$hTimeOut)        
                EndIf
        EndIf
        
        ; ==== 登录需要用户验证的HTTP服务器 ====
        If $ConnectURL[4] <> "" Or $ConnectURL[5] <> "" Then _WinHttpSetCredentials($hRequest, $WINHTTP_AUTH_TARGET_SERVER, $WINHTTP_AUTH_SCHEME_BASIC, $ConnectURL[4], $ConnectURL[5])
        ; ==== 禁止重定向 ====
        If $Mode[3] = 1 Then _WinHttpSetOption($hRequest,$WINHTTP_OPTION_DISABLE_FEATURE,$WINHTTP_DISABLE_REDIRECTS)        
        If @error Then Return SetError(3,0,_GetLastError_Winhttp())
        
        ; ==== Header构建 ====
        Local $BinaryMode=0
        If $Context <> -1 And $Context <> Default And $Context <> "" Then 
                Switch IsString($Context)
                        Case 1
                                _WinHttpAddRequestHeaders($hRequest, "Content-Length: "&StringLen($ConText)&@CRLF)
                        Case 0
                                _WinHttpAddRequestHeaders($hRequest, "Content-Length: "&BinaryLen($ConText)&@CRLF)
                                $BinaryMode = 1
                EndSwitch
        EndIf
        If $Cookies <> -1 And $Cookies <> Default And $Cookies <> "" Then _WinHttpAddRequestHeaders($hRequest, "Cookie: "&$Cookies&@CRLF)
        If $MoreHeader <> "" And $MoreHeader <> -1 And $MoreHeader <> Default Then _WinHttpAddRequestHeaders($hRequest,$MoreHeader)

        ; ==== 发送数据 ====
        _WinHttpSendRequest($hRequest)
        If @error Then Return SetError(4,0,_GetLastError_Winhttp())
        ; ==== 发送POST数据 ====
        If $Context <> -1 And $Context <> Default And $Context <> "" Then 
                Switch $BinaryMode
                        Case 0
                                _WinHttpWriteData($hRequest,$Context)
                        Case 1
                                _WinHttpWriteData($hRequest,$Context,1)
                EndSwitch
        EndIf 
        
        ; ==== 接受服务器回应 ====
        _WinHttpReceiveResponse($hRequest)
        ; ==== 判断数据是否有效 ====
        If Not _WinHttpQueryDataAvailable($hRequest) Then Return SetError(5,0,_GetLastError_Winhttp())
        
        ; ==== 自定义函数处理过程(此时开始调用外部函数) ====
        If $FuncName <> "" And $FuncName <> -1 And $FuncName <> Default Then
                If $ParamArray <> "" Then
                        Local $FuncArray[UBound($ParamArray) +1]
                        $FuncArray[0] = "CallArgArray"
                        For $i = 1 To UBound($ParamArray)
                                $FuncArray[$i] = $ParamArray [$i -1]
                                If StringLeft($ParamArray [$i -1],1) = "$" Then $FuncArray[$i] = Eval(StringTrimLeft($FuncArray[$i],1))
                        Next
                        Call($FuncName,$FuncArray)
                Else
                        Call($FuncName)
                EndIf 
                If $Mode[5]  = 1 Then 
                        _WinHttpCloseHandle($hRequest)
                        _WinHttpCloseHandle($hConnect)
                        If $SimpleMode = 1 Then _WinHttpCloseHandle($hOpen) 
                        Return 1
                EndIf
        EndIf
        
        ; ==== 函数返回数据构建 ====
        Local $iReturn[8] = [-1,-1,-1,-1,-1,-1,-1,-1]
        If $Mode[2] = 1 Then $iReturn[6]=_WinHttpQueryHeaders($hRequest)                                ;完整的Header信息
        $iReturn[1]=_WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_STATUS_CODE)        ;服务器状态
        $iReturn[2]=_WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_CONTENT_LENGTH)        ;文件长度
        ; ==== Cookies拆分 ====
        $iReturn[3] =_WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_SET_COOKIE,Default,0)                ;Cookies with CRLF换行
        If $iReturn[3] <> "" Then 
                For $i = 1 To 20
                        Local $TempCookies = _WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_SET_COOKIE,Default,$i)
                        If $TempCookies <> "" Then
                                $iReturn[3] &= @CRLF & $TempCookies
                        Else
                                $i = 21
                                $TempCookies = 0
                        EndIf
                Next
        EndIf
        ; ==== 完整的网址重定向构建 ====
        $iReturn[4]=_WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_LOCATION)                        ;重定向及其处理过程
        If $iReturn[4] <> "" Then 
                Local $RedictURL=_WinHttpCrackUrl($iReturn[4])
                If @error Then 
                        Local $RedictURL = $ConnectURL
                        $RedictURL[6] = $iReturn[4]
                        $RedictURL[7] = ""
                        $iReturn[4] = _WinHttpCreateUrl($RedictURL)
                EndIf
                $RedictURL = 0
        EndIf
        $iReturn[5]=_WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_CONTENT_TYPE)                ;编码类型
        ; ==== 返回-1替代空数据 ====
        For $i = 1 To 5                                                                                
                If $iReturn[$i] = "" Then $iReturn[$i] = -1
        Next
        ; ==== 读取返回正文数据 ====
        If $Mode[1] = 1 Then 
                Switch $iReturn[2]
                        Case -1,""
                                $rDate =Binary("")
                                While 1
                                        $rDate &= _WinHttpReadData($hRequest,2,1024 * 16)
                                        If @error Then ExitLoop
                                        Sleep(10)
                                WEnd
                                $iReturn[0] = Binary($rDate)
                        Case Else
                                $iReturn[0] = _WinHttpReadData($hRequest,2,$iReturn[2])
                EndSwitch
                ; ==== 转回字符串 ====
                If $Mode[8] = 0 Then
                        Local $StringText[4] = ['text/html','text/xml','application/xhtml+xml','text/plain'],$FindText = 0,$StringType[1] = ["UTF-8"],$FindType = -1
                        For $i = 0 To UBound($StringText) -1
                                If StringInStr($iReturn[5],$StringText[$i]) Then
                                        $FindText = 1
                                        ExitLoop
                                EndIf
                        Next
                        If $FindText Then
                                For $i = 0 To 0
                                        If StringInStr($iReturn[5],$StringType[$i]) Then
                                                $FindType = $i
                                                ExitLoop
                                        EndIf 
                                Next
                                Switch $FindType
                                        Case 0 
                                                $iReturn[0] = BinaryToString($iReturn[0],4)
                                        Case Else
                                                $iReturn[0] = BinaryToString($iReturn[0])
                                EndSwitch
                        EndIf
                EndIf

        EndIf
        
        ; ==== 判断是否关闭句柄 ====
        _WinHttpCloseHandle($hRequest)
        Switch $Mode[6]
                Case 1
                        $iReturn[7] = $hConnect
                Case Else
                        _WinHttpCloseHandle($hConnect)
        EndSwitch
        If $SimpleMode = 1 Then _WinHttpCloseHandle($hOpen) 
        Return $iReturn
EndFunc

;-----LastError Meaning:
;~ http://msdn.microsoft.com/en-us/library/ms681381(VS.85).aspx
;~ http://msdn.microsoft.com/en-us/library/aa385465(v=VS.85).aspx
Func _GetLastError_Winhttp()
        Local $lastError = DllCall ( "kernel32.dll", "dword", "GetLastError" )
        Return $lastError[0]
EndFunc

Func _NumberToBinary_Winhttp($iNumber)
    Local $sBinString = "",$ModeNum = 11, $Numbers[$ModeNum]
    Local $iUnsignedNumber=BitAND($iNumber,0x7FFFFFFF)
    Do
        $sBinString = BitAND($iUnsignedNumber, 1) & $sBinString
        $iUnsignedNumber = BitShift($iUnsignedNumber, 1)
    Until Not $iUnsignedNumber

        $sBinString = StringRight("0000000000000000" &$sBinString,$ModeNum)
        For $i = 0 To $ModeNum -1
                $Numbers[$i] = StringMid($sBinString,$ModeNum - $i,1)
        Next
        Return $Numbers
        
EndFunc   ;==>_NumberToBinary

Func _WinHttpProxyInfoCreate($dwAccessType, $sProxy, $sProxyBypass)
    Local $tWINHTTP_PROXY_INFO[2] = [DllStructCreate($tagWINHTTP_PROXY_INFO), DllStructCreate('wchar proxychars[' & StringLen($sProxy)+1 & ']; wchar proxybypasschars[' & StringLen($sProxyBypass)+1 & ']')]
    DllStructSetData($tWINHTTP_PROXY_INFO[0], "dwAccessType", $dwAccessType)
    If StringLen($sProxy) Then DllStructSetData($tWINHTTP_PROXY_INFO[0], "lpszProxy", DllStructGetPtr($tWINHTTP_PROXY_INFO[1], 'proxychars'))
    If StringLen($sProxyByPass) Then DllStructSetData($tWINHTTP_PROXY_INFO[0], "lpszProxyBypass", DllStructGetPtr($tWINHTTP_PROXY_INFO[1], 'proxybypasschars'))
    DllStructSetData($tWINHTTP_PROXY_INFO[1], "proxychars", $sProxy)
    DllStructSetData($tWINHTTP_PROXY_INFO[1], "proxybypasschars", $sProxyBypass)
    Return $tWINHTTP_PROXY_INFO
EndFunc
 楼主| 发表于 2016-4-21 02:55:49 | 显示全部楼层
本帖最后由 heavenm 于 2016-4-21 03:07 编辑

发现问题鸟!是
BinaryToString 转换的时候有字符限制好像
太长了
 楼主| 发表于 2016-4-21 03:15:24 | 显示全部楼层
本帖最后由 heavenm 于 2016-4-21 14:15 编辑

Local $_STR
                                                $iReturn[0] = StringTrimLeft($iReturn[0], 2)
                                                Do
                                                        $_STR = BinaryToString('0x'&StringLeft($iReturn[0], 1024*20),4)
                                                        FileWriteLine ( @ScriptDir&"\1.txt", $_STR )
                                                        $iReturn[0] = StringTrimLeft($iReturn[0], 1024*20)
                                                Until StringIsSpace($iReturn[0])
                                                $iReturn[0] = $_STR

写入文本就不会丢失!是神马问题
 楼主| 发表于 2016-4-21 14:08:18 | 显示全部楼层
我靠 终于发现终极问题了,竟然是一个变量储存的字符串有数量限制!!!!
发表于 2016-4-21 14:15:07 | 显示全部楼层
我靠 终于发现终极问题了,竟然是一个变量储存的字符串有数量限制!!!!
heavenm 发表于 2016-4-21 14:08



    Au3限制: 二进制数据的最大字节或字符串的最大长度 2,147,483,647  这么大应该足够用了吧
 楼主| 发表于 2016-4-21 14:17:06 | 显示全部楼层
本帖最后由 heavenm 于 2016-4-21 14:19 编辑
Au3限制: 二进制数据的最大字节或字符串的最大长度 2,147,483,647  这么大应该足够用了吧
afan 发表于 2016-4-21 14:15



    奇怪转换成字符串的时候就会丢失
连接起来就会丢失
                                       
        Local $_STR
                                                $iReturn[0] = StringTrimLeft($iReturn[0], 2)
                                                Do
                                                       $_STR &= BinaryToString('0x'&StringLeft($iReturn[0], 1024*20),4)

                                                        $iReturn[0] = StringTrimLeft($iReturn[0], 1024*20)
                                                Until StringIsSpace($iReturn[0])
                                                $iReturn[0] = $_STR

写入文本不会丢失

Local $_STR
                                                $iReturn[0] = StringTrimLeft($iReturn[0], 2)
                                                Do
                                                       $_STR = BinaryToString('0x'&StringLeft($iReturn[0], 1024*20),4)
                                                        FileWriteLine ( @ScriptDir&"\1.txt", $_STR )
                                                        $iReturn[0] = StringTrimLeft($iReturn[0], 1024*20)
                                                Until StringIsSpace($iReturn[0])
                                                $iReturn[0] = $_STR
 楼主| 发表于 2016-4-21 14:25:17 | 显示全部楼层
本帖最后由 heavenm 于 2016-4-21 14:26 编辑

= =#不知道是不是剪切板问题,直接写入文本也是可以的
发表于 2016-4-21 14:28:50 | 显示全部楼层
奇怪转换成字符串的时候就会丢失
连接起来就会丢失
                                         ...
heavenm 发表于 2016-4-21 14:17



    估计你是输出限制
 楼主| 发表于 2016-4-21 14:32:22 | 显示全部楼层
估计你是输出限制
afan 发表于 2016-4-21 14:28



    终于知道为什么了!研究了一天
_ClipBoard_SetData($_TempHtml[0])输出文字会丢失

_ClipBoard_SetData($_TempHtml[0],$CF_UNICODETEXT)这样子就OK了
 楼主| 发表于 2016-4-21 14:33:52 | 显示全部楼层
谢谢组织,谢谢AFAN版主
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-9-29 04:18 , Processed in 0.087734 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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