2

I have a problem with making POST httprequest in VBA. I have fiddler log with some parameters and JSON stuff. Parameters are two, JSON (is that parameter too?) is one. It looks like that:

enter image description here

And here is my question - how to send these parameters all together? Would be ideally in VBA, but even general answer would be great.

I want to say I am kinda new in that stuff.

Greetings, Luke.

Lucas
  • 329
  • 1
  • 13
  • See this: https://stackoverflow.com/questions/44086334/curl-equivalent-to-post-json-data-using-vba – SlowLearner Aug 25 '17 at 11:49
  • Unfortunately, it is not related to my problem, but thanks a lot for effort. – Lucas Aug 25 '17 at 11:57
  • 1
    No worries, generally you'll get more help if you share what you already have, perhaps use the above code (an the code from the links within) as a basis for writing something that might work and come back with some more specific questions ;-) – SlowLearner Aug 25 '17 at 12:02
  • 1
    Also keep in mind that not everyone can see images hosted on imgur – braX Aug 25 '17 at 12:03
  • @braX, thanks for that advice, I had no idea about that. @ SlowLearner I tried many code configuration, but nothing worked. After a lot of trying, I defined my problem as - how to combine these two things - parameters ('Raw' tab at my image) and JSON ('JSON' tab at my image) together and send them. When I send only parameters, what I got back is search filled with number "20-610", but under this search field there is "SEARCH" button. I think, the JSON 'thing' is responsible for pressing it. But I have no idea how to do that. Sending JSON alone does nothin. – Lucas Aug 25 '17 at 12:08
  • 1
    Fiddler just tries to evaluate the XHR parameters string `kod=20-610&page=kod` as JSON expression, and shows parsed up to first invalid character, which is `=`, so parsed part is `kod`, more of that pay attention to warning at the bottom `Illegal/Unquoted identifier 'kod' at position 0`. Just ignore JSON tab, in that case it's not relevant, since request parameters are webform data, but not JSON. Please share the code you are using to make that XHR. What is actual and expected response? – omegastripes Aug 26 '17 at 05:07
  • @omegastripes, I am using Chilkat library, so you might not be familliar with that. Actual response is the same site from which I do request "http://kody.poczta-polska.pl/", only with filled search box with "20-610". Expected response is like you have postted in answet below. – Lucas Aug 26 '17 at 11:48

1 Answers1

1

Try to provide proper Cookies and Content-Type headers within a request, take a look at the below example, it uses MSXML2.ServerXMLHTTP to manage with cookies:

Option Explicit

Sub scrape_kody_poczta_polska_pl()

    Dim sRespHeaders As String
    Dim aSetHeaders
    Dim sPayload  As String
    Dim sRespText  As String
    Dim aRows
    Dim aCells
    Dim i As Long
    Dim j As Long
    Dim aData

    ' Get search page to retrieve cookies
    XmlHttpRequest _
        "GET", _
        "http://kody.poczta-polska.pl/", _
        Array(), _
        "", _
        sRespHeaders, _
        ""
    ' Extract cookies
    ParseResponse "^Set-(Cookie): (\S*?=\S*?);[\s\S]*?$", sRespHeaders, aSetHeaders
    ' Setup request
    sPayload = "kod=20-610&page=kod"
    PushItem aSetHeaders, Array("Content-Type", "application/x-www-form-urlencoded")
    ' Retrieve results
    XmlHttpRequest _
        "POST", _
        "http://kody.poczta-polska.pl/index.php", _
        aSetHeaders, _
        sPayload, _
        "", _
        sRespText
    ' Parse table rows
    ParseResponse _
        "(<tr>(?:[\s\S]*?<t[dh]>[\s\S]*?</t[dh]>)+?[\s\S]*?</tr>)", _
        sRespText, _
        aRows
    ' Parse table cells
    For i = 0 To UBound(aRows)
        ParseResponse _
            "<t[dh]>([\s\S]*?)</t[dh]>", _
            aRows(i), _
            aCells, _
            False
        For j = 0 To UBound(aCells)
            aCells(j) = DecodeHTMLEntities((aCells(j)))
        Next
        aRows(i) = aCells
    Next
    ' Output
    With ThisWorkbook.Sheets(1)
        .Cells.Delete
        .Cells.HorizontalAlignment = xlCenter
        .Cells.VerticalAlignment = xlTop
        aData = Denestify(aRows)
        If IsArray(aData) Then Output2DArray .Cells(1, 1), aData
    End With

End Sub

Sub XmlHttpRequest(sMethod, sUrl, aSetHeaders, sPayload, sRespHeaders, sRespText)

    Dim aHeader

    With CreateObject("MSXML2.ServerXMLHTTP")
        .SetOption 2, 13056 ' SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS
        .Open sMethod, sUrl, False
        For Each aHeader In aSetHeaders
            .SetRequestHeader aHeader(0), aHeader(1)
        Next
        .Send sPayload
        sRespHeaders = .GetAllResponseHeaders
        sRespText = .ResponseText
    End With

End Sub

Sub ParseResponse(sPattern, sResponse, aData, Optional bAppend As Boolean = True)

    Dim oMatch
    Dim aTmp()
    Dim sSubMatch

    If Not (IsArray(aData) And bAppend) Then aData = Array()
    With CreateObject("VBScript.RegExp")
        .Global = True
        .MultiLine = True
        .Pattern = sPattern
        For Each oMatch In .Execute(sResponse)
            If oMatch.SubMatches.Count = 1 Then
                PushItem aData, oMatch.SubMatches(0)
            Else
                aTmp = Array()
                For Each sSubMatch In oMatch.SubMatches
                    PushItem aTmp, sSubMatch
                Next
                PushItem aData, aTmp
            End If
        Next
    End With

End Sub

Sub PushItem(aData, vItem, Optional bAppend As Boolean = True)

    If Not (IsArray(aData) And bAppend) Then aData = Array()
    ReDim Preserve aData(UBound(aData) + 1)
    aData(UBound(aData)) = vItem

End Sub

Function DecodeHTMLEntities(sText As String) As String

    Static oHtmlfile As Object
    Static oDiv As Object

    If oHtmlfile Is Nothing Then
        Set oHtmlfile = CreateObject("htmlfile")
        oHtmlfile.Open
        Set oDiv = oHtmlfile.createElement("div")
    End If
    oDiv.innerHTML = sText
    DecodeHTMLEntities = oDiv.innerText

End Function

Function Denestify(aRows)

    Dim aData()
    Dim aItems()
    Dim i As Long
    Dim j As Long

    If UBound(aRows) = -1 Then Exit Function
    ReDim aData(1 To UBound(aRows) + 1, 1 To 1)
    For j = 0 To UBound(aRows)
        aItems = aRows(j)
        For i = 0 To UBound(aItems)
            If i + 1 > UBound(aData, 2) Then ReDim Preserve aData(1 To UBound(aRows) + 1, 1 To i + 1)
            aData(j + 1, i + 1) = aItems(i)
        Next
    Next
    Denestify = aData

End Function

Sub Output2DArray(oDstRng As Range, aCells As Variant)

    With oDstRng
        .Parent.Select
        With .Resize( _
                UBound(aCells, 1) - LBound(aCells, 1) + 1, _
                UBound(aCells, 2) - LBound(aCells, 2) + 1)
            .NumberFormat = "@"
            .Value = aCells
        End With
    End With

End Sub

The output for me as follows:

output

and that is the same as results on the webpage:

webpage

I add some variables values below, it may help to debug in case of any issues. To watch the content of sRespHeaders and sRespText I used additional procedure WriteTextFile from this answer.

sRespHeaders after the first XmlHttpRequest call (execute WriteTextFile sRespHeaders, "C:\tmp.txt", -1):

Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Date: Sat, 26 Aug 2017 14:24:48 GMT
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Server: Apache
Set-Cookie: PHPSESSID=rl4gc6nq91tfb34u2inj634u10; path=/
Set-Cookie: restrwww4=!hN5+tRTsssR9ii3Yf8b335uDNFxhmd5PNCjvCndeUeIwBxZnB38oHuGc9Nz19debb6vLbW1nYQ+Ncgw=; path=/; Httponly
X-Cnection: close

aSetHeaders after extracting cookies:

aSetHeaders

Relevant part sRespText containing a table with target data after the second XmlHttpRequest call (execute WriteTextFile sRespText, "C:\tmp.htm", -1):

<table border="0" width="100%">
<tr>
    <th>lp.</th>
    <th>kod PNA</th>
    <th>nazwa <br />(firmy lub placówki pocztowej)</th>
    <th>miejscowość</th>
    <th>adres</th>
    <th>województwo</th>
    <th>powiat</th>
    <th>gmina</th>
</tr>
            <tr>
            <td>1.</td>
            <td>20-610</td>
    <td></td>
            <td>Lublin</td>
            <td>                    Kajetana Hryniewieckiego                                <br />
            <i>numery od&nbsp;1&nbsp;do&nbsp;końca&nbsp;obie strony</i>
            </td>
            <td>LUBELSKIE</td>
            <td>Lublin</td>
            <td>Lublin</td>
        </tr>
        <tr>
            <td>2.</td>
            <td>20-610</td>
    <td></td>
            <td>Lublin</td>
            <td>                    Leszka Czarnego                             <br />
            <i>numery od&nbsp;1&nbsp;do&nbsp;końca&nbsp;obie strony</i>
            </td>
            <td>LUBELSKIE</td>
            <td>Lublin</td>
            <td>Lublin</td>
        </tr>
        <tr>
            <td>3.</td>
            <td>20-610</td>
    <td></td>
            <td>Lublin</td>
            <td>                    Mieszka I                               <br />
            <i>numery od&nbsp;1&nbsp;do&nbsp;końca&nbsp;obie strony</i>
            </td>
            <td>LUBELSKIE</td>
            <td>Lublin</td>
            <td>Lublin</td>
        </tr>
        <tr>
            <td>4.</td>
            <td>20-610</td>
    <td></td>
            <td>Lublin</td>
            <td>                    Piastowska                              <br />
            <i>numery od&nbsp;1&nbsp;do&nbsp;końca&nbsp;obie strony</i>
            </td>
            <td>LUBELSKIE</td>
            <td>Lublin</td>
            <td>Lublin</td>
        </tr>
</table>

aRows after parsing table rows:

aRows after parsing table rows

aRows after parsing table cells:

aRows after parsing table cells

aData after Denestify call:

aData

omegastripes
  • 12,351
  • 4
  • 45
  • 96
  • Thank you for so much effort. It is great your code works on your machine, but... I dont know why it doesnt work on mine. It just deletes all input in my excell Sheet, but doesnt fill them with any data. Do you have any idea why? I use Office '03 (company rules). – Lucas Aug 26 '17 at 10:49
  • 1
    @Lucas I ran the code on Win 7 HB x64, Excel 2010 64-bit. No output means that no table found and parsed in the second response (the same response containing the search page you have in the question). Try to debug by step over, and referencing to variables values I have posted. – omegastripes Aug 26 '17 at 15:14
  • are you familiar with Chilkat? – Lucas Aug 28 '17 at 13:08
  • @Lucas I'm not familiar with Chilkat. – omegastripes Aug 28 '17 at 13:24
  • Nevermind then. Thank you for your help, I really appriciate it. I will try to debug my code using yours. If more questions will come up, can I ask you? – Lucas Aug 29 '17 at 09:24
  • @Lucas have you succeeded? – omegastripes Jan 13 '18 at 21:21
  • hey, thank you for your effort and impact into my problem, but it was needed for me during my internship, which has ended few months ago, this is why I have quickly forgotten about the whole thing. Answering your question - no, didnt work, but I am 99% sure it was about the old softwer :( – Lucas Jan 14 '18 at 13:32
  • @Lucas Anyway if you found the answer helpful you may click to accept it. – omegastripes Jan 14 '18 at 23:30
  • Sure, sorry for not doing so, I am quite new to the SO. Thanks again! – Lucas Jan 15 '18 at 12:33