excel股票实时数据和vba获取股票实时数据
Web Service是一种新的Web应用程序分支,其可以执行从简单的请求到复杂商务处理的任何功能。Web Service技术使得运行在不同机器上的不同应用进行数据交互或集成。
1、Web Service简介
Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。Web Service的主要目标是跨平台的可互操作性。为了实现这一目标,Web Service 完全基于XML(可扩展标记语言)、XSD(XML Schema)等独立于平台、独立于软件供应商的标准,是创建可互操作的、分布式应用程序的新平台。
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
应用程序接口(API:application programming interface)是一组定义、程序及协议的集合,通过 API 接口实现计算机软件之间的相互通信。API 的一个主要功能是提供通用功能集。程序员通过使用 API 函数开发应用程序,从而可以避免编写无用程序,以减轻编程任务。
2、腾讯股票实时数据
腾讯提供相对稳定、免费的股票即时数据Web Service API接口,分为股票实时数据详细信息和简要信息。
I、股票实时数据详细信息
接口:http://qt.gtimg.cn/q=sh601006
返回值:
v_sh601006="1~大秦铁路
~601006~7.48~7.43~7.43~260548~145815~114733~7.47~590~7.46~4407~7.45~3851~7.44~1062~7.43~3079~7.48~686~7.49~4629~7.50~6627~7.51~2656~7.52~2393~~20230703155612~0.05~0.67~7.50~7.39~7.48/260548/194083793~260548~19408~0.17~9.53~~7.50~7.39~1.48~1132.80~1132.80~0.86~8.17~6.69~0.85~-4002~7.45~7.75~10.12~~~0.54~19408.3793~0.0000~0~
~GP-A~11.98~3.46~6.30~9.00~6.66~8.21~5.95~0.13~-1.06~4.03~~~-13.35~11.98~~~~22.02~0.00~~CNY~0~___D__F__N";
7.40~-3.77~4.15~22.45~18.52~216.11~128.55~-3.24~1.50~-14.46~3881525907~3881608005~-30.63~-1.94~3881525907~~~-12.97~-0.15~~CNY~0~___D__F__N";
注:腾讯股票实时行情数据接口网址中“sh”表示上海、“sz”表示深圳。如,“sh600653”为上证交易所的“申华控股”、“sz000021”为深圳交易所“深科技”;以 “~” 分割字符串中内容,下标从0开始
这个字符串由许多数据拼接在一起,不同含义的数据用逗号隔开了,对于网页前台程序员来说,这就是定义好的格式化字符变量。按数据循序具体含义为:
|
[0] 证券所 [1] 名字 [2] 代码 [3] 当前价格 [4] 昨收 [5] 今开 [6] 成交量(手) [7] 外盘 [8] 内盘 [9] 买一 [10] 买一量(手) [11] 买二 [12] 买二量 [13] 买三 [14] 买三量 |
[15] 买四 [16] 买四量 [17] 买五 [18] 买五量 [19] 卖一 [20] 卖一量 [21] 卖二 [22] 卖二量 [23] 卖三 [24] 卖三量 [25] 卖四 [26] 卖四量 [27] 卖五 [28] 卖五量 [29] 最近逐笔成交 |
[30] 时间 [31] 涨跌 [32] 涨跌幅(%) [33] 最高 [34] 最低 [35] 价格/成交量(手)/成交额 [36] 成交量(手) [37] 成交额(万) [38] 换手率 [39] 市盈率(TTM) [40] [41] 最高 [42] 最低 [43] 振幅 [44] 流通市值 |
[45] 总市值 [46] 市净率 [47] 涨停价 [48] 跌停价 [49] 量比 [50] [51] 均价 [52] 市盈率(动) [53] 市盈率(静) |
II、股票实时数据简要信息
接口:http://qt.gtimg.cn/q=s_sh601006
返回值:
v_s_sh601006="1~大秦铁路
~601006~7.48~0.05~0.67~260548~19408~~1132.80~GP-A";
具体含义为:
|
[0] 未知 [1] 名字 [2] 代码 |
[3]当前价格 [4]涨跌 [5]涨跌% |
[6]成交量(手) [7]成交额(万) [8] 总市值 |
6秒是交易所发给常规会员单位的实时数据刷新时间间隔!会员单位一般都追求0延迟,交易所有多快他们就尽量做到有多快; 对于转接数据或者N手转让数据,这个6秒就不能够保证了,一般会更长。 如果你发现是一分钟更新一次的话 那说明他们后台在以60秒为单位自行打包接收到的数据。 这个现象在一些中小网站的页面报价中也存在,具体时间间隔 由他们自己划定。
3、实时数据抓取
这里我们介绍抓取腾讯股票实时数据简要信息。
I、股票选择
在sheet1表格中选择感兴趣的股票(股票池),如图:
必要的信息是股票代码和名称,其它列信息根据自己的要求标注即可。沪深两市上市交易股票数量有5000多只,选择抓取股票的数量取决于用户特点、网络传输速度和电脑性能等多种因素。
在sheet3表格中选择主要股票指数和ETF基金指数,如图:
II、数据抓取窗体即功能
建立窗体如下图:
注:窗体UserForm1的ShowModel属性设为False,使得打开窗体后可切换到EXCEL表格中
CommandButton1:【数据抓取】命令按钮;
TextBox1:文本框,打开窗体时显示选股数,运行时显示序号;
TextBox2:文本框,鼠标点击sheet1或sheet3中的代码所在单元格,WebBrowser1网页控件显示所选代码历史数据图形;
ComboBox1:复合框控件,下拉可选不同类型图形;
WebBrowser1:网页控件。
运行结果如下:
点击【数据抓取】按钮,按sheet1所列股票代码抓取实时交易信息(抓取进程序号显示在)在sheet2中,如图:
按sheet3所列股票指数代码抓取实时交易信息在sheet4中,如图:
点击【数据抓取】按钮如果弹出下面警告窗口,按【确定】即可。
III、VBA代码
窗体初始化事件代码:
Private Sub UserForm_Initialize() 'WebBrowser1控件加载上证指数分时线图形 WebBrowser1.Navigate "http://image.sinajs.cn/newchart/min/n/sh000001.gif" '复合框初始化 ComboBox1.AddItem "分时线" ComboBox1.AddItem "日K线" ComboBox1.AddItem "周K线" ComboBox1.AddItem "月K线" ComboBox1.ListIndex = 0 '计算要抓取的股票和指数数量和 TextBox1.Value = Sheet1.UsedRange.Rows.Count + Sheet3.UsedRange.Rows.Count - 4 End Sub
点击【数据抓取】代码:
Private Sub CommandButton1_Click() Dim i, k As Integer Dim ID As String Dim str As String Dim URL As String Dim app, wb, wc '建立Application对象 Set app = CreateObject("Excel.Application") Sheet2.Cells.Clear Sheet2.Cells(1, 1) = "代码" Sheet2.Cells(1, 2) = "名称" Sheet2.Cells(1, 3) = "实时价格" Sheet2.Cells(1, 4) = "涨跌" Sheet2.Cells(1, 5) = "涨跌(%)" k = Sheet1.UsedRange.Rows.Count For i = 1 To k - 1 ID = Sheet1.Cells(i + 1, 1) '设置股票代码 URL = "http://qt.gtimg.cn/q=s_" & ID '构造新浪股票实时行情数据接口地址 Set wb = app.Workbooks.Open(URL) '由当前工作簿打开数据接口 Set wc = wb.Sheets.Item(1) '提取数据接口返回的文本信息 str = wc.Cells(1, 1).Text Sheet2.Cells(i + 1, 1) = ID Sheet2.Cells(i + 1, 2) = Split(str, "~")(1) Sheet2.Cells(i + 1, 3) = Split(str, "~")(3) Sheet2.Cells(i + 1, 4) = Split(str, "~")(4) Sheet2.Cells(i + 1, 5) = Split(str, "~")(5) TextBox1.Value = i Next i Sheet4.Cells.Clear Sheet4.Cells(1, 1) = "代码" Sheet4.Cells(1, 2) = "名称" Sheet4.Cells(1, 3) = "实时价格" Sheet4.Cells(1, 4) = "涨跌" Sheet4.Cells(1, 5) = "涨跌(%)" k = Sheet3.UsedRange.Rows.Count For i = 1 To 8 ID = Sheet3.Cells(i + 1, 1) URL = "http://qt.gtimg.cn/q=s_" & ID Set wb = app.Workbooks.Open(URL) Set wc = wb.Sheets.Item(1) str = wc.Cells(1, 1).Text Sheet4.Cells(i + 1, 1) = ID Sheet4.Cells(i + 1, 2) = Split(str, "~")(1) Sheet4.Cells(i + 1, 3) = Split(str, "~")(3) Sheet4.Cells(i + 1, 4) = Split(str, "~")(4) Sheet4.Cells(i + 1, 5) = Split(str, "~")(5) TextBox1.Value = i Next i Set wc = Nothing wb.Close Set wb = Nothing End Sub
点击sheet1第一列股票代码显示图形代码:
Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim r, c '获得单元格所在行 r = Target.Row '获得单元格所在列 c = Target.Column '调用子过程setChart( r, c, 1),第3个参数为常数1,表示点击的是sheet1 setChart r, c, 1 End Sub
点击sheet3第一列股指数票代码显示图形代码:
Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim r, c r = Target.Row c = Target.Column setChart r, c, 3 End Sub
模块1中用子过程setChart代码:
Sub setChart(r, c, p) Dim s As Integer Dim ID As String If c = 1 And r > 1 Then If p = 1 Then ID = Sheet1.Cells(r, 1) Else ID = Sheet3.Cells(r, 1) End If End If s = UserForm1.ComboBox1.ListIndex If s = 0 Then UserForm1.WebBrowser1.Navigate "http://image.sinajs.cn/newchart/min/n/" & ID & ".gif" If s = 1 Then UserForm1.WebBrowser1.Navigate "http://image.sinajs.cn/newchart/daily/n/" & ID & ".gif" If s = 2 Then UserForm1.WebBrowser1.Navigate "http://image.sinajs.cn/newchart/weekly/n/" & ID & ".gif" If s = 3 Then UserForm1.WebBrowser1.Navigate "http://image.sinajs.cn/newchart/monthly/n/" & ID & ".gif" End Sub
代码中,"
http://image.sinajs.cn/newchart/..."为新浪股票图形接口地址,
新浪股票分时线:http://image.sinajs.cn/newchart/min/n/sh000001.gif"
新浪股票日K线:http://image.sinajs.cn/newchart/daily/n/sh000001.gif
新浪股票周K线:http://image.sinajs.cn/newchart/weekly/n/sh000001.gif"
新浪股票月K线:http://image.sinajs.cn/newchart/monthly/n/sh000001.gif"
将上证指数代码”sh000001“替换为其它股票代码,可显示不同股票所列图形。
下拉框选择不同类图形代码:
Dim r, c, p '当前单元格所在行 r = ActiveCell.Row '当前单元格所在列 c = ActiveCell.Column '当前表格序号 p = ActiveWindow.ActiveSheet.Index setChart r, c, p
打开窗体,鼠标选择sheet1中茅台酒股票代码”sh600519“,如图:
下拉框选择日K线:
下拉框选择周K线:
下拉框选择月K线:
用户可根据自己的判断选择感兴趣的股票进行实时监控,数据抓取刷新后可在其它表格(如sheet5、sheet6等)通过跨表格数据引用进行进一步处理、分析,对个别感兴趣的股票也可以通过不同类图形观察其历史变化趋势。
通过VBA Application对象抓取股票实时数据的效率不是特别理想,优点是不需要解析网页文档,对于不熟悉网页编程的用户不失为一种好的解决方案。
为了便于股票数据查询,可查阅上海和深圳证交所股票代码表,网址如下:
上海:http://www.wstock.net/wstock/market/shcode1.htm 深圳:http://www.wstock.net/wstock/market/szcode1.htm
这两个网页提供了上海和深圳证券交易所股票代码和名称,如图:
两个网页共有220多张表格,每个表格有160个证券代码和名称信息。抓取220×160=35200条证券代码和名称信息,这项任务完全贴近实战,需要较高的EXCEL VBA编程水平。
1、网页结构分析
I、表格结构
用浏览器打开网页后,每张表格中有40×4=160个证券代码和名称。
II、网页分页
上海证券交易所证券代码和名称信息表共有154张表,网址“
http://www.wstock.net/wstock/market/shcode1.htm”中“shcode1.htm”代表第1张表、“shcode2.htm”代表第2张表、...、“shcode154.htm”代表第154张表。
深圳证券交易所证券代码和名称信息表共有75张表,网址“
http://www.wstock.net/wstock/market/szcode1.htm”中“szcode1.htm”代表第1张表、“szcode2.htm”代表第2张表、...、“szcode75.htm”代表第75张表。
III、股票代码筛选
上述两个网址提供的证券代码和名称有股票、有证券和债券,有上市的股票和未上市的股票、有A股和B股。我们的目的是只抓取沪深两市场的上市交易股票。
上证股票A股代码为“6”字头。深圳证券交易所“000”开头为主板、“3”字头为创业板、“002”开头为中小板。代码具备这些开头特征的股票代码是我们抓取的目标。
IV、分页范围
通过翻页观察,上海证券交易所“6”字头股票代码和名称信息表在2-17页;深圳证券交易所“000”开头、“3”字头、“002”开头股票代码和名称信息表在1-14页。两市我们要抓取的数据都在1-20页内。
2、表格信息抓取窗体
I、建立窗体如下图
窗体控件解释:
CommandButton1:【打开网页】命令按钮;
CommandButton2:【网页数据抓取】命令按钮;
TextBox1:网址文本框(单行)
WebBrowser1:网页控件
II、打开Web页面
打开窗体时运用CommandButton1【打开网页】命令按钮打开TextBox1网址文本框中指定的网页
Private Sub CommandButton1_Click() WebBrowser1.Navigate TextBox1.Text End Sub
由于浏览器兼容问题和网页制作者的疏忽,打开网页时往往会弹出上面警告窗口,屏蔽脚本错误的方法如下:
Private Sub CommandButton1_Click() '打开网页时屏蔽脚本错误 WebBrowser1.Silent = True WebBrowser1.Navigate TextBox1.Text End Sub
3、解析HTML文档
I、通过table标签集合抓取表格数据
网页中要抓取的标签没设定id属性,可通过DOM文档模型的
Document.getElementsByTagName获得table标签集合。将CommandButton2【网页数据抓取】命令按钮做为人机对话代码调试按,查找表格集合序号代码如下:
Private Sub CommandButton2_Click() Dim tables As Object Dim i, k As Integer Dim tbRows As Integer ' 获取网文档中所有的table集合 Set tables = WebBrowser1.Document.getElementsByTagName("table") ' 获取网页文档中table标签数量 k = tables.Length For i = 0 To k - 1 Set doc = tables(i) tbRows = doc.Rows.Length If tbRows > 40 Then MsgBox i Exit For End If Next i End Sub
运行窗体,用CommandButton1【打开网页】命令按钮打开TextBox1文本框网址,显示窗体如下,
点击CommandButton2【网页数据抓取】命令按钮,
说明要查找表格集合序号为20。表格集合序号从0开始,说明第21个表格是我们要抓取的表格。
II、表格数据抓取
更换CommandButton2【网页数据抓取】命令按钮代码:
Dim tables As Object ' 获取文档中所有的table集合 Set tables = WebBrowser1.Document.getElementsByTagName("table") ' 获取文档中第21个table对象 Set doc = tables(20) Dim tbRows As Integer Dim tbCols As Integer Dim i, j As Integer tbRows = doc.Rows.Length tbCols = doc.Rows(0).Cells.Length Sheet1.Cells.Clear '不需要表格最后一行 For i = 0 To tbRows - 2 For j = 0 To tbCols - 1 Sheet1.Cells(i + 1, j + 1) = doc.Rows(i).Cells(j).innerText Next j Next i End Sub
运行代码,上交所股票代码和名称网址(
http://www.wstock.net/wstock/market/shcode2.htm)第2页(shcode2.htm)第21个表格部分数据(全部数据到41行)被写入EXCEL文档sheet1表中。如图,
如前所述,上海证券交易所“6”字头股票代码和名称信息表在2-17页,深圳证券交易所“000”开头、“3”字头、“002”开头股票代码和名称信息表在1-13页。
替换TextBox1文本框网址:
'替换shcodeN.htm的分页序号N,N=2,3, ..., 16 上海:http://www.wstock.net/wstock/market/shcode2~16.htm '替换szcodeN.htm的分页序号N,N=1,2, ..., 13 深圳:http://www.wstock.net/wstock/market/szcode1~13.htm
每次替换网址分页序号后,执行【打开网页】、【网页数据抓取】,
反复进行如下操作:
替换网址分页序号
执行【打开网页】
执行【网页数据抓取】
复制、粘贴sheet1表中数据到其它表格
至此,如果信息更新不太频繁、网页分页不多情况下,数据抓取任务就算基本完成了,剩下的工作可以在EXCEL前端完成。
4、数据处理
通常,在网上抓取的信息在格式、内容上不符合我们的要求,需要按要求进行进一步处理。另外,如果抓取信息分页过多、更新频繁,则需要进一步提高数据抓取效率。
I、改进数据抓取流程
在原来窗口添加一个命令按钮和文本框,窗体如下:
CommandButton3:【上证分页数据抓取】命令按钮;
CommandButton4:【深证分页数据抓取】命令按钮
TextBox3:分页序号文本框(单行)
添加UserForm_Initialize窗体初始化事件代码,
Private Sub UserForm_Initialize() Sheet1.Cells.Clear Sheet2.Cells.Clear Sheet3.Cells.Clear End Sub
每次运行窗体,Sheet1、Sheet3、Sheet3表格数据被清空。结果显示如下:
抓取上证数据时,CommandButton3【上证分页数据抓取】命令按钮代码如下:
Private Sub CommandButton3_Click() '上证数据对应shcode TextBox1.Text = "http://www.wstock.net/wstock/market/shcode" & TextBox2.Text & ".htm" Call CommandButton1_Click TextBox2.Text = TextBox2.Value + 1 End Sub
连续点击CommandButton3【上证分页数据抓取】命令按钮,每次点击【序号】自动增加1,从而实现分页数据抓取。
同理,抓取深证数据时,CommandButton4【深证分页数据抓取】命令按钮代码如下:
Private Sub CommandButton4_Click() '深证数据对应szcode TextBox1.Text = "http://www.wstock.net/wstock/market/szcode" & TextBox2.Text & ".htm" Call CommandButton1_Click TextBox2.Text = TextBox2.Value + 1 End Sub
连续点击CommandButton4【深证分页数据抓取】命令按钮,每次点击【序号】自动增加1,从而实现分页数据抓取。
每次打开不同分页时,网页加载成功后执行WebBrowser1的DocumentComplete事件,代码如下:
Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant) Call CommandButton2_Click End Sub
即,连续点击【上证分页数据抓取】命令按钮或【深证分页数据抓取】命令按钮,每次网页加载成功后调用CommandButton2_Click【网页数据抓取】命令按钮。
II、数据筛选
第一步:改进CommandButton2_Click【网页数据抓取】命令按钮代码
Private Sub CommandButton2_Click() Dim tables As Object Dim tbRows As Integer Dim tbCols As Integer Dim i, j As Integer Dim city As String ' 获取文档中所有的table集合 Set tables = WebBrowser1.Document.getElementsByTagName("table") ' 获取文档中第21个table对象 Set doc = tables(20) tbRows = doc.Rows.Length tbCols = doc.Rows(0).Cells.Length Sheet1.Cells.Clear '获取交易所标识符sh或sz city = Mid(TextBox1.Text, 37, 2) '不需要表格最后一行 For i = 0 To tbRows - 2 For j = 0 To tbCols - 1 If i = 0 Or j / 2 <> Int(j / 2) Then Sheet1.Cells(i + 1, j + 1) = doc.Rows(i).Cells(j).innerText Else '保证股票代码为6位数,并在代码获取交易所标识符sh或sz Sheet1.Cells(i + 1, j + 1) = city & Format(Val(doc.Rows(i).Cells(j).innerText), "000000") End If Next j Next i '调用模块子过程setData Call setData End Sub
【网页数据抓取】命令按钮代码经过改进后,在窗体上连续点击【上证分页数据抓取】命令按钮或【深证分页数据抓取】命令按钮。每次点击网页表格数据被抓取到sheet1,然后调用模块子过程setData()将数据按2列写入sheet2。setData()代码如下:
Sub setData() Dim rowCount1, rowCount2 As Long Dim i, j, k As Long '获取Sheet1的数据行数 rowCount1 = Sheets("Sheet1").UsedRange.Rows.Count rowCount2 = Sheets("Sheet2").UsedRange.Rows.Count For i = 2 To rowCount1 For j = 1 To 8 Step 2 If rowCount2 < 2 Then Sheets("Sheet2").Cells(1, 1) = "股票代码" Sheets("Sheet2").Cells(1, 2) = "股票名称" k = Sheets("Sheet2").UsedRange.Rows.Count Sheets("Sheet2").Cells(k + 1, 1) = Sheets("Sheet1").Cells(i, j) Sheets("Sheet2").Cells(k + 1, 2) = Sheets("Sheet1").Cells(i, j + 1) Else k = Sheets("Sheet2").UsedRange.Rows.Count Sheets("Sheet2").Cells(k + 1, 1) = Sheets("Sheet1").Cells(i, j) Sheets("Sheet2").Cells(k + 1, 2) = Sheets("Sheet1").Cells(i, j + 1) End If Next j Next i End Sub
注意,模块子过程setData代码放在【模块1】中,如图,
在窗体上连续点击【上证分页数据抓取】命令按钮,如图,
每次点击,随着序号的变化、页面不断更新,页面表格信息被更新写入sheet1中,如图:
然后调用模块子过程setData()将数据按2列写入sheet2,如图:
注意,在上述过程中,sheet1不断更新、sheet2将sheet1中多列变2列累计写入。对于上证数据来说,按节奏连续点击150次【上证分页数据抓取】命令按钮,150个分页表格的数据被写入sheet1。由于上证和深证的股票代码大致都在1-20页间,分别连续点击20次即可。
最后,再给窗体添加CommandButton5_Click【数据筛选】命令按钮,如图:
CommandButton5_Click【数据筛选】命令按钮,代码如下:
Private Sub CommandButton5_Click() Dim rowCount As Long Dim i, k As Long Dim city As String Dim a, b, c, d As String '获取Sheet2的数据行数 rowCount = Sheets("Sheet2").UsedRange.Rows.Count '获取交易所标识符sh或sz city = Mid(TextBox1.Text, 37, 2) Sheet3.Cells(1, 1) = Sheet2.Cells(1, 1) Sheet3.Cells(1, 2) = Sheet2.Cells(1, 2) For i = 2 To rowCount k = Sheets("Sheet3").UsedRange.Rows.Count a = Sheet2.Cells(i, 1) b = Sheet2.Cells(i, 2) If city = "sh" Then If Left(a, 3) = "sh6" And Left(b, 2) <> "退市" Then Sheet3.Cells(k + 1, 1) = a Sheet3.Cells(k + 1, 2) = b End If Else If Left(a, 3) = "sz3" Or Left(a, 5) = "sz002" Or Left(a, 5) = "sz000" Then Sheet3.Cells(k + 1, 1) = a Sheet3.Cells(k + 1, 2) = b End If End If Next i End Sub
通过在窗体上连续点击【上证分页数据抓取】命令按钮20次后,点击CommandButton5_Click【数据筛选】命令按钮,经过筛选的数据被写入sheet3。如图:
我们还可以继续改进代码,实现一键完成数据抓取全过程。Web API接口技术可以更高效地数据抓取网页数据,对数据量大、自动化程度要求高的项目,应该选用Web API接口技术。
通过WebBrowser控件抓取网页数据不用过分最求过程自动化,面对灵活多变的网页文档,做到兼容性强、代码易修改即可。
参考文章:
下一篇:如何开户买股票同股票入门基础知识

炒股技巧
技术指标
炒股入门
炒股专题
炒股问题
外部文章
网站首页