Страницы: 1
RSS
Получение параметров Cookies
 
При парсинге сайта арбитрточкару не могу решить следующую задачу. При запросе Post в RequestHeader используется Cookies. Без него не получается получить правильны ответ. Эти Cookie имеют время жизни, после чего требуется их обновить.


Через запрос GET  и последующее .getAllResponseHeaders:
Код
Sub sGetCoockes()
    Dim sGetResult As Variant
    Dim httpObject As Object
    Set httpObject = CreateObject("Msxml2.ServerXMLHTTP.6.0")
    httpObject.Open "GET", "https://kad.arbitr.ru/", False
    httpObject.setRequestHeader "Host", "kad.arbitr.ru"
    httpObject.setRequestHeader "Content-type", "application/xml"
    httpObject.send
    sGetResult = httpObject.getAllResponseHeaders
    Debug.Print sGetResult
    Set httpObject = Nothing
End Sub
получается ответ, который содержит только два компонента (ASP.NET_SessionId и CUID):
Код
Pragma: no-cache
Content-Length: 4298
Content-Type: text/html; charset=utf-8
Set-Cookie: ASP.NET_SessionId=onva11syoaf5yei0dtdb0mps; path=/; HttpOnly
Set-Cookie: ASP.NET_SessionId=onva11syoaf5yei0dtdb0mps; path=/; HttpOnly
Set-Cookie: CUID=f6e62d6a-38a2-4421-8da5-38ef0bc1b04c:dLSyS9fefhpkRtWAe2Sfyw==; domain=.arbitr.ru; expires=Wed, 11-Feb-2032 11:51:18 GMT; path=/; HttpOnly
Set-Cookie: .ASPXAUTH=fixcookie; domain=.kad.arbitr.ru; path=/; expires=Tue, 02-Apr-2012 14:12:08 GMT; HttpOnly
content-security-policy: upgrade-insecure-requests

Как я могу получить полный пакет Cookies (в том числе pr_fp    wasm   rcid) для формирования правильного запроса POST ?

 
При загрузке главной страницы браузер выполняет много запросов (в том числе и запросы, инициированные скриптами)
В ответ на разные запросы, сервером могут возвращаться разные куки (которые заменяют или дополняют предыдущие)
Смотрите, по каким запросам появляются эти куки, и выполняйте макросом аналогичные запросы:


Причем, это еще не всё
Некоторые куки ставятся в момент редиректов.
Сайт перенаправляет вас 2-3 раза, а ваш код считает заголовки ответа сервера только из последнего из 2-3 перенаправлений (и вы можете потерять кукисы, которые сайт выдавал в первых редиректах)
Чтобы это учесть, надо заметно усложнять функцию загрузки страницы:

Код
 ' ...
 
' отключаем авторедирект, чтобы получать cookies при каждом редиректе
wHTTP.Option(WinHttpRequestOption_EnableRedirects) = False

' ...

 wHTTP.Send

 ' считываем и запоминаем куки
 ResponseHeaders$ = DecodeUTF8(wHTTP.GetAllResponseHeaders)
 SaveCookiesFromResponseHeaders ResponseHeaders$
 
 ' если есть заголовок Location - выполняем редирект
 URL$ = GetRedirectLocation(ResponseHeaders$, wHTTP.Option(WinHttpRequestOption_URL))
 
 While IsURL(URL$) ' ЦИКЛ ДЛЯ РЕДИРЕКТОВ
     RedirectsCount& = RedirectsCount& + 1
     If RedirectsCount& > 5 Then
         AddBalloon "Зацикливание редиректа на " & CreateHTMLlink(URL$) & "<br />Загрузка страницы прервана.", bt_Warning
         GoTo StopRedirects
     End If
     If (PrevRedirectURL$ = URL$) And (RedirectsCount& > 1) Then
         ' надо очистить заголовки запроса, т.к. там старые Host и Referer
         Set wHTTP = New WinHttpRequest
         RequestHeadersStore.RemoveAll
         AddStandartHeadersIntoStore URL$
         AddRequestHeadersFromStore
         If Not WP Is Nothing Then WP.Proxy.Apply
     End If
     
     wHTTP.Open "GET", URL$, True
     AddRequestHeadersFromStore
     PrevRedirectURL$ = URL$
     
     PreviousCookies$ = GetCookiesFromStore
     If Not CookiesStore Is Nothing Then wHTTP.SetRequestHeader "Cookie", GetCookiesFromStore
     
     wHTTP.Send
     
     URL$ = ""
     If wHTTP.WaitForResponse(Timeout&) Then
         ' MsgBox .GetAllResponseHeaders, vbCritical
         ResponseHeaders$ = "": ResponseHeaders$ = wHTTP.GetAllResponseHeaders
         SaveCookiesFromResponseHeaders ResponseHeaders$
         
         URL$ = GetRedirectLocation(ResponseHeaders$, wHTTP.Option(WinHttpRequestOption_URL))
     End If
 Wend

' ...


Есть другой вариант — открыть страницу в браузере IE, и потом считать все Cookies из IE
Причем тут 2 варианта считывания — из документа IE (много, но не все, путем обращения к IE.document.Cookie), и напрямую из текстовых файлов Cookies (там точно всё считается)
И с этими кукисами потом выполнять запрос средствами WinHttp

Пример кода для считывания куки из системных файлов:
Код
Function GetIECookiesFromFiles(ByVal domain$, Optional Apply As Boolean) As String
    On Error Resume Next
    Dim sCookiesPath$, oCookies As Object, oFSO As Object, oFolder As Object, oFile
    Dim sContent As String, a() As String, i As Long, aItems, aCookies()
    
    ' read IE cookie files
    sCookiesPath = CreateObject("shell.application").Namespace("shell:Cookies").self.Path
    Set oCookies = CreateObject("Scripting.Dictionary")
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oFolder = oFSO.GetFolder(sCookiesPath)
    For Each oFile In oFolder.Files
        If LCase(oFSO.GetExtensionName(oFile.Name)) = "txt" Then
            With oFile.OpenAsTextStream(1, 0) ' read-only, ascii
                sContent = .ReadAll
                .Close
            End With
            sContent = Replace(sContent, vbCr, "")
            ' split cookies within file
            a = Split(sContent, vbLf & "*" & vbLf)
            For i = 0 To UBound(a) - 1
                If InStr(1, a(i), domain$, vbTextCompare) > 0 Then oCookies.Add oCookies.Count, a(i)
            Next
        End If
    Next
    
    ' parse data, repack to 2d array
    aItems = oCookies.Items()
    If UBound(aItems) = -1 Then Exit Function
    
    ' If CookiesStore Is Nothing Then Set CookiesStore = New Dictionary        ' глобальный словарь с cookies
    ReDim aCookies(1 To UBound(aItems) + 1, 1 To 6)
    Dim param_name$, param_value$, NewCookiesList$
    
    For i = 1 To UBound(aItems) + 1
        a = Split(aItems(i - 1), vbLf)
        
        param_name$ = "": param_value$ = ""
        param_name$ = a(0)
        param_value$ = a(1)
        
        
        If Len(param_name$) Then
            NewCookiesList$ = NewCookiesList$ & IIf(NewCookiesList$ = "", "", vbLf) & param_name$
            GetIECookiesFromFiles = GetIECookiesFromFiles & IIf(GetIECookiesFromFiles = "", "", "; ") & param_name$ & "=" & param_value$
            
            CookiesStore.Item(param_name$) = param_value$
        End If
    Next
    
    If (Len(NewCookiesList$) > 0) Then
        Debug.Print "Добавлено cookies из файлов IE: " & 1 + Len(NewCookiesList$) - Len(Replace(NewCookiesList$, vbLf, ""))
    End If
    
End Function

Sub test_IECookies()
   ' сначала надо открыть сайт https://www.planetaexcel.ru/ в браузере IE
   ' и только потом запускать этот макрос
    res = GetIECookiesFromFiles("planetaexcel.ru")
    Debug.Print res
    
    ' пример результата:
    
    ' Добавлено cookies из файлов IE: 6
    ' PHPSESSID=ZxFVnPmSxkYRIWHYk45QG1wpw67HjW4S; ct_sfw_pass_key=d923fe31370fb636c3ae0bbe78f888370; BX_USER_ID=dc035afce16c0c73611c8af1423dd; _ga=GA1.2.660066615.1645556965; _gid=GA1.2.1591444045.1644333965; _gat=1
End Sub

Изменено: Игорь - 11.02.2022 22:17:30
 
Игорь, спасибо большое за развернутый ответ. Я все воскресенье вчера бился. Но не победил:

Цитата
написал:
При загрузке главной страницы браузер выполняет много запросов
Да, я тоже это предполагал и пробежался по всему перечню на предмет Set-cookies. Ни в одном Response Headers не устанавливаются искомые Cookies.


Цитата
написал:
Чтобы это учесть, надо заметно усложнять функцию загрузки страницы:

Я не смог переложить предложенный код в VBA excel. Не распознаются функции GetRedirectLocation,SaveCookiesFromResponseHeaders и др. Не понимаю как их переложить. Может тут нужно какую библиотеку подкулючить

Цитата
написал:
открыть страницу в браузере IE
открыть страницу в браузере IE не вариант, видимо разработчики предусмотрели этот ход, и доступ к странице из IE защищен капчей.
 
Цитата
Ни в одном Response Headers не устанавливаются искомые Cookies
не верю
надо открывать страницу в режиме Инкогнито, предварительно открыв консоль браузера (до начала загрузки страницы)
и тогда найдете

Цитата
Я не смог переложить предложенный код в VBA excel.
это не готовый код. это алгоритм, для понимания, что примерно нужно делать

Цитата
доступ к странице из IE защищен капчей
ну так введите капчу один раз (у меня вот нет капчи, а у вас она из-за частых попыток запросов)
это же самый простой вариант, при запуске открыть браузер, ввести капчу если она есть, считать куки,  закрыть браузер, и потом выполнять запросы
 
Цитата
написал: надо открывать страницу в режиме Инкогнито
Искал и в режиме Инкогнито, и удалял куки прям перед перехода на страницу. Отслеживал все стоки в консоли. Использовал поиск в консоли. Соответствующие куки находит только Request Headers. Не исключаю, что я что то делал не так, но я затратил на это достаточно много времени.

Цитата
это алгоритм, для понимания, что примерно нужно делать
Да я в принципе понял, что это алгоритм. Попробую еще раз завтра с утра переложить в код. Может выйдет.

Цитата
написал: это же самый простой вариант, при запуске открыть браузер, ввести капчу если она есть, считать куки,  закрыть браузер, и потом выполнять запросы
Получить куки я могу и через консоль, скопировав их из Request Headers. Это нужно делать даже не так часто, данные куки живут около недели. Вопрос в автоматизации получения куков.
 
Цитата
Еще раз попытался пойти по твоему алгоритму, уткнулся в отсутствие Location в возвращаемом ответе

Цитата
написал:
' если есть заголовок Location - выполняем редирект


Код
Sub sGetCoockes()
    Dim sGetResult As Variant
    Dim httpObject As Object
    Dim sCookiesPath$, oCookies As Object, oFSO As Object, oFolder As Object, oFile
    Dim sContent As String, aCook() As String, i As Long, aItems, aCookies()
    
    Set httpObject = CreateObject("WinHttp.WinHttpRequest.5.1")
    httpObject.Open "GET", "https://kad.arbitr.ru/", False
    httpObject.Option(WinHttpRequestOption_EnableRedirects) = False
    httpObject.setRequestHeader "Host", "kad.arbitr.ru"
   ' httpObject.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
    httpObject.send

    sGetResult = httpObject.getAllResponseHeaders
     Debug.Print sGetResult
    Set httpObject = Nothing
End Sub


Ответ:

Код
[/CODE][P][/P]
[P][/P]
[P][/P]
[CODE]Cache-Control: no-cache, no-store, must-revalidate
Date: Tue, 15 Feb 2022 14:41:25 GMT
Pragma: no-cache
Content-Length: 4298
Content-Type: text/html; charset=utf-8
Set-Cookie: ASP.NET_SessionId=j1bhhlskxhwesanq15uikgcn; path=/; HttpOnly
Set-Cookie: ASP.NET_SessionId=j1bhhlskxhwesanq15uikgcn; path=/; HttpOnly
Set-Cookie: CUID=7cbb50c8-7d1b-4620-b880-b55adbfde177:egJsawQDPfJ+UtJCXEsarg==; domain=.arbitr.ru; expires=Sun, 15-Feb-2032 14:41:25 GMT; path=/; HttpOnly
Set-Cookie: .ASPXAUTH=fixcookie; domain=.kad.arbitr.ru; path=/; expires=Tue, 02-Apr-2012 14:12:08 GMT; HttpOnly
Set-Cookie: SERVERID=KAD-APP3; path=/
content-security-policy: upgrade-insecure-requests
Изменено: ANDREY - 15.02.2022 17:44:57
Страницы: 1
Наверх