首先,我是VBA的新手,并且想在Excel中建立天气统计信息。非常感谢您的帮助!
为此,我需要来自多个网站的数据,其中包括温度,气象站和时间的信息。
到目前为止,我已经在互联网上找到了一些VBA信息,并编写了代码,该代码仅在即时窗口中为我提供了一个网站所需的信息。
看起来像这样:
7.4°C | Wien-Mariabrunn (225m) | 14:00
7.6°C | Wien-Hohe Warte (198m) | 14:00
7.6°C | Wien-Unterlaa (200m) | 14:00
7.7°C | Wien-Schwechat (183m) | 14:00
7.8°C | Wien-Donaufeld (160m) | 14:00
8.1°C | Grossenzersdorf (154m) | 14:00
8.2°C | Wien-City (177m) | 14:00
Dim xmlReq As New MSXML2.XMLHTTP60
Dim HTMLDoc As New MSHTML.HTMLDocument
Dim Temps1 As MSHTML.IHTMLElementCollection
Dim temps2 As MSHTML.IHTMLElementCollection
Dim Temp As MSHTML.IHTMLElement
xmlReq.Open "GET", "https://kachelmannwetter.com/at/messwerte/wien/temperatur/20190101-1300z.html", False
xmlReq.send
If xmlReq.Status <> 200 Then
MsgBox "Problem" & vbNewLine & xmlReq.Status & " - " & xmlReq.statusText
Exit Sub
End If
HTMLDoc.body.innerHTML = xmlReq.responseText
Set Temps1 = HTMLDoc.getElementsByClassName("ap o o-1 o-tmp-5")
Set temps2 = HTMLDoc.getElementsByClassName("ap o o-1 o-tmp-1")
For Each Temp In Temps1
Debug.Print Temp.Title
Next Temp
For Each Temp In temps2
Debug.Print Temp.Title
Next Temp
我遇到的第一个问题是我不知道如何将这些信息放入表格或单元格中。
第二个问题是,从开始日期到结束日期,我需要来自多个网站的相同数据。
我在此示例代码中使用的网站是https://kachelmannwetter.com/at/messwerte/wien/temperatur/20190101-1300z.html
。最后,您可以找到日期,在此示例中为“ 20190101”,时间为“ 1300”。
所以为此,我需要某种循环。
因此,最后我需要一个工作表,其中的A列带有日期,B列带有时间,C列带有数据(每个日期和时间)。
我希望这是可以理解的,我非常感谢您的帮助。
答案 0 :(得分:0)
以下内容适用于短日期范围。较长的日期范围会导致响应变慢。网站很可能被阻止/限制。为此:
pauseIndex
,这意味着每增加x个URL(= pauseIndex),在添加下一个请求之前将延迟y秒(由waitSeconds
指定)。你可以玩这个。MSXML2.ServerXMLHTTP
。使用上述修补程序获得最佳设置和批处理请求大小(如果进行批处理)。
指定开始日期时间和结束日期时间:
日期范围在名为Date ranges
的工作表中指定。它具有以下设置:
构建数据集:
我建议您建立一个平面数据集,在其中指定要返回其信息的确切桩号。并非每个电台在每个时间日期都出现。
stations = Array("Wien-Schwechat", "Wien-Unterlaa", "Wien-Mariabrunn", "Wien-Hohe Warte", "Grossenzersdorf", _
"Wien-Donaufeld", "Wien-City")
您可以展开它。我包括一个词典变量newStations
,该变量存储遇到的所有不在您的监视列表中的电台。您可以轻松地将其写出,以帮助确定要监视/包括在数据集中的其他电台。
缺少测站读数的占位符值用于确保完整的数据集。
您可能希望归一化“异常值”-例如,实际的小时值可以在范围内,而不是在小时上。在下面的演示中,对于一个工作站,准确地获取了16:20以下的内容。您可以将其标准化为16:00。
辅助功能/子:
代码中使用了许多辅助功能和1个子功能。
GetAllLinks
。生成开始日期时间和结束日期时间之间的所有请求URL。请参阅代码中的注释。这些可以循环发出每个数据请求EmptyDict
-确保在请求之间清除站点数据UpdateDictForNoReading
。处理在指定的日期时间未报告受监视的电台的情况。它使用"No reading"
WriteOutResults
。产生"flat"
(即非嵌套的2D数组结构)并将结果写入指定的输出工作表检索电台和电台数据:
我使用css attribute = value选择器和contains
运算符来定位电台数据。
使用示例电台的HTML
<a class="ap o o-1 o-tmp--1" data-target="#obs-detail-3h" data-toggle="modal" data-left="635" data-top="545" onclick="obs_detail_3h('-1.0°C', 'Wien-Schwechat (183m)', '16:20','110360', '201901031500');" title="-1.0°C | Wien-Schwechat (183m) | 16:20" style="left: 408.533px; top: 337.757px;">-1</a>
如果我们查看class属性,我们将看到如下所示:
class="ap o o-1 o-tmp--1"
class属性的值为"ap o o-1 o-tmp--1"
,实际上是一系列用空格分隔的类。每个站类值具有相同的子字符串o-tmp
。您可以对此稍作更改。我使用querySelectorAll返回所有在class属性值中具有此子字符串的元素的nodeList。
Set mapStations = html.querySelectorAll("[class*='o-tmp']")
这与页面(地图)上的所有站点相匹配。
nodeList(title
)中每个节点的mapStations
属性包含感兴趣的数据:
title="-1.0°C | Wien-Schwechat (183m) | 16:20"
该字符串包含竖线(|
)分隔符。我可以使用split()
来生成包含每个信息位的数组:
arr = Split(mapStations.item(i).Title, " | ")
这将生成一个数组,该数组将在不同的索引处具有-1.0°C
,Wien-Schwechat (183m)
和16:20
。在此示例中,我将-1.0°C
存储在变量temp
中,将Wien-Schwechat (183m)
存储在变量stationFull
中,而将站名Wien-Schwechat
存储在station
中,{{ 1}}在16:20
中。
待办事项:
要求:
time
的工作表Date ranges
的工作表 Output
中的数据应按照上图所示进行布局。
VBA:
Date ranges
示例输出: