Невозможно получить данные в табличном формате - PullRequest
0 голосов
/ 09 июня 2018

Я написал скрипт в vba, используя IE для получения данных с веб-страницы.Данные не хранятся ни в одной таблице, я имел в виду, что нет тега table, tr или td.Тем не менее, они выглядят как в табличном формате.Вы можете увидеть изображение ниже для ясности.

То, что я пробовал до сих пор, может получить данные в одну строку, например:

$4,085  
$1,620
$1,435  
$35
$1,125  
$905

То, как я хочу их получить, выглядит следующим образом:

$4,085  $1,620
$1,435  $35
$1,125  $905

В других языках есть опция для list comprehension, с помощью которой я могу обработать ее в одной строке кода, но в случае vba я застреваю.

html elementsв пределах которого находятся данные (это просто часть целого):

<ul id="tco_detail_data">
    <li>
        <ul class="list-title">
            <li class="first">&nbsp;</li>
            <li>Year 1</li>
            <li>Year 2</li>
            <li>Year 3</li>
            <li>Year 4</li>
            <li>Year 5</li>
            <li class="last">5 Yr Total</li>
        </ul>
    </li>
    <hr class="loose-dotted">


    <li class="first">
        <ul class="first">
            <li class="first">Depreciation</li>
                        <li>$4,085</li>
                        <li>$1,620</li>
                        <li>$1,425</li>
                        <li>$1,263</li>
                        <li>$1,133</li>
                    <li class="last">$9,526</li>
        </ul>
    </li>
</ul>

Данные выглядят так, как на этой странице:

enter image description here

Это то, что я пытался сделать до сих пор:

Sub Get_Information()
    Dim IE As New InternetExplorer, HTML As HTMLDocument
    Dim post As Object

    With IE
        .Visible = False
        .Navigate "https://www.edmunds.com/ford/escape/2017/cost-to-own/?zip=43215"
        While .Busy = True Or .ReadyState < 4: DoEvents: Wend
        Set HTML = .Document
    End With

    Application.Wait Now + TimeValue("00:00:05") 'waiting for the items to be available

    For Each post In HTML.getElementById("tco_detail_data").getElementsByTagName("li")
        Debug.Print post.innerText
    Next post
    IE.Quit
End Sub

Ссылка для добавления в библиотеку для выполнения вышеуказанного сценария:

Microsoft Internet Controls
Microsoft HTML Object Library

Ответы [ 2 ]

0 голосов
/ 09 июня 2018

Помимо того, что QHarr уже показал, есть и другой способ достижения той же цели:

Sub Get_Information()
    Dim IE As New InternetExplorer, HTML As HTMLDocument
    Dim posts As Object, post As Object, oitem As Object
    Dim R&, C&, B As Boolean

    With IE
        .Visible = False
        .Navigate "https://www.edmunds.com/ford/escape/2017/cost-to-own/?zip=43215"
        Do While .Busy = True Or .ReadyState <> 4: DoEvents: Loop
        Set HTML = .Document
    End With

    ''no hardcoded delay is required. The following line should take care of that

    Do: Set oitem = HTML.getElementById("tco_detail_data"): DoEvents: Loop While oitem Is Nothing

    For Each posts In oitem.getElementsByTagName("li")
        C = 1: B = False

        For Each post In posts.getElementsByTagName("li")
            Cells(R + 1, C).Value = post.innerText
            C = C + 1: B = True
        Next post

        If B Then R = R + 1
    Next posts
    IE.Quit
End Sub
0 голосов
/ 09 июня 2018

Это работает с помощью селектора CSS.Обновлен, чтобы удалить явное ожидание.

Селектор:

#tco_detail_data > li

Что является li в пределах идентификатора tco_detail_data

, который выглядит как следующие примеры результатовс веб-страницы с помощью CSS-запроса

CSS query


Код:

Option Explicit
Public Sub Get_Information()
    Dim IE As New InternetExplorer

    With IE
        .Visible = False
        .navigate "https://www.edmunds.com/ford/escape/2017/cost-to-own/?zip=43215"
        While .Busy = True Or .readyState < 4: DoEvents: Wend
    End With
    Dim a As Object, exitTime As Date
    exitTime = Now + TimeSerial(0, 0, 5)

    Do
        DoEvents
        On Error Resume Next
        Set a = IE.document.querySelectorAll("#tco_detail_data")
        On Error GoTo 0
        If Now > exitTime Then Exit Do
    Loop While a Is Nothing

    If a Is Nothing Then Exit Sub

    Dim resultsNodeList As Object, i As Long, arr() As String
    Set resultsNodeList = HTML.querySelectorAll("#tco_detail_data > li")

    With ActiveSheet
        For i = 0 To 9
            arr = Split(resultsNodeList(i).innerText, Chr$(10))
            .Cells(i + 1, 1).Resize(1, UBound(arr) + 1).Value = arr
        Next
    End With

    IE.Quit
End Sub

Результат в листе

Result


Дополнительная информация:

Часть массиваэто потому, что resultsNodeList (i) .innerText возвращается как «сложенная строка» - то есть с разрывами строк между ними;Смотрите изображение ниже.Я разделил их, чтобы создать массив, который затем выписал на лист.Массив основан на 0, поэтому я должен добавить 1, чтобы иметь возможность правильно заполнить диапазон.

unsplit strings

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...