自动上网抓数据的机器人[2]

[入库:2005年8月18日] [更新:2007年3月24日]

本文简介:选择自 hsn1982 的 blog

    htmltable对象的innertext属性记录了整个 table的全部信息,包括字段名。因此我们可以根据字段名判断出哪个 table是我们需要的。

    为了逐行逐列地提取数据,我们还需要htmltablerow对象和htmltablecell对象:

dim row ashtmltablerow, cell as htmltablecell
    for i = 1 to table1.rows.length - 1      ' 逐行处理
       set row = table1.rows(i)
       j = 0
       for each cell in row.cells      ' 逐列处理
          ' row.cells(j).innertext即为当前行及当前列上的单元数据
          text1 = text1 + trim(row.cells(j).innertext) + ","
          j = j + 1
       next
       ' 一行处理完毕后,去除行尾的逗号并加上回车
       text1 = left(text1, len(text1) - 1) + vbcrlf
    next

    至此,当前网页上的二维表已转换成“.csv”格式。

3. 自动浏览时的页面控制技巧

    我们从上个例子中就已经清晰地看到,自动浏览程序的主体是webbrowser控件的documentcomplete事件。只有在当前页面已被完全调入后,我们才能开始对当前页面进行数据处理,然后再根据当前在哪个页面来决定下一步的浏览方向。

    需要指出的是,documentcomplete事件的发生并不一定意味着当前页面已被全部调入。如果页面上没有其它子框架(frames),发生documentcomplete事件即表明当前页面(即主框架)已完成调入;若页面上有多个框架,则每个框架完成时都会发生documentcomplete事件;当所有子框架都完成后,主框架最后产生一次documentcomplete事件。为了判断出这最后一次documentcomplete事件,需要比较每次事件发生时的对象(pdisp)是否是webbrowser控件对象本身:

private sub webbrowser1_documentcomplete(byvalpdisp as object, _
                                             url as variant)
      if (pdisp is webbrowser1.object) then
        debug.print "document is finished loading."
      end if
    end sub

   下面是实例程序的完整代码(运行该程序可得到完整的1061行“.csv”格式的数据,分别代表1061个上市公司的财务信息。该文件可直接导入access数据库或 excel中。):

' 程序二:将网页上的二维表导入数据库
'
' 为运行本程序,应在“菜单->工程->部件”中添加“microsoft internet controls”
' 并在“菜单->工程->引用”中添加“microsoft html object library”
'
option explicit
dim page as long
private sub form_load()
form1.mousepointer = 11
webbrowser1.navigate "www.stockstar.com.cn" ' 起始网址
end sub
private sub webbrowser1_documentcomplete(byval pdisp as object, url as variant)
dim table1 as htmltable, tables as ihtmlelementcollection
dim row as htmltablerow, cell as htmltablecell
dim i, j, tmp
text2 = webbrowser1.locationurl ' 显示当前网址
' 判断当前网页是否全部调入完毕
if not (pdisp is webbrowser1.object) then exit sub
on error resume next
select case text2
case "http://www.stockstar.com.cn/home.htm" ' 当进入主页面时执行以下程序
' 用户注册登录
for i = 0 to webbrowser1.document.forms(0).length - 1
' 找到 checkbox 后,将其值改为 false,以防止用户名及密码被存储
if webbrowser1.document.forms(0)(i).name = "checksavepw" then _
webbrowser1.document.forms(0)(i).checked = false
if webbrowser1.document.forms(0)(i).name = "userid" then _
webbrowser1.document.forms(0)(i).value = "kompass_china"
if webbrowser1.document.forms(0)(i).name = "passwd" then _
webbrowser1.document.forms(0)(i).value = "kompass1"
' 此处是按名字访问按钮(上例中是按值访问按钮)
if webbrowser1.document.forms(0)(i).name = "continue" then _
webbrowser1.document.forms(0)(i).click
next
case "http://my.stockstar.com/scripts/mystockstar.dll?login"
' 当用户登录完成后,准备打开表格的第一页
webbrowser1.navigate "http://finance.stockstar.com/scripts/finance.dll?" + _
"showstkdfpm&begin=0&ret=1&index=2&concode=01"
page = 1
case else ' 当进入数据页面(表格的第一页至最后一页)时执行以下程序
set tables = webbrowser1.document.getelementsbytagname("table")
for each table1 in tables
if left(table1.innertext, 2) = "名次" then ' 找到需要的table
' 将表格转换成“.csv”格式
for i = 1 to table1.rows.length - 1
set row = table1.rows(i)
j = 0
for each cell in row.cells
text1 = text1 + trim(row.cells(j).innertext) + ","
j = j + 1
next
text1 = left(text1, len(text1) - 1) + vbcrlf
next
' 数据存盘
open "c:\data.csv" for append as #1
print #1, left(text1, len(text1) - 2): text1 = "": close #1
exit for
end if
next
' 准备打开下一页
page = page + 1
tmp = "http://finance.stockstar.com/scripts/finance.dll?showstkdfpm&ret=" + _
trim(str(page)) + "&index=2&concode=01"
if page <= 54 then ' 判断是否浏览结束
webbrowser1.navigate tmp
else
' 上网任务完成后,应在此调用自动挂断过程。
form1.mousepointer = 0
msgbox "finished!!": end
end if
end select
end sub

   以下给出的是上述程序所存数据文件的片段:

1,乐凯胶片,600135,材料,81.493,18.445,23.165,8.850,20.717,10.315
2,歌华有线,600037,传播娱乐,80.553,13.009,22.256,12.141,20.304,12.844
3,外运发展,600270,仓储运输,80.326,17.331,23.005,8.829,19.900,11.261
4,东方钽业,0962,有色金属,80.312,15.160,22.483,11.648,21.290,9.730
5,双汇发展,0895,食品,79.772,15.428,20.673,11.508,20.235,11.930
6,四川美丰,0731,化肥,79.361,15.795,23.235,11.323,16.921,12.088
... ... ...
1059,轮胎橡胶,600623,车类,7.167,8.265,10.973,-34.411,14.120,8.219
1060,pt吉轻工,0546,日用轻工产品,-11.895,5.740,-49.149,7.999,14.136,9.379
1061,广船国际,600685,机械仪器,-57.452,9.824,-1.528,-89.648,14.366,9.533

第三部分  自动拨号、自动挂断以及自动处理中途掉线

    一个出色的“自动上网机器人”程序应能按照既定的时间准时开始拨号、并当所需任务已完成后立即挂断。而且仅做到这些还不够,它还应在发出拨号指令后跟踪拨号操作是否真的成功、上网速度如何、是否需要挂断后重新拨号、自动浏览过程中是否出现掉线、以及最终的挂断操作是否真的成功完成,等等。

    因此,“机器人”程序应定时检查在线状况,以保证浏览时一定在在线状态、浏览完毕后一定不在在线状态。同时还要检查浏览进度,当浏览速度过慢时尝试挂断后重新拨号。

    本部分讨论了实现“自动拨号”、“检查在线状况”、以及“自动挂断”这三个功能的若干方法,比较了诸方法各自的优劣,并总结给出了使用建议。本部分的示例程序将这三个功能的诸方法集成在一起,以便于大家对比使用(见下图)。

1. 自动拨号

    方法1a:使用rnaui.dll

    rnaui.dll是微软的“拨号网络用户接口”程序集,一般在“\windows\system”目录下。其中的rnadial程序用于启动拨号。该程序可在命令行执行(在“开始”->“运行”中键入):

    rundll32.exe rnaui.dll,rnadial <拨号网络连接名>

    其中的“rnadial”和“<拨号网络连接名>”是区分大小写的。

    但由于上述命令仅启动拨号窗口而未立即开始拨号,因此在程序中使用时还应再

送出模拟“回车”的按键:

ret = shell("rundll32.exe rnaui.dll,rnadial " + 连接名, 1)
    sendkeys "{enter}", true

    方法1b:使用wininet.dll

    wininet.dll是微软的internet扩充函数集,一般在“\windows\system”目录下。其中的internetautodial、internetautodialhangup和internetgetconnectedstate三个函数分别可完成自动拨号、自动挂断和判断在线状态等任务。internetautodial的定义为:

private declare function internetautodial lib "wininet.dll" _
           (byvaldwflags as long, byvaldwreserved as long) as long

        若将第一个参数(dwflags)的值设为2,该函数无需用户干预就可自动拨号。但使用该函数有一个前提:即必须将“internet 属性”->“连接”设成“始终拨打默认连接”(见下图)。

    用internetautodial函数自动拨号的情况可参见下图。从图中可以看出,该方法可自动重试多次。具体的重试次数在默认连接的“设置”->“高级”中定义:

本文关键:WebBrowser,拨号
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top