【问题标题】:Web scraping ticketing information using Excel VBA使用 Excel VBA 抓取 Web 票务信息
【发布时间】:2015-12-06 14:37:39
【问题描述】:

我的任务是从旅行预订网站 (http://english.ctrip.com/trains/#ctm_ref=nb_tn_top) 抓取票务信息。

我已经零碎地编写了一些代码来打开目标 URL 并搜索定义的参数。我现在被困在解析信息上。

在 HTML(下面提供)中,我希望解析类类型、数据列车编号和座位左侧类。例如,我想从第一个实例中检索“2nd class seat”、“G102”和“416”。

我无法确定要使用的正确“类”以及可以利用哪些函数来定位特定值。

到目前为止我拥有的最少代码:

    With oIE
    .navigate sURL
    .Visible = True

    Do Until (.readyState = 4 And Not .Busy)
       DoEvents
    Loop

    ' search for particular entry

    Set ElementCol = .document.getElementsByTagName("button")
        For Each btnInput In ElementCol
            If btnInput.innerText = "Search" Then
                btnInput.Click
                Exit For
            End If
        Next btnInput

     ' ensure page has been fully loaded
    Do Until (.readyState = 4 And Not .Busy)
       DoEvents
    Loop

End With

Set ieDoc = oIE.document
Set ElementCol = ieDoc.getElementsByClassName("train-seat")
    For Each optInput In ElementCol
        MsgBox optInput.innerHTML
    Next optInput

源 HTML

            <ul class="train-seat">
                    <li class=" ">
                        <span class="class-type">2nd class seat</span><span class="c-price"><span class="price-currency">CNY</span>&nbsp;<em class="price-num">553</em><span class="seat-left">416 left</span></span><a class="c-btn btn-key" href="javascript:;" 
                           data-trainnumber="G102" 
                           data-departtime="06:43" 
                           data-departdate="1449187200" 
                           data-departstation="Rochester" 
                           data-arrivalstation="Albany" 
                           data-seatname="2nd class">Book</a>
                    </li>
                    <li class=" ">
                        <span class="class-type">1st class seat</span><span class="c-price"><span class="price-currency">CNY</span>&nbsp;<em class="price-num">933</em><span class="seat-left">66 left</span></span><a class="c-btn btn-key" href="javascript:;" 
                           data-trainnumber="G102" 
                           data-departtime="06:43" 
                           data-departdate="1449187200" 
                           data-departstation="Rochester" 
                           data-arrivalstation="Albany" 
                           data-seatname="1st class">Book</a>
                    </li>
                    <li class=" ">
                        <span class="class-type">Business class seat</span><span class="c-price"><span class="price-currency">CNY</span>&nbsp;<em class="price-num">1,748</em><span class="seat-left">19 left</span></span><a class="c-btn btn-key" href="javascript:;" 
                           data-trainnumber="G102" 
                           data-departtime="06:43" 
                           data-departdate="1449187200" 
                           data-departstation="Rochester" 
                           data-arrivalstation="Albany" 
                           data-seatname="Business">Book</a>
                    </li>

【问题讨论】:

  • 您现在使用的代码有什么问题?你想让它做什么不做什么?阅读this 可能会帮助您解决问题。

标签: html excel vba web-scraping


【解决方案1】:

您必须在发现元素时对其进行隔离,然后仅依次处理每个匹配元素中的项目。有很多方法可以做到这一点。对我来说,我发现处理由getElementsByClassName methodgetElementsByTagName method 返回的项目的集合 最好使用With ... End With statements 来处理。这会隔离项目,以便后续对内部项目的调用只会发现父元素内的匹配项。

With oie
    .navigate "http://english.ctrip.com/trains/List/Index?DepartureCity=shanghai%28%E4%B8%8A%E6%B5%B7%29&ArrivalCity=beijing%28%E5%8C%97%E4%BA%AC%29&DepartDate=12-7-2015&TrainNo=&DepartureCityPinyin=&ArrivalCityPinyin=&DepartureStation=%E4%B8%8A%E6%B5%B7&ArrivalStation=%E5%8C%97%E4%BA%AC&searchboxArg="
    .Visible = True

    Do Until (.readyState = 4 And Not .Busy)
       DoEvents
    Loop

    With oie.document
        For ts = 0 To .getelementsbyclassname("train-seat").Length - 1
            'work with each UL of class 'train-seat'
            With .getelementsbyclassname("train-seat")(ts)
                'work with each LI within the UL
                For li = 0 To .getelementsbytagname("li").Length - 1
                    With .getelementsbytagname("li")(li)
                        'only keep working if there is at least one class-type class and one anchor element
                        If CBool(.getelementsbyclassname("class-type").Length) And _
                           CBool(.getelementsbyclassname("price-num").Length) And _
                           CBool(.getelementsbytagname("a").Length) Then
                            'show first 'class-type' class within the LI
                            Debug.Print .getelementsbyclassname("class-type")(0).innertext
                            'show first 'price-num' class within the LI
                            Debug.Print .getelementsbyclassname("price-num")(0).innertext
                            'the other one are trickier; get the first A element
                            With .getelementsbytagname("a")(0)  'c-btn btn-key class
                                'but can be parsed using Split of the outerHTML on the quote character
                                vPIECEs = Split(.outerhtml, Chr(34))
                                Debug.Print vPIECEs(13) '& vPIECEs(14) '& vPIECEs(7)
                            End With
                        End If
                    End With
                Next li
            End With
        Next ts

    End With
End With

Set oie = Nothing

我选择使用Debug.Print 将输出发送到 VBE 的即时窗口 (Ctrl+G),而不是重复显示 MsgBox 弹出窗口。

【讨论】:

  • 吉普车 - 非常感谢您在这方面的帮助。只是为了学习,请问(ts)在下面这行代码中做了什么? .getelementsbyclassname("train-seat")(ts)
  • 这在 cmets 中处理起来似乎太多了。建议您使用更新的代码和相关详细信息开始一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-13
  • 1970-01-01
  • 2018-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-15
相关资源
最近更新 更多