(不定期更新)使用VBA解決 excel web 查詢無法匯入、匯入太慢的股市資料

strainny wrote:
另原文問的現在還想不通,譬如"丁",他對應的網址是https://www.cns11643.gov.tw/wordView.jsp?ID=82979此網址中的ID=82979和丁的關聯是?


建議,發問用=>我要回覆
跟問題無關=>我要留言 or 我要回覆

新文章還好,就算沒有勾選=>同時將回覆內容發給……
因為文章排序會改變,通常也不會漏看

主要是我不會沒事就回頭去看幾個月、幾年前的文章
所以有些人在舊文章(我要留言=>01系統不會提示)發問
有時過了好幾個月才看到,過太久也懶的回答了


關於這個問題,那個id是網站給的(如下圖),我也不知道計算規則是什麼
因為看起來有一定的順序,且不重複,推測是類似資料庫的索引值那種東西



請問樓主 網頁有改版嗎

目前報錯超出陣列
rachel0501
因同樣問題找到此樓,感恩樓主。
david61810
好的 十分感謝
請問大大:
該如何1次抓取多代號同頁次的資料呢?

例:
https://concords.moneydj.com/z/zc/zca/zca_1101.djhtm

基本資料:
同業平均本益比,營收比重,最高本益比,最低本益比

1頁基本上都沒有問題,但如是台股全部2048頁該如何抓呢?

目前小弟是用google抓,但因google限制1次只能抓50筆,只能分批次慢慢抓
=INDEX(IMPORTHTML(CONCATENATE("http://concords.moneydj.com/z/zc/zca/zca_",B652,".djhtm"),"table",3),21,2)

網址如下
https://docs.google.com/spreadsheets/d/1L3PH9LP2FltwEXMwlrYS2tMPnQzC3Jr-e7ujzT-B9xs/edit?usp=sharing

請問大大有更快的抓法嗎?
Clark741224 wrote:
1頁基本上都沒有問題,但如是台股全部2048頁該如何抓呢?


抓是很簡單,21樓簡易範例就行,問題是會不會被網站ban ip

(點我看大圖)


excel 資料格式如上圖,需=>excel、工作表1、模組,執行get_all()
排版、i 值、b欄資料,請自行微調修改

Sub get_all()

Dim i As Integer, UrL As String

For i = 3 To 10 'i=3~n
UrL = "https://concords.moneydj.com/z/zc/zca/zca_" & Sheets("工作表1").Cells(i, 2) & ".djhtm"
Call Get_moneydj(UrL, i)

'延遲用,時間愈長,被網站ban的可能性愈低,不用也行,建議加上
'2秒
Application.Wait (Now + TimeValue("0:00:02"))

Next i


End Sub


Sub Get_moneydj(UrL As String, i As Integer)

Dim HTML As Object, GetXml As Object, j As Integer

Set HTML = CreateObject("htmlfile")
Set GetXml = CreateObject("msxml2.xmlhttp")

On Error Resume Next

Sheets("工作表1").Range("c" & i & ":ac" & i).Clear
Sheets("工作表1").Cells(i, 5) = "最高本益比"
Sheets("工作表1").Cells(i, 14) = "最低本益比"

With GetXml
.Open "GET", UrL, False
.setRequestHeader "Cache-Control", "no-cache"
.setRequestHeader "Pragma", "no-cache"
.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
.send

HTML.body.innerhtml = .responsetext

Set Table = HTML.all.tags("table")(2).Rows

Sheets("工作表1").Cells(i, 3) = Table(4).Cells(1).innertext
Sheets("工作表1").Cells(i, 4) = Table(20).Cells(1).innertext

Set Table = HTML.all.tags("table")(3).Rows


For j = 1 To 8
Sheets("工作表1").Cells(i, j + 5) = Table(3).Cells(j).innertext
Sheets("工作表1").Cells(i, j + 14) = Table(4).Cells(j).innertext
Next j


End With

Set HTML = Nothing
Set GetXml = Nothing

End Sub

Clark741224
感謝大大的教學
snare大大,不好意思,想請教您一下,IE即將在6/15停止使用,但我有一些VBA程式碼都是指向IE網頁,該怎麼修改成CHROME呢?主要是想將網頁裡面的內容貼在excel裡面,所以原本IE是設定Visible,但不知如何修改成CHROME,因此向您請教,感謝您

Sub IE_openweb()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.application")
With IE
    .Visible = False
    .navigate "https://www.XXXXXX.html"
    Do While .Busy Or .readyState <> 4: DoEvents: Loop
.execwb 17,2
.execwb 12,2
End Sub



smart3135 wrote:
原本IE是設定Visible,但不知如何修改成CHROME


"純vba"非常麻煩,因為vba沒有chrome object這種東西
要呼叫很多api,FindWindowExA、GetWindowTextA…還有一大堆
不是短短幾行就能處理

建議另外安裝軟體,例如 python 或 SeleniumBasic
缺點是不能一個檔案帶到跑,每台電腦都要裝
如果該網頁沒有保護,建議可改用xmlhttp,也就是本樓所有範例的主要下載方法



簡單介紹一下SeleniumBasic chrome vba 下載方式

windows 前置作業

一、
下載SeleniumBasic v2.0.9.0,安裝
https://github.com/florentbr/SeleniumBasic/releases/tag/v2.0.9.0

二、
檢查自己電腦內的chrome版本,主要版本號就行
例如101.XXXXX,102.XXXXX,101、102就是

三、
下載跟自己電腦chrome版本號相同的chromedriver,如果chrome改版需重新下載
不同電腦也要重新確認版本後再下載
https://sites.google.com/chromium.org/driver/downloads
(下載chromedriver_win32.zip,測試後,chrome x64也可正常使用)

四、
到SeleniumBasic的安裝目錄,例如C:\Program Files\SeleniumBasic
把步驟三zip檔內的chromedriver.exe,覆蓋安裝目錄內的舊版chromedriver.exe

五、
檢查一下電腦內是否有.net 3.5 或以上,沒有請安裝

六、
進excel vba,設定引用項目,把Selenium Type Library =>打勾


以下2種簡易複製、貼上範例,請參考












Sub test_Ctrla_Ctrlc()

Dim chrome As New Selenium.ChromeDriver, keys As New keys, UrL As String

UrL = "https://www.mobile01.com/topiclist.php?f=511"

With chrome
.Get UrL

'.Window.Maximize
.Wait 5000


.Keyboard.KeyDown (keys.Control)
.SendKeys "a"
.Keyboard.KeyUp (keys.Control)
'.Wait 1000

.Keyboard.KeyDown (keys.Control)
.SendKeys "c"
.Keyboard.KeyUp (keys.Control)
'.Wait 3000

End With


With Sheets("工作表1")
.Select
Call SheetClear("工作表1")
.Cells(1, 1).Select
.PasteSpecial NoHTMLFormatting:=False ' true
.Columns.AutoFit
.Cells(1, 1).Select
End With

chrome.Quit
Set chrome = Nothing

End Sub

Sub test_Clipboard()

Dim chrome As New Selenium.ChromeDriver, Clipboard As Object, UrL As String
Set Clipboard = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")


UrL = "https://www.mobile01.com/topiclist.php?f=511"

With chrome
.Get UrL

'.Window.Maximize
.Wait 5000

'Dim s As String
's = .FindElementByTag("body").Text
'Debug.Print s

Clipboard.SetText .FindElementByTag("body").Text
Clipboard.PutInClipboard

End With


With Sheets("工作表1")
.Select
Call SheetClear("工作表1")
.Cells(1, 1).Select
.PasteSpecial NoHTMLFormatting:=True
.Columns.AutoFit
.Cells(1, 1).Select
End With

chrome.Quit
Set chrome = Nothing

End Sub



Sub SheetClear(sheetName As String)

Dim all_shape As shape
Sheets(sheetName).Cells.Clear
Debug.Print sheetName, Sheets(sheetName).Shapes.Count

For Each all_shape In Sheets(sheetName).Shapes
all_shape.Delete
Next

End Sub



snare wrote:
"純vba"非常麻煩...(恕刪)

感謝snare大這麼仔細的回覆,由於這個VBA是我在公司自己寫的,用在重覆的日常工作上,可以省去不少時間,但公司目前的資安非常嚴格,連外網都沒辦法連,更不用說讓我去安裝一些從網上抓的軟體,所以我可能要再想想別的辦法了,微軟好像是準備用EDGE取代IE,不知道有沒有辦法在不安裝軟體的情況下,把VBA的程式碼改成開啟EDGE呢?
smart3135 wrote:
但公司目前的資安非常嚴格,連外網都沒辦法連,更不用說讓我去安裝一些從網上抓的軟體


smart3135 wrote:
把VBA的程式碼改成開啟EDGE呢


目前不行,微軟沒有做 edge object,未來不知
不過SeleniumBasic,也有支援edge

如果連程式都不能裝,您也不想改用xmlhttp
那還有WScript.Shell+sendkey、滑鼠點擊這個方法,但非常容易誤動作
程式執行時,滑鼠、鍵盤都不能動
網頁如果有popup視窗,有時還要增加程式碼重新定位、active

通常內部網頁不會有太特別的設計,可以的話試著改用xmlhttp
說不定用21樓簡易方式就能處理
但是因為您無法公開資料,所以無法給您正確的建議


以下只有sendkey,滑鼠功能請參考(909樓範例)
#If Win64 Then
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If



Sub test()

Dim Target As String, Wsh As Object, Run_App As Object, UrL As String, title As String

Set Wsh = CreateObject("WScript.Shell")

UrL = "https://www.mobile01.com/topicdetail.php?f=511&t=4737630&p=123"
title = "(不定期更新)使用VBA解決 excel web 查詢無法匯入、匯入太慢的股市資料 (第123頁) - Mobile01 - Google Chrome"

Target = "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe " & UrL


'這裡要特別注意,視窗標題,是工作管理員裡面看到的那個





'但也有例外,特殊符號、unicode、不可見字元…像edge的標題就不一樣




'title = "(不定期更新)使用VBA解決 excel web 查詢無法匯入、匯入太慢的股市資料 (第123頁) - Mobile01 - 設定檔 1 - Microsoft? Edge"
'Target = "C:\Program Files (x86)\Microsoft\Edge\Application\102.0.1245.33\msedge.exe " & UrL


Set Run_App = Wsh.exec(Target)
Sleep 5000

AppActivate title
Sleep 1000

SendKeys "^a", True

Sleep 3000

SendKeys "^c", True

Sleep 3000


With Sheets("工作表1")
.Select
.Cells.Clear
.Cells(1, 1).Select
Sleep 6000
.PasteSpecial NoHTMLFormatting:=True 'false
.Columns.AutoFit
.Cells(1, 1).Select
End With

If Run_App.Status = 0 Then Run_App.Terminate
Set Run_App = Nothing
Set Wsh = Nothing

End Sub





補一個自動找完整標題的副程式,不過用途不太
基本上只要瀏覽器不變,標題是定值,一次性的東西
想要合併到上面的程式也行

#If Win64 Then
Declare PtrSafe Function GetWindow Lib "user32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
#Else
Declare Function GetWindow Lib "user32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
#End If


Sub findtitle()

Dim AppTitle As String

AppTitle = find_windows_full_title("不定期") '輸入部份特定關鍵字即可
Debug.Print AppTitle, Len(AppTitle)
'Cells(1, 1) = AppTitle

End Sub

Function find_windows_full_title(s As String) As String
Dim apphWnd As Long, AppTitle As String
apphWnd = FindWindow(vbNullString, vbNullString)
While apphWnd
AppTitle = Space(255)
AppTitle = Left(AppTitle, GetWindowText(apphWnd, AppTitle, Len(AppTitle)))

If AppTitle Like "*" & s & "*" Then
find_windows_full_title = AppTitle
Exit Function
End If
apphWnd = GetWindow(apphWnd, 2)
Wend
End Function


snare wrote:
目前不行,微軟沒有做(恕刪)

snare大,我有用您1228樓的程式碼去跑一次,確實是可以做到開啟網頁並複製內容貼上excel,只是我之前用excel vba開啟IE的時候,必須要設定IE Visible=False,不能讓網頁開啟(但仍能複製網頁內容),如果網頁開起來的話,在執行過程中就會出錯,您的程式碼是可以開啟chrome並執行複製貼上,實際上若在公司執行的時候,不確定會不會出錯,要等上班的時候試了才知道,不知道是不是有辦法讓chrome不要開啟,但一樣能複貼網址內容並貼上呢?另外您1228樓的程式碼,不需要另外安裝其它軟體,像SeleniumBasic這些嗎?再次感謝您。
smart3135 wrote:
另外您1228樓的程式碼,不需要另外安裝其它軟體,像SeleniumBasic這些嗎?


您在沒安裝任何軟體的情況下,成功執行了範例
您認為要不要裝呢

smart3135 wrote:
excel vba開啟IE的時候,必須要設定IE Visible=False,不能讓網頁開啟(但仍能複製網頁內容),如果網頁開起來的話,在執行過程中就會出錯


這邊您搞錯了一件事,網頁是完整打開的,只是看不見視窗
Visible=False,是因為vba有完整支援ie object,所以可以控制可見、不可見
Visible=True,ie可見下,執行會出錯,通常是程式沒寫好,可能是不可見時湊巧避開了bug

smart3135 wrote:
不知道是不是有辦法讓chrome不要開啟,但一樣能複貼網址內容並貼上呢?


不行,最多控制大小,無法像ie一樣隱形
帶隨身碟偷渡SeleniumBasic相關套件去公司裝
或是包個紅包給mis,請mis偷偷開一下權限安裝
不然就想辦法學習xmlhttp

sendkey是不得已的方法,因為太容易出問題了
文章分享
評分
評分
複製連結
請輸入您要前往的頁數(1 ~ 157)

今日熱門文章 網友點擊推薦!