標題:
[發問]
網頁資料很長,如何有效率地知道已完整進來
[打印本頁]
作者:
Scott090
時間:
2017-11-12 16:59
標題:
網頁資料很長,如何有效率地知道已完整進來
本帖最後由 Scott090 於 2017-11-12 17:01 編輯
'捲動網頁
'''' i 值太小,網頁資料會來不及進來;太大會浪費時間
'''' 有何方法可以知道資料已進來齊全而停止;或其他方式取代本方法?
i = 0
While i < 50
.Document.Parentwindow.scrollby 0, 10000 'Move,Scroll IE window down to bottom
i = i + 1
Wend
請問那一位前輩幫忙? 先謝謝
以下的例子是資料的長短多寡取決於日期期間的長短,如何做會比較有效率?
'使用 ie,Application 物件
'從 finance.Yahoo.com取得歷史資料
'
Sub getHistoricalData()
Dim Code
Code = "AAPL"
Const mysteryNum = 2209190400#
Dim ie, DATAar, A$, yyDate
Dim URL As String
Dim StartDate, EndDate, timer, tt As Date
Dim Table As Object, oDoc As Object
Dim i%, j%, k%
StartDate = "1999/1/2" '開始日期
EndDate = Date '結束日期,預設為今天
'轉換為秒鐘數字
StartDate = DateValue(StartDate) * 86400 - mysteryNum
EndDate = DateValue(EndDate) * 86400 - mysteryNum
Set ie = CreateObject("InternetExplorer.Application")
With ie
Application.StatusBar = "打開網頁,等待資料備齊 ....."
URL = "https://finance.yahoo.com/quote/" & Code & "/history?period1=" & StartDate & "&period2=" & EndDate & "&interval=1d&filter=history&frequency=1d"
.Visible = True ' False '顯示 IE否?
.navigate URL
Application.Wait Time + #12:00:04 AM# '等候網頁4秒鐘
tt = Time + #12:00:05 AM#
Do While (.busy Or .readyState <> 4) And Time < tt
DoEvents
Loop
'捲動網頁
'''' i 值太小,網頁資料會來不及進來;太大會浪費時間
'''' 有何方法可以知道資料已進來齊全而停止;或其他方式取代本方法?
i = 0
While i < 50
.Document.Parentwindow.scrollby 0, 10000 'Move,Scroll IE window down to bottom
i = i + 1
Wend
Application.StatusBar = "取網頁資料中 .... "
Set oDoc = .Document.getElementsByTagName("TABLE")(1)
ActiveSheet.Cells.Clear
ReDim DATAar(oDoc.Rows.Length - 1, 7)
For i = 0 To oDoc.Rows.Length - 2
For j = 0 To 6
On Error Resume Next
DATAar(i + 1, j + 1) = oDoc.Rows(i).Cells(j).innertext
If j = 0 And i <> 0 Then
'''' yyDate = CDate("Oct 01, 2017")
A = DATAar(i + 1, j + 1)
A = Mid(A, 2, 3) & " " & Mid(A, 8, 2) & ", " & Right(A, 4)
yyDate = CDate(A)
DATAar(i + 1, j + 1) = yyDate
End If
Next
Next
Application.StatusBar = "資料移到Excel 工作表 ....."
ActiveSheet.Cells(1, 1).Resize(UBound(DATAar), 7).Value = DATAar
Columns("A:A").NumberFormatLocal = "yyyy/mm/dd"
Columns("G:G").NumberFormatLocal = "#,##0_)"
.Quit
End With
Application.StatusBar = "資料下載完成 ....... "
Application.Wait Time + #12:00:02 AM#
Application.StatusBar = False
End Sub
複製代碼
作者:
GBKEE
時間:
2017-11-13 07:18
本帖最後由 GBKEE 於 2017-11-14 15:24 編輯
回復
1#
Scott090
Option Explicit
Dim Sh As Worksheet
Sub Ex_網頁底部()
Dim E As Object, Er As Integer
'Dim Timer As Date 'Timer 為vba的內建函數 ,變數名稱盡量不要相同
Dim xTimer As Date
Application.DisplayStatusBar = True
Application.StatusBar = False
Set Sh = ActiveSheet
Sh.Cells.Clear
On Error GoTo EE
With CreateObject("InternetExplorer.Application")
' .Visible = True
xTimer = Time
.Navigate "https://finance.yahoo.com/quote/AAPL/history?period1=915206400&period2=1505174400&interval=1d&filter=history&frequency=1d"
Do While .Busy Or .readyState <> 4: DoEvents: Application.StatusBar = "****** 等 候 網 頁 下... " & Time: Loop
Do
Application.StatusBar = "****** 資料 下載中..." & Application.Text(Time - xTimer, " [S]秒") & " ******"
.document.Parentwindow.scrollBy 0, 37900
Do While .Busy Or .readyState <> 4: DoEvents: Loop
With .document.documentElement
' Debug.Print .scrollTop , .clientHeighT, .scrollHeight '***計算出 37900為最大值
If .scrollTop + .clientHeighT = .scrollHeight Then Exit Do
End With
DoEvents
Loop
Set E = .document.ALL.TAGS("TABLE")(1)
Ep .document.ALL.TAGS("TABLE")(1).outerHTML
Application.StatusBar = "** [" & xTimer & " - " & Time & Application.Text(Time - xTimer, " ] , 計 [S]秒") & " ,下載 共 " & E.Rows.Length - 2 & " 筆資料 完畢 !! **"
.Quit '關閉網頁
End With
Exit Sub
EE: '程式運行速度大於ie時的措施
Application.StatusBar = "網頁錯誤等候中...."
Er = Er + 1
If Er >= 3 Then Stop
Application.Wait (Second(Now()) + 2)
Resume
End Sub
Private Sub Ep(S As String) ' A(A.Length - 1).outerHTML
With CreateObject("InternetExplorer.Application")
.Navigate "about:Tabs"
' .Visible = True
.document.body.innerHTML = S
.ExecWB 17, 2 ' Select All
.ExecWB 12, 2 ' Copy selection
With Sh
.Activate
' .Cells.Clear
.Range("A1").Select
.PasteSpecial Format:="HTML", Link:=False, DisplayAsIcon:=False, NoHTMLFormatting:=True
.Range("A1").Select
End With
.Quit
End With
End Sub
複製代碼
作者:
Scott090
時間:
2017-11-13 15:57
本帖最後由 Scott090 於 2017-11-13 16:01 編輯
回復
2#
GBKEE
謝謝 GBKEE 大的指導
為觀察網頁行為特性將兩種方法做一比較,執行結果如下表:
設定欲取資料期間;開始 1999/1/2, 結束期間 2017/9/12
[attach]27961[/attach]
其中方法二並未完整的取得資料;
方法一則視 scrollby 的參數而定,設小了取資料不完整,設大了資料可以完整取得但有空轉的時間
謝謝
Sub Ex_網頁底部()
Dim E As Object, R As Long, C As Long, i%
Dim timer As Date
'period1 = 1483286400 '2017/1/2
'period1 = 1451664000 '2016/1/2
'period1 = 915206400 '1999/1/2
'period2 = 1505174400 '2017/9/12
With CreateObject("InternetExplorer.Application")
.Visible = True
.Navigate "https://finance.yahoo.com/quote/AAPL/history?period1=915206400&period2=1505174400&interval=1d&filter=history&frequency=1d"
Do While .Busy Or .readyState <> 4: DoEvents: Loop
Set E = .document.ALL.TAGS("TR")
i = 0
timer = Time
Do
i = i + 1
With .document
'方法一:
' .Parentwindow.scrollBy 0, 500 '改變 y 點數做試驗
' With .DocumentElement
' R = R + .clientheight
' Debug.Print "捲動次數:" & i, "R:" & R, "SH: " & .scrollHeight ', "CH: " & .clientheight
' If R - .clientheight > .scrollHeight Then Exit Do
' End With
'==============================================================
'方法二:
.Parentwindow.scrollBy 0, .DocumentElement.scrollHeight
R = R + .DocumentElement.scrollHeight
Debug.Print "捲動次數:" & i, "R:" & R, "SH: " & .DocumentElement.scrollHeight
If R - .DocumentElement.scrollHeight > .DocumentElement.scrollHeight Then Exit Do
''''==============================================================
End With
DoEvents
Loop
Debug.Print "時程: " & (Time - timer) * 86400
ActiveSheet.Cells.Clear
For R = 1 To E.Length - 1
For C = 0 To E(R).Cells.Length - 1
Cells(R, C + 1) = E(R).Cells(C).INNERTEXT
Next
Next
.Quit '關閉網頁
End With
MsgBox "Ok"
End Sub
複製代碼
作者:
GBKEE
時間:
2017-11-14 15:27
回復
3#
Scott090
參考這裡
http://www.jb51.net/article/57614.htm
2# 的程式碼修改了為
With .document.documentElement
' Debug.Print .scrollTop , .clientHeighT, .scrollHeight '***計算出 37900為最大值
If .scrollTop + .clientHeighT = .scrollHeight Then Exit Do
End With
複製代碼
但測試時,.偶爾還是不能完全下載,有待努力
作者:
Scott090
時間:
2017-11-14 21:41
回復
4#
GBKEE
GBKEE大:
謝謝進一步的解答與教導 及提供的參考的網址
將繼續地瞭解與研究
感恩
作者:
Scott090
時間:
2017-11-16 18:13
回復
4#
GBKEE
從參考的網址內的各個變數,
scrollHeight, scrolltop, offsetheight, clientHeight, body.clientheight .....
沒找出確實的 滾動數字相互之間的穩定關係,造成 激發滾動迴圈的不穩定性 及 取得的資料不一定 是底部最後一筆;
而,欲取得的資料格式是可以既知,所以改用 "是否最後一筆資料" 來決定滾動迴圈
把程式碼修飾如下:
增加 日期 變數 Dim startDate as date, A
startdate = #1999/1/2#
'跳出迴圈條件 If .scrolltop + .clientHeight = .scrollHeight Then exit do 改成
A = E(E.Length - 2).Cells(0).INNERTEXT
If CDate(Mid(A, 2, 3) & " " & Mid(A, 8, 2) & ", " & Right(A, 4)) - startDate < 5 Then Exit Do
測試結果是穩定的
作者:
GBKEE
時間:
2017-11-19 10:53
回復
6#
Scott090
不錯的這樣就可以得到完整資料.
程式執行時間大約需一分鐘,我整理一下在狀態列上加上資訊.
Option Explicit
Dim Sh As Worksheet
Dim xTimer As Date
'Dim Timer As Date 'Timer 為vba的內建函數 ,變數名稱盡量不要相同
Sub Ex_網頁底部()
Dim E As Object, Ie_Date As Date, i As Integer
Application.DisplayStatusBar = True
Application.StatusBar = False
Set Sh = ActiveSheet
Sh.Cells.Clear
On Error GoTo EE
With CreateObject("InternetExplorer.Application")
'.Visible = True
xTimer = Time
.Navigate "https://finance.yahoo.com/quote/AAPL/history?period1=915206400&period2=1505174400&interval=1d&filter=history&frequency=1d"
Do While .Busy Or .readyState <> 4: DoEvents: Application.StatusBar = "****** 等 候 網 頁 下....★★★" & GetTime: Loop
Ie_Date = Getdate(.document.ALL.TAGS("INPUT")(4).Value)
Set E = .document.ALL.TAGS("tr")
Do
Application.StatusBar = "★★★★★ 資料 下載中..." & GetTime & String(Val(GetTime), "★")
.document.Parentwindow.scrollby 0, 37900
' Do While .Busy Or .readyState <> 4: DoEvents: Loop
If Getdate(E(E.Length - 2).Cells(0).innertext) - Ie_Date < 5 Then Exit Do
DoEvents
Loop
Set E = .document.ALL.TAGS("TABLE")(1)
Ep .document.ALL.TAGS("TABLE")(1).outerHTML
Application.StatusBar = "** ★" & xTimer & " - " & Time & "★" & GetTime & " ,下載 共 " & E.Rows.Length - 2 & " 筆資料 完畢 !! **"
.Quit '關閉網頁
End With
With Sh
For i = 2 To .Range("A1").End(xlDown).Row - 1
.Range("A" & i) = Getdate(.Range("A" & i))
Next
.Range("A:A").NumberFormatLocal = "yyyy/mm/dd"
End With
Exit Sub
EE: '程式運行速度大於ie時的措施
Application.StatusBar = "網頁錯誤等候中....★★★ " & GetTime
Application.Wait (Second(Now()) + 2)
Resume
End Sub
Private Sub Ep(S As String)
With CreateObject("InternetExplorer.Application")
.Navigate "about:Tabs"
' .Visible = True
.document.body.innerHTML = S
.ExecWB 17, 2 ' Select All
.ExecWB 12, 2 ' Copy selection
With Sh
.Activate
' .Cells.Clear
.Range("A1").Select
.PasteSpecial Format:="HTML", Link:=False, DisplayAsIcon:=False, NoHTMLFormatting:=True
.Range("A1").Select
End With
.Quit
End With
End Sub
Private Function Getdate(sDate As String) As Date
Dim A As String, b As Integer
A = Split(sDate, "-")(0)
b = AscW(Mid(A, 1, 1))
A = Replace(A, ChrW(b), " ")
A = Replace(A, "?", "")
Getdate = CDate(A)
End Function
Private Function GetTime() As String
GetTime = Application.Text(Time - xTimer, " [S]秒")
End Function
複製代碼
作者:
quickfixer
時間:
2017-11-19 18:40
我在01文書處理區有看到只要1.8秒的程式碼
作者:
Scott090
時間:
2017-11-20 07:27
回復
7#
GBKEE
GBKEE 大大:
謝謝你的總結
作者:
Scott090
時間:
2017-11-20 07:31
回復
8#
quickfixer
我在01文書處理區有看到只要1.8秒的程式碼
請把網址貼出來,讓大家參考
謝謝
作者:
quickfixer
時間:
2017-11-20 10:25
本帖最後由 quickfixer 於 2017-11-20 10:27 編輯
不好意思我還不能貼url沒有權限
去看就知道是那篇文章了
在文書處理區的第一頁
文章内11/16號那個程式
作者:
Scott090
時間:
2017-11-20 21:23
回復
11#
quickfixer
參考網址: https://www.mobile01.com/topicdetail.php?f=511&t=4737630&p=28
這個是直接下載 .csv 檔
謝謝提供的信息
作者:
quickfixer
時間:
2017-11-21 02:24
回復
12#
Scott090
多了一篇不下載csv,只下載網頁的程式碼
比較慢每個股票資料要8.91秒下載
那篇文章每個程式都很快,可是有點難
作者:
Scott090
時間:
2017-11-28 07:40
回復
13#
quickfixer
這個麻辣家族論壇也有使用 xmlhttp 供參考的例子,
搜索一下就有了
作者:
quickfixer
時間:
2018-2-2 00:26
回復
14#
Scott090
我知道有一些範例可搜尋到,可是很分散
那串文章寫了各大網站的下載範例很集中,而且新手也可以下載:lol
另外您在問的,鉅亨網歷史行情下載問題
01那邊75樓的文章可解決
不好意思權限還不夠,只能在這發言
作者:
Scott090
時間:
2018-2-2 08:39
回復
15#
quickfixer
謝謝提供的信息
去年有去瀏覽過
歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)