VB网页抓取想要的.docx
《VB网页抓取想要的.docx》由会员分享,可在线阅读,更多相关《VB网页抓取想要的.docx(23页珍藏版)》请在冰豆网上搜索。
VB网页抓取想要的
在大多数情况下,上网冲浪是件令人愉快的事情。
但若是数百上千的超链接摆在你面前,而
你又不得不一一点击这些链接、进入相应的网页、手工筛选出每页里你需要的信息、最后再将这
些信息编进数据库中、,你将做何感想?
如果每天都从事这种繁杂、枯燥的工作会不会让你发
疯?
“自动上网机器人”或许可救你出“苦海”:
你可以喝着咖啡、听着音乐、看着“机器人”辛勤地替
你工作,那感觉是不是棒极了!
本文结合实例详尽讨论了用VB实现“上网机器人”的技术细节。
我们知道,搜集和下载资料是
人们使用互联网的最主要的目的之一,但有些信息资源过于庞大,用手工摘取的方法是困难的或
根本就是行不通的。
例如,你需要搜集欧洲进口机械设备的公司名录以便给他们发信邀请其参加
博览会,在网上找到这些信息并不难,但出于数据安全等方面的考虑,几乎所有提供类似信息的
网站都没有提供直接下载数据的功能。
要想搜集齐想要的数据,唯一可用的方法就是一页一页地浏览每个公司的信息页,摘取其中
有用的数据并存入数据库。
但当公司总数超过数千时,巨大的工作量会让任何人望而却步!
其实,
这浩大的工作完全可以由程序来完成,因为这些任务完全是机械的重复性工作。
而且,用程序完
成比用手工要快得多。
本文涉及的技术细节是通用的,即对实例程序稍加修改就可完成任何“自
动上网冲浪”任务。
自动拨号上网、自动处理中途掉线、任务完成后自动挂断,这些都是“上网机器人”的最基本
的功能之一。
它还能给你带来明显的经济回报:
如果你让“机器人”在晚间至凌晨的上网费优惠期
内拨号上网去自动冲浪,那真可称得上是典型的“一石三鸟”你睡觉、它工作、还省钱!
有关
这方面的细节将在本文的第三部分里讨论。
该部分提供了实现上述各功能的若干方法,并比较了
这些方法各自的优劣。
本文的第一和第二部分分别以两个实例讨论了自动浏览的技术细节:
在网页上的输入区内自
动填入数据以便完成诸如用户登录等的操作、自动更新CheckBox、自动选择下拉式列表
(ComboBox)的值、自动点击网页上的按钮、从网页上精确提取有用的数据并存盘、将网页上
二维表(Table)内的数据一一提取出来并转换且存储成可直接导入数据库或Excel的格式,以
及控制浏览进程的技巧等等。
第一部分从网页上精确提取数据
本部分的实例是:
下载沪深两市全部约1100家个股的基本信息及财务数据。
若用手工操作,
如上图所示,需要在股票代码区内分别输入1100个股票代码,在下拉式列表(ComboBox)中
分别选择“个股资料”和“财务数据解读”,算下来约是2200次操作!
这样的工作当然是由程序来
完成划算得多。
况且手工提取数据(先选中、再使用Ctrl+C拷贝)极容易出错(多选或漏选),
又很费眼神。
1.在输入区内自动填入数据
为使程序能高效地自动浏览,需引入一些最基本的功能,如在输入区内自动填入数据、自动
点击按钮等等。
虽然用变换URL地址的方法有时也能完成任务,但往往过于费力,尤其当网页
上的输入区较多时更是如此。
为了在输入区内输入数据,需要先搜索到该对象的名字,然后将该对象的值置为要填入的数
据即可。
搜索名字的工作可编程完成,亦可用FrontPage轻松获得。
2.自动在下拉式列表(ComboBox)中进行选择
同样地,首先要获得下拉式列表的名字。
然后根据下拉式列表的元素总数(length属性)在列
表中搜索要设置的值(列表的Options集合中元素的Text属性),找到后,将该元素设为选中元
素(元素的Selected属性)。
3.自动点击按钮
对于按钮来讲,可根据其名字访问,亦可根据其值访问。
按钮的值就是显示在按钮上的文字。
一个按钮可能没有名字,但一定有值。
本例的程序就是根据值来访问按钮。
执行按钮的Click
方法就相当于点击了该按钮。
图二中红色箭头所指即为程序自动填入输入框、自动在ComboBox中选择以及自动点击按钮
4.精确提取数据
仅将有用的数据存储下来才是有意义的。
必须研究网页,找出有效数据所在的Tag区(可用
文本编辑器或FrontPage),然后用该对象的innerText属性获得最终的文本。
本例中要存储的数
据如下图所示,其所用的Tag为“PRE”。
下面给出的是实例程序的完整代码:
'程序一:
从网页上精确提取数据'
'为运行本程序,应在“菜单->工程->部件”中添加“MicrosoftInternetControls
'并在“菜单->工程->引用”中添加“MicrosoftHTMLObjectLibrary”'
'为了简洁,程序仅下载九只个股的基本信息
OptionExplicit
PrivateConstForm_ID=1
DimCode(9)AsString
DimCurrentAsLong
PrivateSubForm_Load()Form1.MousePointer=11'以下是个股代码'为了程序简洁,这里仅使用九只代码。
'而在真实环境中,应从数据文件中读入全部个股代码。
Code(0)="600001":
Code
(1)="600002":
Code
(2)="600003"
Code(3)="600005":
Code(4)="600006":
Code(5)="600007"
Code(6)="600008":
Code(7)="600009":
Code(8)="600010"
Current=0
WebBrowser1.Navigate""'起始网址
EndSub
PrivateSubWebBrowser1_DocumentComplete(ByValpDispAsObject,URLAsVariant)
Dimi,k
Text2=WebBrowser1.LocationURL'显示当前网址
'判断当前网页是否全部调入完毕
IfNot(pDispIsWebBrowser1.Object)ThenExitSub
OnErrorResumeNext
SelectCaseText2
Case"'当进入主页面时执行以下程序
Fori=0ToWebBrowser1.Document.Forms(Form_ID).length-1
'找到代码输入框后填入个股代码
IfWebBrowser1.Document.Forms(Form_ID)(i).Name="code"Then_
WebBrowser1.Document.Forms(Form_ID)(i).Value=Code(Current)
'在下拉式列表中进行选择
IfWebBrowser1.Document.Forms(Form_ID)(i).Name="target"Then
Fork=0ToWebBrowser1.Document.Forms(Form_ID)(i).length-1
IfWebBrowser1.Document.Forms(Form_ID)(i).Options(k).Text_
="个股资料"Then
WebBrowser1.Document.Forms(Form_ID)(i).Options(k).Selected=True
ExitFor
EndIf
Nextk
EndIf
'点击按钮
IfWebBrowser1.Document.Forms(Form_ID)(i).Value="查询"Then_
WebBrowser1.Document.Forms(Form_ID)(i).Click
Next
CaseElse'当进入数据页面时执行以下程序
Fori=0ToWebBrowser1.Document.All.length-1
IfWebBrowser1.Document.All(i).tagName="PRE"Then
'精确提取数据
Text1=Text1+Code(Current)+vbCrLf+_
WebBrowser1.Document.All(i).innerText+vbCrLf
ExitFor
EndIf
Next
'数据存盘
Open"C:
\Data2.Txt"ForAppendAs#1
Print#1,Text1:
Text1="":
Close#1
'换下一只股票
Current=Current+1
IfCurrent>=9Then
'上网任务完成后,应在此调用自动挂断过程。
Form1.MousePointer=0:
MsgBox"Finished!
":
End
EndIf
'回退到主页面,查询下一只股票的信息
WebBrowser1.GoBack
EndSelect
EndSub
第二部分将网页上的二维表导入数据库
在上一部分中,我们讨论了让程序自动在网上浏览并将所需的数据准确、快速地存储下来的
方法。
现在,我们将迎接更大的挑战:
将网页上以表格形式存在的二维数据提取出来,并存成可
直接导入数据库的“MicrosoftExcel逗号分隔值文件”(即.csv文件)。
用手工在网页上直接提取类似上图中所示的表格数据是非常困难的。
如果这样的表格有数十页甚至上百页之多,手工提取工作将是不可想象的,而且非常容易出错。
本部分的实例是:
将沪深两市全部约1100家个股的财务评分表数据(共54页,每页20家,
如上图所示)快速、准确地转换成“.csv文件。
”
1.自动设置CheckBox的值
由于只有注册用户才能访问上述财务评分表,因此实例程序首先演示了自动注册的功能。
下
我们在上一部分中已讨论了自动填写输入区以及自动点击按钮等的方法。
对于自动设置
CheckBox值,其方法完全类似:
首先要搜索到该CheckBox的名字,然后将该对象的Checked
属性置为True或False即可。
2.将网页上的二维表导入数据库
首先定义一个IHTMLElementCollection对象用于收集网页上所有的Table,然后用getElementsByTagName方法执行收集工作:
DimTablesAsIHTMLElementCollection
SetTables=WebBrowser1.Document.getElementsByTagName("Table")
一个网页上往往有多个Table。
我们用HTMLTable对象来处理每个Table:
DimTable1AsHTMLTable
ForEachTable1InTables
Next
HTMLTable对象的innerText属性记录了整个Table的全部信息,包括字段名。
因此我们可以
根据字段名判断出哪个Table是我们需要的。
为了逐行逐列地提取数据,我们还需要HTMLTableRow对象和HTMLTableCell对象:
DimRowAsHTMLTableRow,CellAsHTMLTableCell
Fori=1ToTable1.rows.length-1'逐行处理
SetRow=Table1.rows(i)
j=0
ForEachCellInRow.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控件对
象本身:
PrivateSubWebBrowser1_DocumentComplete(ByValpDispAsObject,_
URLAsVariant)
If(pDispIsWebBrowser1.Object)Then
Debug.Print"Documentisfinishedloading.
EndIf
EndSub
下面是实例程序的完整代码(运行该程序可得到完整的1061行“.csv格式的数据,分别代表”
1061个上市公司的财务信息。
该文件可直接导入Access数据库或Excel中。
):
'程序二:
将网页上的二维表导入数据库
'
'为运行本程序,应在“菜单->工程->部件”中添加“MicrosoftInternetControls”
'并在“菜单->工程->引用”中添加“MicrosoftHTMLObjectLibrary”
'
OptionExplicit
DimPageAsLong
PrivateSubForm_Load()
Form1.MousePointer=11
WebBrowser1.Navigate""'起始网址EndSub
PrivateSubWebBrowser1_DocumentComplete(ByValpDispAsObject,URLAsVariant)
DimTable1AsHTMLTable,TablesAsIHTMLElementCollection
DimRowAsHTMLTableRow,CellAsHTMLTableCell
Dimi,j,tmp
Text2=WebBrowser1.LocationURL'显示当前网址
'判断当前网页是否全部调入完毕
IfNot(pDispIsWebBrowser1.Object)ThenExitSub
OnErrorResumeNext
SelectCaseText2
Case"'当进入主页面时执行以下程序'用户注册登录
Fori=0ToWebBrowser1.Document.Forms(0).length-1
'找到CheckBox后,将其值改为False,以防止用户名及密码被存储
IfWebBrowser1.Document.Forms(0)(i).Name="checkSavePW"Then_
WebBrowser1.Document.Forms(0)(i).Checked=False
IfWebBrowser1.Document.Forms(0)(i).Name="userId"Then_
WebBrowser1.Document.Forms(0)(i).Value="kompass_china"
IfWebBrowser1.Document.Forms(0)(i).Name="passwd"Then_
WebBrowser1.Document.Forms(0)(i).Value="kompass1"
'此处是按名字访问按钮(上例中是按值访问按钮)
IfWebBrowser1.Document.Forms(0)(i).Name="continue"Then_
WebBrowser1.Document.Forms(0)(i).Click
Next
Case"
'当用户登录完成后,准备打开表格的第一页
WebBrowser1.Navigate"+_
"showstkdfpm&begin=0&ret=1&index=2&concode=01"
Page=1
CaseElse'当进入数据页面(表格的第一页至最后一页)时执行以下程序
SetTables=WebBrowser1.Document.getElementsByTagName("Table")ForEachTable1InTables
IfLeft(Table1.innerText,2)="名次"Then'找到需要的Table
'将表格转换成“.csv格式”
Fori=1ToTable1.rows.length-1
SetRow=Table1.rows(i)j=0
ForEachCellInRow.cells
Text1=Text1+Trim(Row.cells(j).innerText)+","j=j+1
Next
Text1=Left(Text1,Len(Text1)-1)+vbCrLf
Next'数据存盘
Open"C:
\Data.csv"ForAppendAs#1
Print#1,Left(Text1,Len(Text1)-2):
Text1="":
Close#1
ExitFor
EndIf
Next'准备打开下一页
Page=Page+1
tmp="+_Trim(Str(Page))+"&index=2&concode=01"
IfPage<=54Then'判断是否浏览结束
WebBrowser1.Navigatetmp
Else'上网任务完成后,应在此调用自动挂断过程。
Form1.MousePointer=0MsgBox"Finished!
!
":
EndEndIf
EndSelect
EndSub
以下给出的是上述程序所存数据文件的片段:
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是微软的“拨号网络用户接口”程序集,一般在“System”目录下。
其中的
RnaDial程序用于启动拨号。
该程序可在命令行执行(在“开始”->“运行”中键入):
rundll32.exernaui.dll,RnaDial<拨号网络连接名>
其中的“RnaDial和”“<拨号网络连接名>”是区分大小写的。
但由于上述命令仅启动拨号窗口而未立即开始拨号,因此在程序中使用时还应再
送出模拟“回车”的按键:
ret=Shell("rundll32.exernaui.dll,RnaDial"+连接名,1)
SendKeys"{enter}",True
方法1B:
使用wininet.dll
wininet.dll是微软的Internet扩充函数集,一般在“System”目录下。
其中的
InternetAutodial、InternetAutodialHangup和InternetGetConnectedState三个函数分别可完成自动拨
号