抓取AJAX数据
本示例可参考示例文件"CaseStudy\WebViewer\网页自动化.Table"的窗口"抓取股票数据"
前面几节实现的网页数据抓取和自动登录,都有一个前提,就是有一个目标网页要跳转,Foxtable在异步等待网页加载完毕后进行判断处理。
但是很多场景并没有网页跳转,而是通过AJAX局部动态更新数据和网页内容,这种情况用WebViewer处理起来同样简单。
本节的任务是抓取以下网页的股票交易数据:
http://data.10jqka.com.cn/funds/ggzjl/
当我们在这个页面单击不同的页码,或者单击"下一页"时,并不会跳转网页,而是通过AJAX刷新table元素的数据。
模拟单击下一页以及数据的抓取都比较简单,和前面的示例无异。
最大的问题是如何判断AJAX执行成功了呢?
原理:
AJAX刷新数据后,网页某些元素的内容必定会发生变化,我们通过跟踪关键元素的内容,即可判断本次AJAX数据刷新是否成功。
以上面的网站为例,有一个显示页码和总页数的元素,其class为"page_info",我们只需跟踪这个元素的内容变化,即可判断出本次AJAX刷新是否成功。
测试代码:
'''Async
Dim
wv
As
WebViewer = e.Form.Controls("WebViewer1").WebViewer
wv.CoreWebView2.Navigate("http://data.10jqka.com.cn/funds/ggzjl/")
'打开同花顺页面
Dim
ret
As
Integer
=
Await
wv.NavigationTaskAsync(10)
'异步等待网页加载完成,等待时间为10秒
If
ret <> 0
Then
MessageBoxA.Show("网页加载失败,终止程序")
Return
End
If
Dim
pageInfo = wv.querySelector(".page_info")
'这是一个关键元素,显示了页码和总页数,通过这个元素的内容可以判断换页是否成功
Dim
pageString
As
String
= (Await
pageInfo.textContent).Trim("""")
Dim
pageCount
As
Integer
= pageString.Split("/")(1)
'获取总页数
For
page
As
Integer
= 0
To
1
'只获取两页数据,如果要获取所有数据,请将1改为pageCount
-2
Dim
stRows = wv.querySelectorAll("table.m-table.J-ajax-table
tbody tr")
'获得所有数据行
Dim
rowsCount
As
Integer
=
Await
stRows.length
'获得总行数
For
r
As
Integer
= 0
To
rowsCount - 1
'遍历行
Dim
dr
As
DataRow = DataTables("资金表即时").AddNew()
dr("序号")
=
CInt((Await
stRows(r).cells(0).innerText).Trim(""""))
dr("股票代码")
= (Await
stRows(r).cells(1).innerText).Trim("""")
dr("股票简称")
= (Await
stRows(r).cells(2).innerText).Trim("""")
dr("最新价")
= val((Await
stRows(r).cells(3).innerText).Trim(""""))
dr("涨跌幅")
= val((Await
stRows(r).cells(4).innerText).Trim("""").Trim("%"))
dr("换手率")
= val((Await
stRows(r).cells(5).innerText).Trim("""").Trim("%"))
dr("流入资金(元)")
= val((Await
stRows(r).cells(6).innerText).Trim(""""))
dr("流出资金(元)")
= val((Await
stRows(r).cells(7).innerText).Trim(""""))
dr("净额(元)")
= val((Await
stRows(r).cells(8).innerText).Trim(""""))
dr("成交额(元)")
= val((Await
stRows(r).cells(9).innerText).Trim(""""))
Next
Dim
nextPage = wv.xpathQuery("//a[@class='changePage'
and text()='下一页']")
'取得下一页元素
If
Await
nextPage.isNull()
Then
Return
'如果没有下一页这个元素,说明已经是最后一页,直接退出
End
If
Dim
oldpage
As
String
=
Await
pageInfo.textContent
'获得当前页码
Dim
success
As
Boolean
=
False
nextPage.click()
'模拟单击下一页按钮
For
m
As
Integer
= 1
To
20
'每0,5秒查询一次页码,10秒内页码没发生变化的话,则认为刷新失败
Await
task.Delay(500)
'间隔0.5秒
Dim
nepage
As
String
=
Await
pageInfo.textContent
'获得新页码
If
nepage <> oldpage
Then
'如果页码有变化
success =
True
'说明已经跳转到下一页
Exit
For
End
If
Next
If
success =
False
Then
'如果跳转到下一页失败
MessageBoxA.Show("获取到第"
& (page + 1) &
"页数据时失败")
Return
End
If
Await
task.Delay(3000)
'延迟3秒,避免被反爬,根据需要调整时间,可选
Next