ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[讨论] VBA中使用XMLHTTP网抓,实现并行+持久连接初探

[复制链接]

TA的精华主题

TA的得分主题

发表于 2015-7-17 16:14 | 显示全部楼层 |阅读模式
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 liu-aguang 于 2015-7-17 17:57 编辑

直接上两个附件.两附件中代码结构一样. 想聚焦在实现"并行+持久连接"的VBA代码结构,代码并没有进行容错处理.请同志们指出代码中可能的潜在问题.
XMLHTTP并行.rar (27.18 KB, 下载次数: 173)
XMLHTTP并行 持久连接.rar (30.05 KB, 下载次数: 192)

说明:
一. 测试中可能遇到的问题
1. 首次运行时,无论何种连接方式速度会慢许多,原因有:
...... 各连接需要首先解析DNS,即要向远程DNS主机查询IP. 解析出的IP会在电脑缓存中保存,所以第二次以后,会省下这个时间.
......用XMLHTTP方式, 它自带缓存. 第二次执行时,只要页面在生存期内,请求页面不会去远程服务器索取,而直接读缓存内容.
2. 如果在工作表中, 修改并发连接数为1, 这时相当于OPEN的第三个参数选择False的效果.
3. 不要试图通过拷贝代码的方式, 把类模块中代码拷贝到其它工作薄来测试. 如果需要在其它工作薄测试,请把附件工作薄中的类模块导出,然后导入其它工作薄.

二. 关于串行, 并行和持久连接
1. 持久连接与非持久连接
非持久连接方式. 每取回一个页面之前,首先建立一个连接, 取回后,立即断开连接.
持久连接方式在取回页面后, 客/服双方连接并不会断开,下一个请求可以重用.这种方式可以提高取回复合页面的效率.
HTTP /1.0默认是非持久连接方式, 欲转换为持久连接,需要在头部增加Connection:Keep-Alive. Http /1.1默认是持久连接的.
如果客户端和服务器其中一方设置Connection: Close, 或某个中间设备不支持Connection头部,都不可能实现持久连接.
在上面第一个附件中的网站服务器的Connection设置为Close,所以即使每个连接的IP一样,也不可能实现持久连接.
2. 持久连接或非持久连接是串行实现HTTP事务的.
所谓串行, 即是每完成一个事务(一个页面取回结束),才能够重新发送请求. 这种方式可能带来的问题是:
......浪费带宽. 即使你有20M的带宽, 也只有让一个也许只有几个K的数据传送完后,才可以进行下一次请求.
......在多页面的下载中, 如果中途遇到一个打开很困难的网页,那么你除了等待它慢慢完成外,其它什么事也做不成.
3. 并行连接
HTTP连接是由操作系统控制的, 它允许同时进行多个连接. 且并发操作.这样多数情形下,可以提高多页面下载的速度.
但并行连接太多也不是什么好事:
.......违反社会道德. 可以想像服务器会有多累. 并且用户间相互竞争的结果,谁也不得到好处.所以HTTP协议中规定只能并行2个,而现实中各种浏览器一般在2-8个之间.IE8在宽带时为4个.
.......由于每一个新的连接在建立时会消费一定软硬资源, 并行连接太多可能导致电脑性能急剧下降,从而得不偿失.
.......连接存在一个慢启动机制. 在连接刚建立时,传输速度会很慢,依次传输成功后,速度才会渐渐提升. 也就是说开始有一个速度"调谐"过程. 太多并行连接也就意为着每次都在使用慢传送.
.......如果带宽受限, 太多并行连接对带宽的争夺会导致每连接都十分缓慢.
.......多数网站会判断为攻击,封你IP!
4.适量的并行+持久连接-------理想的实现方式. 抓包可看出IE是按这种方式组织的.


TA的精华主题

TA的得分主题

发表于 2015-7-17 19:57 | 显示全部楼层
模块
  1. Dim oXhr As XhrConn

  2. Sub x()
  3.     Set oXhr = New XhrConn
  4.     With oXhr
  5.         .Url = "http://www.baidu.com"
  6.         .xhr.onreadystatechange = oXhr
  7.         .go
  8.     End With
  9. End Sub
复制代码


XhrConn 类
  1. Public xhr As XMLHTTP, Url$

  2. Private Sub Class_Initialize()
  3.     Set xhr = New XMLHTTP
  4. End Sub

  5. Sub Ready() ' 默认方法
  6.     If xhr Is Nothing Then Exit Sub
  7.     If xhr.readyState = 4 Then
  8.         If xhr.Status = 200 Then
  9.             Debug.Print "OK", Left(xhr.responseText, 50)
  10.         Else
  11.             Debug.Print xhr.readyState, xhr.Status
  12.         End If
  13.     End If
  14. End Sub

  15. Sub go()
  16.     If xhr Is Nothing Then Exit Sub
  17.     xhr.Open "get", Url, True
  18.     xhr.send
  19. End Sub
复制代码


这样写,结构清晰。好理解。

TA的精华主题

TA的得分主题

发表于 2015-7-17 20:22 | 显示全部楼层
本帖最后由 coby001 于 2015-7-17 20:23 编辑



XhrConn 类的 go 方法改成这样

Sub go(Optional sUrl$ = "")
    If LenB(sUrl) Then Url = sUrl
    If xhr Is Nothing Then Exit Sub
    xhr.onreadystatechange = Me
    xhr.Open "get", Url, True
    xhr.send
End Sub
--------------------


模块 里可以更加简化
Sub x()
    Set oXhr = New XhrConn
    oXhr.go  "http://www.baidu.com"
End Sub


TA的精华主题

TA的得分主题

 楼主| 发表于 2015-7-17 20:22 | 显示全部楼层

这种方式把主要操作包装到类里, 可以让代码结构清楚一些. 不过对同IP多页面的连接请求也只能做到并行.不能充分利用持久连接的优势. 另外, 也无法控制并行连接数.
1楼代码只在类中封装了对ReadState状态的处理. 主要目的是实现并行的基础上, 获得持久连接的优势. 前些时候通过抓包软件分析,发现连续的不同XMLHTTP对象的请求, 产生不同的连接(端口不同), 而同一对象的连续请求可以重用同一连接.

TA的精华主题

TA的得分主题

发表于 2015-7-17 20:26 | 显示全部楼层
liu-aguang 发表于 2015-7-17 20:22
这种方式把主要操作包装到类里, 可以让代码结构清楚一些. 不过对同IP多页面的连接请求也只能做到并行.不 ...

Dim oArrXhr() As XhrConn

定义成全局数组就可以了。

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-7-17 20:28 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
明天有时间具体测试一下你的代码.

TA的精华主题

TA的得分主题

发表于 2015-7-17 20:38 | 显示全部楼层
liu-aguang 发表于 2015-7-17 20:28
明天有时间具体测试一下你的代码.

好用就给朵花呗~
{:soso_e144:}

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-7-18 08:32 | 显示全部楼层
coby001 发表于 2015-7-17 20:22
XhrConn 类的 go 方法改成这样

Sub go(Optional sUrl$ = "")

把XMLHTTP对象包装在类中是可以的,但要实现并行+持久连接功能,还有很多工作要做:
并行控制: 包括并行数控制和并行带来的非顺序结果的正确填写(数组);结果写表方式易冲突.
持久连接功能的实现: 当客户/服务器条件准许, 代码要同时提供持久连接功能的代码结构;
并行与持久连接的衔接.
结束控制: 标准模块代码不会与类模块同步结束, 必须考虑最后结果的写表操作控制
........当一切工作完成后,会发现代码结构就不会那么清爽了.

TA的精华主题

TA的得分主题

发表于 2015-7-18 08:40 | 显示全部楼层
liu-aguang 发表于 2015-7-18 08:32
把XMLHTTP对象包装在类中是可以的,但要实现并行+持久连接功能,还有很多工作要做:
并行控制: 包括并行数 ...

封装后,那些繁琐代码只在类里写一次。然后无脑 New 就可以了~

什么冲突控制,都可以封起来~~

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-7-18 09:26 | 显示全部楼层
coby001 发表于 2015-7-18 08:40
封装后,那些繁琐代码只在类里写一次。然后无脑 New 就可以了~

什么冲突控制,都可以封起来~~

如果可能,建义写一个完整代码,供大家研讨.(用顶楼第二个附件中的凤凰即时新闻做例子吧, 读页相对简单,其服务器提供的是持久连接,并且可做较大数据页面的测试.)
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-22 12:24 , Processed in 0.053115 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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