ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: wcymiss

[原创] 不懂html也来学网抓(xmlhttp/winhttp+fiddler)

    [复制链接]

TA的精华主题

TA的得分主题

发表于 2015-5-1 13:47 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖已被收录到知识树中,索引项:网页交互
wcymiss 发表于 2015-3-9 17:06
嗯,确实有错,而且错得离谱,不知道第一个写这段代码是根据什么写的。
错误1:压缩前数据长度获取错误。 ...

公司电脑网络限制,登录不了本论坛了,也下载不了附件,所以帖上老师的代码,回公司后再慢慢研究:
方法一gzip_dll(Module)
Option Explicit

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

'======================解压API==========================
Private Declare Function InitDecompression Lib "D:\gzip.dll" () As Long
Private Declare Function CreateDecompression Lib "D:\gzip.dll" (ByRef context As Long, ByVal flags As Long) As Long
Private Declare Function DestroyDecompression Lib "D:\gzip.dll" (ByVal context As Long) As Long
Private Declare Function Decompress Lib "D:\gzip.dll" ( _
    ByVal context As Long, _
    ByRef input_buffer As Any, ByVal input_buffer_size As Long, _
    ByRef output_buffer As Any, ByVal Output_buffer_size As Long, _
    ByRef input_used As Long, ByRef output_used As Long) As Long

Public Function UnCompressByGzipDLL(arrByte() As Byte, Optional Flag As Long = 1) As Boolean
    Dim contextHandle As Long
    Dim InputBufferSize As Long
    Dim OutputBuffer() As Byte
    Dim OutputBufferSize As Long
    Dim outUsed As Long
    Dim inUsed As Long
    Dim ReturnValue As Long
   
    UnCompressByGzipDLL = False
    ReDim Result(0)
   
    InputBufferSize = UBound(arrByte) + 1
    CopyMemory OutputBufferSize, arrByte(UBound(arrByte) - 3), 4
    ReDim OutputBuffer(OutputBufferSize - 1) As Byte
   
    InitDecompression
    CreateDecompression contextHandle, Flag
   
    ReturnValue = Decompress( _
        contextHandle, _
        arrByte(0), InputBufferSize, _
        OutputBuffer(0), OutputBufferSize + 1, _
        inUsed, outUsed)
        
    DestroyDecompression contextHandle
   
    If ReturnValue = 0 Then
        UnCompressByGzipDLL = True
        arrByte = OutputBuffer
    End If
End Function
方法二winrar(Module)
Option Explicit

Public Function UnCompressByWinrar(arrByte() As Byte) As Boolean
    Const WinrarFullName As String = "C:\Program Files\WinRAR\WinRAR.exe"
    Const TempPath  As String = "D:\"
    Const TempGzipFile  As String = "GzipTest"
    Dim GzFile As String
    Dim UnGzFile As String
   
    If Dir(WinrarFullName) = "" Then MsgBox "请写入winrar.exe文件的正确路径": Exit Function
   
    GzFile = TempPath & TempGzipFile & ".gz"
    UnGzFile = TempPath & TempGzipFile
   
    If Dir(GzFile) <> "" Then Kill GzFile
   
    Open GzFile For Binary As #1
    Put #1, , arrByte
    Close #1
   
    CreateObject("wscript.shell").Run """" & WinrarFullName & """ x " & GzFile & " " & TempGzipFile & " " & TempPath & " -y -ibck", 0, 1
   
    Open UnGzFile For Binary As #1
    ReDim arrByte(LOF(1) - 1)
    Get #1, , arrByte
    Close #1
   
    Kill TempPath & TempGzipFile & ".gz"
    Kill TempPath & TempGzipFile
    UnCompressByWinrar = True
End Function
网站测试(Module)
Option Explicit

Sub URLTest1() '用方法1
    Dim arrByte() As Byte
    Dim arrByteGzip() As Byte
    Dim strText As String
    Dim strTextGzip As String
    Dim ISize As Long
    Dim CanCompare As Boolean
    Dim i As Long
   
    i = 4
    CanCompare = True
   
    With CreateObject("WinHttp.WinHttpRequest.5.1")
        .Open "GET", Cells(i, 1).Value, False
        .Send
        If .getallresponseheaders Like "*Content-Encoding: gzip*" Then
            CanCompare = False
            Cells(i, 6).Value = "无非GZIP数据"
        Else
            arrByte = .responseBody
            Cells(i, 2).Value = UBound(arrByte) + 1
            strText = byteToStr(arrByte, "utf-8")
        End If
    End With
   
    With CreateObject("WinHttp.WinHttpRequest.5.1")
        .Open "GET", Cells(i, 1).Value, False
        .setRequestHeader "Accept-Encoding", "gzip, deflate"
        .Send
        If .getallresponseheaders Like "*Content-Encoding: gzip*" Then
            arrByteGzip = .responseBody
            Cells(i, 3).Value = UBound(arrByteGzip) + 1
            CopyMemory ISize, arrByteGzip(UBound(arrByteGzip) - 3), 4
            Cells(i, 4).Value = ISize
            Call UnCompressByGzipDLL(arrByteGzip)
            Cells(i, 5).Value = UBound(arrByteGzip) + 1
            strTextGzip = byteToStr(arrByteGzip, "utf-8")
        Else
            CanCompare = False
            Cells(i, 6).Value = "无GZIP数据"
        End If
    End With

    If CanCompare Then
        Cells(i, 6).Value = (strTextGzip = strText)
    End If
End Sub

Sub URLTest2() '用方法2
    Dim arrByte() As Byte
    Dim arrByteGzip() As Byte
    Dim strText As String
    Dim strTextGzip As String
    Dim ISize As Long
    Dim CanCompare As Boolean
    Dim i As Long
   
    i = 4
    CanCompare = True
    Range(Cells(i, 2), Cells(i, 8)).ClearContents
   
    With CreateObject("WinHttp.WinHttpRequest.5.1")
        .Open "GET", Cells(i, 1).Value, False
        .Send
        If .getallresponseheaders Like "*Content-Encoding: gzip*" Then
            CanCompare = False
            Cells(i, 6).Value = "无非GZIP数据"
        Else
            arrByte = .responseBody
            Cells(i, 2).Value = UBound(arrByte) + 1
            strText = byteToStr(arrByte, "utf-8")
        End If
    End With
   
    With CreateObject("WinHttp.WinHttpRequest.5.1")
        .Open "GET", Cells(i, 1).Value, False
        .setRequestHeader "Accept-Encoding", "gzip, deflate"
        .Send
        If .getallresponseheaders Like "*Content-Encoding: gzip*" Then
            arrByteGzip = .responseBody
            Cells(i, 3).Value = UBound(arrByteGzip) + 1
            CopyMemory ISize, arrByteGzip(UBound(arrByteGzip) - 3), 4
            Cells(i, 4).Value = ISize
            Call UnCompressByWinrar(arrByteGzip)
            Cells(i, 5).Value = UBound(arrByteGzip) + 1
            strTextGzip = byteToStr(arrByteGzip, "utf-8")
        Else
            CanCompare = False
            Cells(i, 6).Value = "无GZIP数据"
        End If
    End With

    If CanCompare Then
        Cells(i, 6).Value = (strTextGzip = strText)
    End If
End Sub

Private Function byteToStr(arrByte, strCharset As String) As String
    With CreateObject("Adodb.Stream")
        .Type = 1 'adTypeBinary
        .Open
        .Write arrByte
        .Position = 0
        .Type = 2 'adTypeText
        .Charset = strCharset
        byteToStr = .Readtext
        .Close
    End With
End Function
压缩(Module)
Option Explicit

======================压缩API==========================
Private Declare Function InitCompression Lib "D:\gzip.dll" () As Long
Private Declare Function CreateCompression Lib "D:\gzip.dll" (ByRef context As Long, ByVal flags As Long) As Long
Private Declare Function DestroyCompression Lib "gD:\zip.dll" (ByVal context As Long) As Long
Private Declare Function Compress Lib "D:\gzip.dll" ( _
    ByVal context As Long, _
    ByRef input_buffer As Any, ByVal input_buffer_size As Long, _
    ByRef output_buffer As Any, ByVal Output_buffer_size As Long, _
    ByRef input_used As Long, ByRef output_used As Long, _
    ByVal compression_level As Long) As Long


Public Function CompressByGzipDLL(arrByte() As Byte, Optional Flag As Long = 1) As Boolean
    Dim contextHandle As Long
    Dim InputBufferSize As Long
    Dim OutputBuffer() As Byte
    Dim outUsed As Long
    Dim inUsed As Long
    Dim ReturnValue As Long
    Dim Result() As Byte
    Dim TempLength As Long
    Const MaxBufferSize As Long = 1000
   
    CompressByGzipDLL = False
    ReDim Result(0)
   
    InputBufferSize = UBound(arrByte) + 1
    ReDim OutputBuffer(MaxBufferSize - 1) As Byte
   
    InitCompression
    CreateCompression contextHandle, Flag
   
    Do
        ReturnValue = Compress( _
            contextHandle, _
            arrByte(0), InputBufferSize, _
            OutputBuffer(0), MaxBufferSize, _
            inUsed, outUsed, 1)
        If outUsed <> 0 Then
            TempLength = UBound(Result)
            ReDim Preserve Result(TempLength + outUsed)
            CopyMemory Result(TempLength), OutputBuffer(0), outUsed
            InputBufferSize = InputBufferSize - inUsed
        End If
    Loop While ReturnValue = 0
   
    DestroyCompression contextHandle
   
    If UBound(Result) > 0 Then
        CompressByGzipDLL = True
        ReDim arrByte(UBound(Result) - 1)
        CopyMemory arrByte(0), Result(0), UBound(Result)
    End If
End Function
字符串测试(Module)
Option Explicit

Sub StringTest1() '用方法1
    Dim strText As String
    Dim arrByte() As Byte
    Dim arrByte0() As Byte
    Dim i As Long
   
    strText = String(1000, "a")
    arrByte0 = StrConv(strText, vbFromUnicode)
    arrByte = arrByte0
    Debug.Print "长度:" & UBound(arrByte) + 1
   
    Debug.Print "压缩执行:" & CompressByGzipDLL(arrByte, 1)
    Debug.Print "解压执行:" & UnCompressByGzipDLL(arrByte, 1)
   
    If UBound(arrByte) = UBound(arrByte0) Then
        Debug.Print "解压正确"
    Else
        Debug.Print "解压错误"
    End If
   
    For i = 0 To UBound(arrByte)
        If arrByte(i) <> arrByte0(i) Then Stop
    Next
End Sub

Sub StringTest2() '用方法2
    Dim strText As String
    Dim arrByte() As Byte
    Dim arrByte0() As Byte
    Dim i As Long
   
    strText = String(1000, "a")
    arrByte0 = strText
    arrByte = arrByte0
    Debug.Print "长度:" & UBound(arrByte) + 1
   
    Debug.Print "压缩执行:" & CompressByGzipDLL(arrByte, 1)
    Debug.Print "解压执行:" & UnCompressByWinrar(arrByte)
   
    If UBound(arrByte) = UBound(arrByte0) Then
        Debug.Print "解压正确"
    Else
        Debug.Print "解压错误"
    End If
   
    For i = 0 To UBound(arrByte)
        If arrByte(i) <> arrByte0(i) Then Stop
    Next
End Sub

TA的精华主题

TA的得分主题

发表于 2015-5-1 15:02 | 显示全部楼层
VBA万岁 发表于 2015-5-1 13:47
公司电脑网络限制,登录不了本论坛了,也下载不了附件,所以帖上老师的代码,回公司后再慢慢研究:
方法 ...

测试数据:
测试URL        非压缩长度        压缩长度        后四字节        解压长度        比对
http://www.pss-system.gov.cn/sipopublicsearch/portal/index.shtml                                       
http://www.telerik.com/UpdateCheck.aspx?isBeta=False                                        
http://www.sina.com                                       

TA的精华主题

TA的得分主题

发表于 2015-5-1 16:53 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2015-5-1 16:54 | 显示全部楼层
zongyj 发表于 2014-12-11 12:27
吴姐回复的帖子
主题;回帖;看帖

测试通过——退出登录后运行楼上的代码可取到回贴数据。
正好公司网络限制,无法登录本论坛,等回公司后再测试看看。
另,上传多页回帖数据代码如下:
  1. Sub wcymiss2()
  2. Dim WinHttp As New WinHttpRequest, html, a, p%, n%
  3. ActiveSheet.UsedRange.Offset(1).Clear
  4. Range("a1:c1") = Array("主题", "回复", "查看")

  5. Set html = CreateObject("htmlfile")
  6. With WinHttp
  7.     Do
  8.         p = p + 1
  9.         .Open "GET", "http://club.excelhome.net/home.php?mod=space&uid=218917&do=thread&view=me&type=reply&from=space&page=" & p & "&mobile=yes", False
  10.         .setRequestHeader "User-Agent", "Mozilla/4.0 (compatible: MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; SAMSUNG; SGH-i917)"
  11.         .send
  12.         'If InStr(.responseText, "下一页") = 0 Then Exit Do
  13.         If p = 6 Then Exit Do
  14.         html.body.innerHTML = .responseText
  15.         For Each a In html.all.tags("a")
  16.             If Left(a.href, 5) = "about" And a.innerText <> "" And a.innerText <> "论坛" And a.innerText <> "首页" And a.innerText <> "主题" And a.innerText <> "回复" Then
  17.                 n = n + 1
  18.                 ActiveSheet.Hyperlinks.Add Anchor:=Cells(n + 1, 1), Address:=Replace(a.href, "about:", "http://club.excelhome.net/"), TextToDisplay:=a.innerText
  19.             End If
  20.         Next
  21.     Loop
  22. End With
  23. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2015-5-1 17:11 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
wcymiss 发表于 2014-10-22 15:30
获取数据-防盗链的处理-模拟User-Agent

很少遇到需要模拟User-Agent的网页。

这个太好了——正好公司网络限制登录本论坛,无法查看所关注的会员的回贴信息(主要是链接以方便打开)。回去后立马测试......

TA的精华主题

TA的得分主题

发表于 2015-5-2 08:17 | 显示全部楼层
wcymiss 发表于 2014-10-23 12:13
说到skey和bkn,索性再唠叨一下用IE获取Cookie的例子。

QQ的skey用winhttp比较难以获取,当中包含了一些 ...

我这里测试第一段代码不成功——无法获取Skey值,立即窗口中也未见到skey字样。
第二段代码测试成功。

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-5-2 09:10 | 显示全部楼层
VBA万岁 发表于 2015-5-2 08:17
我这里测试第一段代码不成功——无法获取Skey值,立即窗口中也未见到skey字样。
第二段代码测试成功。

IE法是需要IE加载一个控件的。
先登录软件QQ,然后用IE打开腾讯微博网页,然后登录腾讯微博,IE应该会让你加载一个登录控件。你试试。

TA的精华主题

TA的得分主题

发表于 2015-5-2 15:46 | 显示全部楼层
wcymiss 发表于 2015-5-2 09:10
IE法是需要IE加载一个控件的。
先登录软件QQ,然后用IE打开腾讯微博网页,然后登录腾讯微博,IE应该会让 ...

照做之后可以运行代码获得一个skey值,再用这个skey值去提取(用老师之前的代码提取——该代码用抓包获得的skey值是可以成功取数的)QQ数据,却不成功。而且在IE中登录腾讯微博(直接单击本贴中的“腾讯微博”按钮后登录)时,也没被要求“加载一个登录控件”。不知为何?

TA的精华主题

TA的得分主题

发表于 2015-5-4 21:21 | 显示全部楼层
VBA万岁 发表于 2015-5-1 16:54
测试通过——退出登录后运行楼上的代码可取到回贴数据。
正好公司网络限制,无法登录本论坛,等回公司后 ...

在公司测试失败......

TA的精华主题

TA的得分主题

发表于 2015-5-5 15:50 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
各位大神 请教一下用winhttp POST登陆HTTPS论坛时总是重定向失败 到底要怎样解决啊
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-10-6 15:01 , Processed in 0.049163 second(s), 5 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

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