ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

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

    [复制链接]

TA的精华主题

TA的得分主题

发表于 2014-11-1 16:16 | 显示全部楼层
本帖已被收录到知识树中,索引项:网页交互
coby001 发表于 2014-11-1 15:17
回复框上端,笑脸表情的左边,有对尖括号:

谢谢老师指点

TA的精华主题

TA的得分主题

发表于 2014-11-1 16:44 | 显示全部楼层
renahu 发表于 2014-11-1 14:35
吴老师,能不能这样认为:一个汉字如果用三个十六进制的数表示就是utf8码,一个汉字如果用两个十六进制的 ...

http://club.excelhome.net/thread-998747-1-1.html

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-11-1 17:13 | 显示全部楼层
本帖最后由 moon2778 于 2014-11-26 10:17 编辑

上传文件
同样,上传文件也可以用fiddler抓包。

以EH的论坛上传附件为例。我们上传一个很小的压缩文件来测试(太大了的话,Fiddler的Raw里看不完整)。

在fiddler里搜索文件名(不含路径),确认我们需要模拟的网页。

上传1.png

webforms更清晰:

上传2.png


我们看到上传文件的POST的特点:
1、Content-Type是multipart/form-data,而且后面有一个boundary的赋值(10个英文减号+30个随机字母数字混合字符串),普通的POST的Content-Type是application/x-www-form-urlencoded了。
2、SendData的内容,各项内容以Content-Type里的boundary值分隔,但前面还加了两个英文减号,最后的boundary在末尾处也加了两个英文减号。
3、每项内容除文件流外是“Content-Disposition: form-data; name="名称"”+空行+值组成。
4、文件转成了二进制流,作为SendData其中一项内容,Content比其余各项略微复杂些。

我们也只需要按照这样的格式进行POST发送。

但要注意:字符串与字符串可以用“&”连接,但字符串与二进制流不能将流转为文本后用“&”连接,而应将字符串转为二进制流后再进行连接(数组方式、adostream均可连接流数据)。二进制流转为文本后会被系统按照默认编码格式进行编码,这样容易导致上传文件的格式不正确。

EH上传附件的代码(手工填入hash码即可上传了):
  1. Sub Main()
  2.     Const Uid As String = "" '论坛UID
  3.     Const Hash As String = "" '上传的Hash,从Fiddler里取
  4.     Dim Boundary As String
  5.     Dim SendData
  6.     Dim FileFullName As String
  7.     Dim FileShortName As String
  8.     Dim Title As String
  9.     Dim Filetype As String
  10.    
  11.     FileFullName = "D:\测试2.rar"
  12.     FileShortName = Mid(FileFullName, InStrRev(FileFullName, "") + 1)
  13.     Title = Left(FileShortName, InStrRev(FileShortName, ".") - 1)
  14.     Filetype = "rar"
  15.    
  16.     '获取Boundary
  17.     Boundary = GetBoundary()
  18.     '获取上传所需的SendData
  19.     SendData = GetUpLoadSendData(Boundary, FileFullName, _
  20.                 "Filename", FileShortName, _
  21.                 "proid", "0", _
  22.                 "hash", Hash, _
  23.                 "uid", Uid, _
  24.                 "title", Title, _
  25.                 "filetype", Filetype, _
  26.                 "Filedata", FileShortName, _
  27.                 "Upload", "Submit Query")
  28.         
  29.     '上传
  30.     With CreateObject("MSXML2.XMLHTTP")
  31.         .Open "POST", "http://club.excelhome.net/misc.php?mod=swfupload&fid=2&action=swfupload&operation=upload", False
  32.         .setRequestHeader "Content-Type", "multipart/form-data; boundary=" & Boundary
  33.         .Send SendData
  34.         Debug.Print .responsetext '出现一串数字则为成功。到论坛发帖的界面可看到“未使用的附件”的提示。
  35.     End With
  36. End Sub

  37. Function GetBoundary() As String
  38.     '生成Boundary
  39.     Dim i As Integer, r As Integer
  40.     Do While i < 30
  41.         r = Int(Rnd * 75 + 48)
  42.         If r < 58 Or (r > 64 And r < 91) Or r > 96 Then
  43.             GetBoundary = GetBoundary & Chr(r)
  44.             i = i + 1
  45.         End If
  46.     Loop
  47.     GetBoundary = String(10, "-") & GetBoundary
  48. End Function

  49. Function GetUpLoadSendData(Boundary As String, FileFullName As String, ParamArray NameValue()) As Byte()
  50.     'NameValue()必须成双,前一个是名称,后一个是值
  51.     'NameValue()最后一对是文件流之后的名称值对
  52.     'NameValue()倒数第二对是文件流信息相关的两个数据
  53.    
  54.     Dim DataBefore, DataAfter
  55.     Dim arrBytData(1 To 3), bytData() As Byte
  56.     Dim i As Long, j As Long, n As Long
  57.    
  58.     '连接文件流之前的各项名称值对
  59.     For i = 0 To UBound(NameValue) - 4 Step 2 '最后两对单独处理
  60.         DataBefore = DataBefore & "--" & Boundary & vbCrLf
  61.         DataBefore = DataBefore & "Content-Disposition: form-data; name=""" & NameValue(i) & """" & vbCrLf
  62.         DataBefore = DataBefore & vbCrLf
  63.         DataBefore = DataBefore & NameValue(i + 1) & vbCrLf
  64.     Next
  65.    
  66.     '连接文件流此项的Content-Disposition
  67.     DataBefore = DataBefore & "--" & Boundary & vbCrLf
  68.     DataBefore = DataBefore & "Content-Disposition: form-data; name=""" & NameValue(i) & """; filename=""" & NameValue(i + 1) & """" & vbCrLf
  69.     DataBefore = DataBefore & "Content-Type: application/octet-stream" & vbCrLf
  70.     DataBefore = DataBefore & vbCrLf
  71.    
  72.     '文件流前面的字符串转为流
  73.     arrBytData(1) = StrToUTF8Byte(DataBefore)
  74.    
  75.     '文件转流
  76.     arrBytData(2) = FileToByte(FileFullName)
  77.    
  78.     '文件流之后的字符串(一项)
  79.     DataAfter = "--" & Boundary & vbCrLf
  80.     DataAfter = DataAfter & "Content-Disposition: form-data; name=""" & NameValue(i) & """" & vbCrLf
  81.     DataAfter = DataAfter & vbCrLf
  82.     DataAfter = DataAfter & NameValue(i + 1) & vbCrLf
  83.     DataAfter = DataAfter & "--" & Boundary & "--"
  84.     arrBytData(3) = StrToUTF8Byte(DataAfter) '转为流
  85.    
  86.     '合并字符流和文件流
  87.     ReDim bytData(UBound(arrBytData(1)) + UBound(arrBytData(2)) + UBound(arrBytData(3)) + 2)
  88.     For i = 1 To 3
  89.         For j = 0 To UBound(arrBytData(i))
  90.             bytData(n) = arrBytData(i)(j)
  91.             n = n + 1
  92.         Next
  93.     Next
  94.    
  95.     GetUpLoadSendData = bytData
  96. End Function

  97. Function StrToUTF8Byte(strText)
  98.     '文本转UTF-8编码并去除BOM头
  99.     With CreateObject("adodb.stream")
  100.         .Mode = 3 'adModeReadWrite
  101.         .Type = 2 'adTypeText
  102.         .Charset = "UTF-8"
  103.         .Open
  104.         .Writetext strText
  105.         .Position = 0
  106.         .Type = 1 'adTypeBinary
  107.         .Position = 3 '去除UTF-8编码文本前面的BOM头(三个字节)
  108.         StrToUTF8Byte = .Read()
  109.         .Close
  110.     End With
  111. End Function

  112. Function FileToByte(strFileName As String)
  113.     '文件转流
  114.      With CreateObject("Adodb.Stream")
  115.         .Open
  116.         .Type = 1 'adTypeBinary
  117.         .LoadFromFile strFileName
  118.         FileToByte = .Read
  119.         .Close
  120.     End With
  121. End Function
复制代码
yeah ,大功告成

分享下VBS大神Demon的上传文件的代码:

http://demon.tw/programming/vbs-post-file.html


小贴士:
文件流前后的文本如果不用UTF-8编码的话,文件可以上传成功,但文件名里的中文可能无法正确显示。

评分

5

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-11-1 18:13 | 显示全部楼层
为防止误导,360楼代码已经删减。

TA的精华主题

TA的得分主题

发表于 2014-11-1 18:29 | 显示全部楼层
onlycxb 发表于 2014-11-1 18:13
为防止误导,360楼代码已经删减。

不用删啊,改个名字就好了,转义函数还是有用的~

TA的精华主题

TA的得分主题

发表于 2014-11-1 19:06 | 显示全部楼层
wcymiss 发表于 2014-10-21 12:51
更多Fiddler的使用方法,敬请参考《Fiddler调试权威指南》一书。
电子书下载地址:http://pan.baidu.com/s ...

吴老师,非常感谢您的课程,让我掌握了一些网抓基础知识,虽然还不能想抓什么抓什么,但也能抓点儿想要的了,我也开了个帖子,把平时练习抓的东西放上去,欢迎您光临指导,再次表示衷心感谢。
http://club.excelhome.net/thread-1162676-1-1.html

点评

谢谢你的捧场!能帮到你我也很高兴!  发表于 2014-11-2 21:15

TA的精华主题

TA的得分主题

发表于 2014-11-2 18:22 | 显示全部楼层
本帖最后由 xmyjk 于 2014-11-2 19:00 编辑
wcymiss 发表于 2014-11-1 17:13
上传文件
同样,上传文件也可以用fiddler抓包。

好东西,这让我想起了,当时想借good.gd做一个自动上传程序更新,然后分发的工具。
可惜后来烂尾了。不过文件上传模块倒是写好了,没想到现在还能用。
借花献佛了。

原理基本如吴姐所说。
xmlhttp等控件,如果要发送数据流,就不能使用文本格式的报文主体,但是VB中又不能直接把byte的字节形式的数组送给.send方法来发。
解决方法就是,用一个变体的变量来过度。

程序流程类似,就是我是把文件用open binary函数读入,前后字符串用strconv函数转成ansi的byte数组,然后再用copymemery连接数组。
后话:
在vb中如果发送字节数据,xmlhttp不会转码,就这么出去,如果发送的是文本,不符合规范的文本会自动转为按utf8进行编码再出去。所以gbk那些都要手工转码。
献丑了,当年的代码附件如下:
  1. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
  2. Sub upload()
  3. Dim xmlhttp, sess As String, uid As String, b As String, i As Long, n As Long
  4. Dim fl() As Byte, senddata, flnm As String, aft() As Byte, bef() As Byte, tmp As String, arr() As Byte
  5. Set xmlhttp = CreateObject("MSXML2.XMLHTTP")
  6. flnm = Format(Date, "yymmdd") & " " & Format(Time, "hh时mm分") & "bak.xls"
  7. ThisWorkbook.SaveCopyAs ThisWorkbook.Path & "" & flnm
  8. With xmlhttp
  9.      .Open "GET", "http://upload.good.gd/upload.aspx", False
  10.     .send
  11.     sess = Split(Split(.responsetext, "var SESSIONID = '")(1), "'")(0)
  12.     uid = Split(Split(.responsetext, "var UploadID = '")(1), "'")(0)
  13.     b = getboundary
  14.     Open ThisWorkbook.Path & "" & flnm For Binary As #1
  15.     ReDim fl(LOF(1) - 1) As Byte
  16.     Get #1, , fl()
  17.     Close #1
  18.     tmp = "Content-Disposition: form-data; name=""Filename""" & vbCrLf & vbCrLf & _
  19.                 flnm & vbCrLf & _
  20.                 "------------" & b & vbCrLf & _
  21.                 "Content-Disposition: form-data; name=""ASPSESSID""" & vbCrLf & vbCrLf & _
  22.                 sess & vbCrLf & _
  23.                 "------------" & b & vbCrLf & _
  24.                 "Content-Disposition: form-data; name=""Filedata""; filename=""" & flnm & """" & vbCrLf & _
  25.                 "Content-Type: application/octet-stream" & vbCrLf & vbCrLf
  26.     bef = StrConv(tmp, vbFromUnicode)
  27.     tmp = ""
  28.     tmp = vbCrLf & "------------" & b & vbCrLf & _
  29.                 "Content-Disposition: form-data; name=""Upload""" & vbCrLf & vbCrLf & _
  30.                 "Submit Query" & vbCrLf & _
  31.                 "------------" & b & "--"
  32.     aft = StrConv(tmp, vbFromUnicode)
  33.     ReDim arr(UBound(bef) + 1 + UBound(aft) + 1 + UBound(fl)) As Byte
  34.     CopyMemory arr(0), bef(0), UBound(bef) + 1
  35.     CopyMemory arr(UBound(bef) + 1), fl(0), UBound(fl) + 1
  36.     CopyMemory arr(UBound(bef) + 1 + UBound(fl) + 1), aft(0), UBound(aft) + 1
  37.     senddata = arr
  38.     .Open "POST", "http://upload.good.gd/Receive/ReceiveData.aspx?c=uploadgood&flash=true&uid=" & uid, False
  39.     .setRequestHeader "Content-Type", "multipart/form-data; boundary=" & "----------" & b
  40.     .send senddata
  41.     [b2] = "http://good.gd/" & Split(.responsetext, "|")(1) & ".htm"
  42. End With
  43. Kill ThisWorkbook.Path & "" & flnm
  44. End Sub

  45. Function getboundary() As String
  46. Dim i&
  47. For i = 1 To 10
  48.     getboundary = getboundary & Chr(Int(Rnd * 26) + 65) & Chr(Int(Rnd * 26) + 97)
  49.     getboundary = getboundary & Chr(Int(Rnd * 10) + 48)
  50. Next
  51. End Function
复制代码
good网页备份文件.zip (16.35 KB, 下载次数: 99)


评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-11-2 20:09 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
etsure 发表于 2014-11-1 00:53

55.png

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-11-3 10:46 | 显示全部楼层
wcymiss 发表于 2014-11-1 17:13
上传文件
同样,上传文件也可以用fiddler抓包。

吴姐,再次咨询一个问题,假如我用xmlhttp法 用createobject("htmlfile")      可以像ie法那样查找标签值  进行click 或者  select  那样的操作吗? 不然有的是要查找标签值才可以选择  不知道怎么写

点评

看“提取数据”那一部分  发表于 2014-11-3 11:19

TA的精华主题

TA的得分主题

发表于 2014-11-3 10:59 | 显示全部楼层
wcymiss 发表于 2014-10-29 16:27
复杂登录二:58同城登录

吴老师能弄个58同城抓取简历联系方式的程序不?

点评

你可以自己试试啊。哪步有困难?  发表于 2014-11-3 11:20
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

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

GMT+8, 2024-4-25 13:32 , Processed in 0.043114 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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