需要用户交互的Web Scraping

时间:2016-03-19 18:01:37

标签: json vba web-scraping vbscript xmlhttprequest

我正在尝试抓取要求您向下滚动的网站https://ibotta.com/rebates,当它到达底部时,会加载更多项目。它是一个有限数量的项目,所以我知道它不会永远滚动,但有没有任何方法这样做而无需与浏览器对象进行交互。

我正在尝试在VB / VBA中完成此任务,但任何语言都可以。现在我在MS Access中模仿它只是为了感受网站的反应,我可以用加载的浏览器控件来做,但它很笨重。最好是我可以直接拨打HTTP。

另一方面,他们是否应该关注他们的任何好的网络抓取教程?

1 个答案:

答案 0 :(得分:1)

乍一看我在Chrome中检查过的XHRs - 开发者工具 - 网络选项卡显示所有必要的数据位于2个文件中:retailers.json(15.7 kB)和offers.json(299 kB)。当您向下滚动页面时,实际上没有其他数据被下载,因此我得出结论,页面上的脚本只是从已经下载的文件中获取数据并将项目放到页面中。我检查了XHR的参数和标题,并创建了下面简单的VBS,它下载文件:

strZipCode = "11590" ' your zip code here
strPathRetailers = "C:\retailers.json" ' retailers output file path
strPathOffers = "C:\offers.json" ' offers output file path

' make XHR to retrieve initial page with X-App-Token and X-NewRelic-ID
strURL = "https://ibotta.com/rebates"
XmlHttpRequest "GET", strURL, "", "", "", strResp

' extract X-App-Token eg 'loader_config={xpid:"VQAHUlVUGwcJUlBWBQg="}'
arrTmp = Split(strResp, "loader_config={xpid:""", 2)
strTmp = arrTmp(1)
arrTmp = Split(strTmp, """}", 2)
strNewRelicID = arrTmp(0)

' extract X-NewRelic-ID eg '<meta name="ibotta-t" content="nce0dc967myuho7wco:1458857196:91bf12dcd5442cf6b2100c962c656a510738150a">'
arrTmp = Split(strResp, "<meta name=""ibotta-t"" content=""", 2)
strTmp = arrTmp(1)
arrTmp = Split(strTmp, """>", 2)
strAppToken = arrTmp(0)

' put headers to array
arrHeaders = Array( _
    Array("Accept", "application/json, text/javascript"), _
    Array("Accept-Encoding", "deflate"), _
    Array("Accept-Language", "en-US,en;q=0.5"), _
    Array("Connection", "keep-alive"), _
    Array("Host", "ibotta.com"), _
    Array("If-Modified-Since", "Thu, 1 Jan 1970 10:00:00 GMT"), _
    Array("Referer", "https", "//ibotta.com/rebates"), _
    Array("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:38.0) Gecko/20100101 Firefox/38.0"), _
    Array("X-App-Token", strAppToken), _
    Array("X-App-Version", "3.6:webapp"), _
    Array("X-NewRelic-ID", strNewRelicID), _
    Array("X-Requested-With", "XMLHttpRequest") _
)

' make XHR to retrieve retailers
strURL = "https://ibotta.com/web_v1/retailers.json?zip=" & strZipCode
XmlHttpRequest "GET", strURL, arrHeaders, "", "", strResp
' save retailers to file
WriteTextFile strResp, strPathRetailers, -1

' make XHR to retrieve offers
strURL = "https://ibotta.com/web_v1/offers.json"
XmlHttpRequest "GET", strURL, arrHeaders, "", "", strResp
' save offers to file
WriteTextFile strResp, strPathOffers, -1

Sub XmlHttpRequest(strMethod, strURL, arrSetHeaders, strFormData, strRespHeaders, strRespText)
    Dim arrHeader
    With CreateObject("Msxml2.ServerXMLHTTP")
        .SetOption 2, 13056 ' SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS
        .Open strMethod, strURL, False
        If IsArray(arrSetHeaders) Then
            For Each arrHeader In arrSetHeaders
                .SetRequestHeader arrHeader(0), arrHeader(1)
            Next
        End If
        .Send strFormData
        strRespHeaders = .GetAllResponseHeaders
        strRespText = .ResponseText
    End With
End Sub

Sub WriteTextFile(strContent, strPath, lngFormat)
    ' lngFormat -2 - System default, -1 - Unicode, 0 - ASCII
    With CreateObject("Scripting.FileSystemObject").OpenTextFile(strPath, 2, True, lngFormat)
        .Write (strContent)
        .Close
    End With
End Sub

您可以将此代码保存到vith .vbs扩展名的文本文件中并运行。

目前我可以看到共有857个优惠,220个零售商的邮政编码为11590(使用JSON查看器,如内置Chrome,或通过web service)。如果您只想处理邮政编码11590的优惠,那么您必须获取零售商列表id,并过滤掉列表中属于零售商的优惠。

有零售商截图,每个都有id(红色标注):

retailers

还有提供截图,每个截图都属于retailer_ids中的几个零售商(也用红色概述):

offers

进一步处理取决于您的需求。您可以将JSON字符串解析为对象并进行交互,或将JSON字符串转换为Recordset以对其进行过滤。