您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

VBA Web抓取-更改日历的日期

VBA Web抓取-更改日历的日期

请尝试以下方法。实际上,它单击年份和月份的下拉菜单,然后通过itemindex属性值选择适当的项目。

在年份的情况下,取决于当前显示内容,期望的年份可能不在下拉列表中。该代码使用固定次数的<>按钮单击来确定是否可以找到所需的年份。可以在代码顶部将此数字设置为常量,并在需要时在此更改。

要选择日期,将循环收集天数,如果找到了所需的天数,则将其选中。

Javascript用于等待某些元素变为可单击状态,以及用于出现下拉菜单的定时循环。这会根据事件何时可操作来计时,以产生所需的结果。

Option Explicit
Public Sub MakeChanges()
    'VBE > Tools > References > Selenium Type Library
    'Download: https://github.com/florentbr/SeleniumBasic/releases/tag/v2.0.9.0
    Const url = "https://www.dukascopy.com/swiss/english/marketwatch/historical/"
    Const MAX_WAIT_SEC As Long = 10
    Const JS_WAIT_CLICKABLE = _
    "var target = this, endtime = Date.Now() + arguments[0];" & _
    "(function check_clickable() {" & _
    "  var r = target.getBoundingClientRect(), x = r.left+r.width/2, y = r.top+r.height/2;" & _
    "  for (var e = document.elementFromPoint(x , y); e; e = e.parentElement)" & _
    "    if (e === target){ callback(target); return; }" & _
    "  if (Date.Now() > endtime) { callback(target); return; }" & _
    "  setTimeout(check_clickable, 60);" & _
    "})();"                                      'by @florentbr



    Dim d As WebDriver, t As Date
    Dim myYear As String, myMonth As String, myDay As String

    Set d = New ChromeDriver
    myYear = "2017"
    myMonth = "January"
    myDay = "1"

    With d
        .start "Chrome"
        .get url
        .SwitchToFrame .FindElementByCss("script + iframe") '<==switch to frame

        'You should add tests for acceptable values e.g. January-December for MonthName, day as appropriate for month
        Dim monthIndex As Long, yearIndex As Long, item As Object, dropDown As Object

        monthIndex = Month(DateValue("01 " & myMonth & " 2019")) - 1  '<== get month number from name and -1 to get value to use in attribute selector
        t = Timer
        Do                                       '<== timed loop for month dropdown to be present
            On Error Resume Next
            Set dropDown = .FindElementByCss(".d-wh-vg-xh span span")
            On Error GoTo 0
            If Timer - t > MAX_WAIT_SEC Then Exit Do
        Loop While dropDown Is Nothing

        If dropDown Is Nothing Then Exit Sub

        With dropDown                            '<== wait for drop down to be clickable
            .ExecuteAsyncScript(JS_WAIT_CLICKABLE, 3000) _
            .Click
        End With

        With .FindElementByCss(".d-Ch-fi-mi")
            .ExecuteAsyncScript(JS_WAIT_CLICKABLE, 3000) _
            .Click   '<== display month dropdown
        End With
        .FindElementByCss(".d-Ch-fi-u [itemindex='" & monthIndex & "']").Click '<select month by index

        Dim yearIndices As Object, i As Long, j As Long, currentYear As String, z As Long, dayFound As Boolean

        currentYear = .FindElementByCss(".d-Ch-fi-ni").Text '<= find currently displayed year

        Set yearIndices = CreateObject("Scripting.Dictionary")

        For i = CLng(currentYear) - 5 To CLng(currentYear) + 5 '<== gather range of year options in dropdown into
            'dictionary where key is year and value is the value required to select in attribute selector
            yearIndices(CStr(i)) = CStr(j)
            j = j + 1
        Next

        If yearIndices.Exists(myYear) Then '<check dictionary to see if year desired present
            yearIndex = yearIndices(myYear)
            .FindElementByCss(".d-Ch-fi-ni").Click  '<== display year dropdown
            .FindElementByCss("div:nth-child(11) [itemindex='" & yearIndex & "']").Click  '<==select year
        Else '<== year not present so loop clicking either year add or year subtract to see if desired year does become present
            Dim adjustButton As Object
            Set adjustButton = IIf(CLng(currentYear) > CLng(myYear),.FindElementByCss("d-Ch-fi-prevIoUsYear"), .FindElementByCss("d-Ch-fi-nextYear")) 
            Do
                adjustButton.Click
                If z > 15 Then Exit Sub
                z = z + 1
           Loop Until .FindElementByCss(".d-Ch-fi-ni").Text = myYear

        End If

        Dim daysList As Object
        Set daysList = .FindElementsByCss("div:nth-child(11) td") '<==gather all the days

        For Each item In daysList                '<==loop days in month until required one found
            If item.Text = myDay Then
                item.Click
                Exit For
            End If
        Next
        Stop
        .Quit
    End With
End Sub
其他 2022/1/1 18:18:45 有611人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶