Загрузка файла VBA с логином не работает

Я пытаюсь загрузить файл с этого веб-сайта, пробовал кучу кода, который я могу найти, и файл загружается, но показывает html страницы входа.

Ниже приведены 2 версии, которые я пробовал. Я пробовал каждый фрагмент кода, который мог найти на SO, и пока не повезло.

Я попробовал обе версии здесь, у них была одна и та же проблема, но их решение не работает для меня. Файл загрузки Vba из Интернета WinHttpReq с входом в систему не работает

Кажется, я не могу пройти процесс входа в систему. Я знаю, что переменные (имя пользователя, пароль) в приведенном ниже коде неверны, но я перепробовал все переменные, которые смог найти в источнике (UniqueUser, UniqueLogin, LoginName, каждое слово, которое у них там было), и все равно не повезло.

У одних версий ошибка кода в строке SET COOKIE, у других ошибок нет, файл скачивается но внутри файла все равно html страницы входа

 Sub DownloadFile2(myURL As String)


Dim CurPath As String

CurPath = CurrentProject.Path & "\"
Dim strCookie As String, strResponse As String, _
  strUrl As String
  Dim xobj As Object
  Dim WinHttpReq As Object
  Set xobj = New WinHttp.WinHttpRequest

UN = "hhhhh"
PW = "gggg"

  strUrl = "https://pnds.health.ny.gov/login"
  xobj.Open "POST", strUrl, False
  xobj.SetRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36"
  xobj.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
  xobj.Send "username=" & UN & "&password=" & PW & "&login=login"
  strResponse = xobj.ResponseText

  strUrl = myURL
  xobj.Open "GET", strUrl, False

  xobj.SetRequestHeader "Connection", "keep-alive"
  xobj.SetRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36"
  xobj.Send

  strCookie = xobj.GetResponseHeader("Set-Cookie")
  strResponse = xobj.ResponseBody

 If xobj.Status = 200 Then
    Set oStream = CreateObject("ADODB.Stream")
    oStream.Open
    oStream.Type = 1
    oStream.Write xobj.ResponseBody
    oStream.SaveToFile CurPath & "ValidationDataHFIS.csv", 2 ' 1 = no overwrite, 2 = overwrite
    oStream.Close
End If
End Sub


Sub ddd()

DownloadFile2 ("https://pnds.health.ny.gov/xxxx/xxxx/8")
End Sub

person lalachka    schedule 11.10.2019    source источник
comment
Я могу сразу сказать вам, почему DownloadFile2 ("https://pnds.health.ny.gov/ReferenceDownload/Download/8") не работает должным образом. Вам нужна ссылка на фактический файл, который всегда будет заканчиваться расширением файла (например, .xlsx). Кроме того, DownloadFile2 — это подпрограмма, а не функция. Так что не заключайте аргумент (URL) в круглые скобки.   -  person K.Dᴀᴠɪs    schedule 11.10.2019
comment
но если я вставлю эту ссылку в адресную строку, файл будет загружен.   -  person lalachka    schedule 11.10.2019
comment
Вы должны обрабатывать все перенаправления и файлы cookie в коде, который вы можете увидеть в браузере (например, Chrome) на вкладке сети инструментов разработчика.   -  person omegastripes    schedule 11.10.2019
comment
какой реальный логин-пароль, можете поделиться каким-нибудь демо-счетом? Потому что описанное вами поведение может быть вызвано неправильным логином/паролем (что вернет вас к форме входа)   -  person Pavel Lint    schedule 07.11.2019
comment
Я не могу((( Информация для входа определенно верна, во-первых, я могу войти и делать там все, что мне нужно, во-вторых, если я вставлю эту ссылку в адресную строку, я получу логин. окно, я набираю его, и файл загружается. Так что информация для входа определенно не проблема. Если вы посмотрите на ссылку в моем исходном посте, вы увидите, что у парня такая же проблема, он ее как-то решил. , но я хреново в этом, поэтому я не могу понять, как Его код не работает для меня.   -  person lalachka    schedule 07.11.2019
comment
@PavelLint также, это то, что сказал один из комментаторов. Вы должны обрабатывать все перенаправления и файлы cookie в коде, который вы можете видеть на вкладке сети инструментов разработчика браузера (например, Chrome), но опять же, я ничего не знаю, поэтому я не знаю что с этим делать   -  person lalachka    schedule 07.11.2019
comment
@lalachka Вы уверены, что xobj.Send "username=" & UN & "&password=" & PW & "&login=login" правильно? Форма входа на https://pnds.health.ny.gov/login даже не содержит поля с именем username. Когда я пытаюсь войти на эту страницу, запрос POST содержит совершенно другие данные (LoginName, Token и т. д.).   -  person Petr Srníček    schedule 10.11.2019
comment
@PetrSrníček нет, я не уверен. Это копирование и вставка. Я ничего не понимаю в этом. Но с тех пор, как я опубликовал, я понял, что часть пароля и имени пользователя не высечена на камне, и попробовал каждое слово, которое я могу найти на их сайте (UniqueUser, UniqueLogin, Name, я забыл, что еще у них там было) и безуспешно. Я видел токен, но не знал, что с ним делать. Может быть, я выбираю неправильные переменные? Как вы думаете, что это должно быть?   -  person lalachka    schedule 10.11.2019
comment
@lalachka Будет довольно сложно правильно указать параметры POST. Страница шифрует информацию для входа на стороне клиента и отправляет зашифрованную информацию в запросе POST. Просто взгляните на обработчик кликов, прикрепленный к кнопке «Войти». Он вызывает эту функцию шифрования. Я думаю, что самый простой способ сделать это — использовать VBA для автоматизации действий браузера. Однако я не смог заставить это работать в разумные сроки.   -  person Petr Srníček    schedule 10.11.2019
comment
@PetrSrníček, вы имеете в виду использование ключей отправки или что-то в этом роде? И большое спасибо за попытку и объяснение проблем. Я понимаю, что вы говорите. Я очень ценю это!   -  person lalachka    schedule 10.11.2019
comment
@lalachka Я попробовал этот подход, но не смог заставить страницу выполнять правильный обработчик кликов, когда я имитировал щелчок по кнопке входа. Боюсь, что больше ничем помочь не могу. Кстати, вы можете пересмотреть и обновить теги в этом вопросе. Это имеет очень мало общего с CSV, Chrome или MS Access.   -  person Petr Srníček    schedule 11.11.2019
comment
@PetrSrníček конечно. Какими должны быть теги? Я не был уверен, как классифицировать это   -  person lalachka    schedule 11.11.2019
comment
@omegastripes эй, за это есть награда. Вы можете помочь? Я потерялся, и последний человек, который пытался, сказал, что это, вероятно, невозможно сделать, потому что сайт использует какой-то скрипт для отправки данных POST. Я все еще надеюсь, что есть способ, хотя.   -  person lalachka    schedule 11.11.2019
comment
На сайте определенно используются скрипты, поэтому единственный способ — выполнить реверс-инжиниринг этих скриптов и создать свой собственный код VBA, выполняющий те же вычисления.   -  person omegastripes    schedule 11.11.2019
comment
Вы отправляете данные для входа на неверный адрес для входа. Ваш правильный адрес для входа — https://pnds.health.ny.gov/account/login, страница ожидает LoginName и Token. Токен генерируется с использованием SecurityManager.generate( u, p );. Самый простой способ — использовать объект Browser и выполнить автоматизацию. или узнайте, предлагает ли ваш IT team API   -  person Krish    schedule 13.11.2019
comment
@krishKM спасибо!!! И что вы подразумеваете под автоматизацией с помощью объекта Browser. Я ничего не понимаю, когда дело доходит до этого, не могли бы вы дать мне больше информации о том, как получить токен? Я не могу спросить ИТ-команду, это для другой компании, я пытаюсь автоматизировать отчет, который использует файлы с их веб-сайта. Нежелательно их ни о чем просить((((   -  person lalachka    schedule 15.11.2019


Ответы (2)


Вы отправляете данные для входа на неверный адрес для входа. Ваш правильный адрес для входа: https://pnds.health.ny.gov/account/login страница ожидает LoginName и Token. Токен генерируется с помощью SecurityManager.generate( u, p );

Вы по-прежнему можете проконсультироваться с их ИТ-командой, чтобы убедиться, что вы не нарушаете их политику.

Вот способ сделать это с помощью объекта браузера IE.

Private Sub DownloadValidationData()
'Create Internet explorer object
Dim IE As Object
Set IE = CreateObject("INTERNETEXPLORER.APPLICATION")

IE.Visible = True

Dim URL As String: URL = "https://pnds.health.ny.gov/account/login"

IE.Navigate URL
While IE.READYSTATE <> READYSTATE_COMPLETE
    DoEvents
Wend

Dim userName As String: userName = "test"
Dim password As String: password = "test"

'Fill the login form
IE.Document.getElementById("UniqueUser").Value = userName
IE.Document.getElementById("UniquePass").Value = password

'Submit the form
IE.Document.querySelector("button.SignIn").Click

'Wait for login to complete
While IE.READYSTATE <> READYSTATE_COMPLETE
    DoEvents
Wend
'Verify you are logged in: As we don't know what the site looks like after login in. Only you can do this step.

'Navigate to Download Page. This should prompt to save the file.
IE.Navigate theDownloadUrl '"https://pnds.health.ny.gov/xxxx/xxxx/8"

'Once downloaded just close the browser and exit
'IE.Quit
'Set IE = Nothing


'If you are interested in geting/generating the token using their script you can play around with below lines. These lines come before loging in. Please note: execScript is depreciated now

'Dim Token as string
'IE.Document.parentwindow.execScript ("$('#Token').val(SecurityManager.generate(""" & username & """, """ & password & """ ))")
'Token = IE.Document.getElementById("Token").Value
'Use the token to sign in using your code. That'll be xobj.Send "LoginName =" & userName & "&Token=" & Token
'But not sure if it will work.



End Sub
person Krish    schedule 26.11.2019
comment
Они знают, что мы пытаемся найти способ автоматического входа, я не держу это в секрете))) никаких возражений с их стороны, огромное спасибо, сегодня попробую - person lalachka; 26.11.2019
comment
я авторизовался!!!! файл не скачивается, а я залогинился))))) пытаюсь поиграть с ним. ошибки нет, все хорошо, просто не скачивается - person lalachka; 26.11.2019
comment
Итак, он входит в систему, это нормально, что файл не загружен, пока я могу научиться перемещаться по сайту через vba. подскажите как назвать эту штуку? или где научиться делать? ‹li class=› ‹a href=/referencedownload›‹i class=fa fa-fw fa-download›‹/i› ‹span class=menu-item-parent›Справочные загрузки‹/span›‹/a› ‹/ ли › - person lalachka; 26.11.2019
comment
этот сайт должен помочь вам w3schools.com/jsref/met_document_getelementsbytagname.asp. На сайте вы можете найти множество функций, которые вы можете попробовать - person Krish; 27.11.2019
comment
Спасибо. Это всегда теги? Я вижу в вашем коде, что вы используете elementid. Как узнать, на что вы смотрите: тег, элемент, что-то еще? - person lalachka; 27.11.2019
comment
все element. Вы можете найти элемент по его tag name или по id. Сайт действительно хорошо объясняет это с примерами и что означает tag name. Пожалуйста, следите за сайтом. - person Krish; 27.11.2019
comment
Да, поэтому и возник вопрос. Мне было интересно, какие другие страницы на этом сайте могут быть полезны, кроме той, на которую вы ссылаетесь, поскольку там говорится только о тегах, а я видел код, который не использует теги. Но ничего страшного, я обязательно разберусь - person lalachka; 27.11.2019
comment
@lalachka в левой части сайта есть меню с огромным набором команд. Нажмите другие функции, которые вас интересуют, и вы можете прочитать больше. - person Krish; 27.11.2019
comment
в этом суть лол. Я не знаю, что меня должно интересовать :) Я видел меню, но я совсем новичок в этом деле, если это не очевидно. Но я думаю, что тег должен, по крайней мере, заставить меня начать, пойду оттуда. Еще раз спасибо. Баунти присудят через 20 часов, я думаю - person lalachka; 27.11.2019

Я бы сделал небольшую рекурсивную функцию, которая проверяет перенаправления до тех пор, пока их не останется.

Так:

Option Explicit
Const WinHttpRequestOption_EnableRedirects = 6

Public Function GetRedirect(ByRef oHttp As Object, ByVal strUrl As String) As String
    With oHttp
        .Open "HEAD", strUrl, False
        .Send
    End With

    If oHttp.Status = 301 Or oHttp.Status = 302 Or oHttp.Status = 303 Then
        GetRedirect= GetRedirect(oHttp, oHttp.GetResponseHeader("Location"))
    Else
        GetRedirect= strUrl
    End If
End Function

Sub DownloadFile2(myURL As String)

    Dim CurrentProject
    Dim CurPath As String

    CurPath = CurrentProject.Path & "\"
    Dim strCookie As String, strResponse As String, _
    strUrl As String
    Dim xobj As Object
    Dim WinHttpReq As Object
    Set xobj = CreateObject("WINHTTP.WinHTTPRequest.5.1")
    Dim UN As String
    UN = "hhhhh"
    Dim PW As String
    PW = "gggg"

    strUrl = "https://pnds.health.ny.gov/login"
    With xobj
        .Open "POST", strUrl, False
        .SetRequestHeader "Connection", "keep-alive"
        .SetRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36"
        .SetRequestHeader "Content-Type", "application/x-www-form-urlencoded"
        .Send "&username=" & UN & "&password=" & PW & "&login=login"
    End With

    strUrl = GetRedirect(xobj, myURL)

    If xobj.Status = 200 Then
        Dim oStream As Object
        Set oStream = CreateObject("ADODB.Stream")
        With oStream
            .Open
            .Type = 1
            .Write xobj.ResponseBody
            .SaveToFile CurPath & "ValidationDataHFIS.csv", 2 ' 1 = no overwrite, 2 = overwrite
            .Close
        End With
    End If
End Sub

Sub ddd()

    DownloadFile2 ("https://pnds.health.ny.gov/xxxx/xxxx/8")
End Sub

ПРИМЕЧАНИЕ. Этот код не тестировался, и его необходимо адаптировать для вашего варианта использования.

person HackSlash    schedule 07.11.2019
comment
эй, во-первых, спасибо! во-вторых, здесь появилась ошибка 429 Set xobj = CreateObject(WINHTTP.WinHTTPRequest), изменено на Set xobj = CreateObject(WINHTTP.WinHTTPRequest.5.1), теперь ошибка GetResult = GetResult(oHttp, oHttp.GetResponseHeader(Location)), 2-й GETRESULT выделено, ошибка Sub или Function Not Define - person lalachka; 08.11.2019
comment
подумал, что может быть GETRESULT должен быть GETREDIRECT, вместо этого изменил его, теперь эта строка с ошибками strCookie = xobj.GetResponseHeader(Set-Cookie) с запрошенным заголовком не найдена - person lalachka; 08.11.2019
comment
еще одна вещь, когда я наводил курсор на STRRESPONSETEXT в strResponse = xobj.ResponseTex, он отображается как . не уверен, что это значит, что ответ пуст? - person lalachka; 08.11.2019
comment
Правильно, я обновил свой пример, чтобы удалить эти ошибки. Я не уверен, что это будет за текст. Вы в конечном итоге на ссылку для скачивания сейчас? - person HackSlash; 08.11.2019
comment
нет((( я обновил его сам ранее и ошибка этой части strCookie = xobj.GetResponseHeader(Set-Cookie) с запрошенным заголовком не найдена – - person lalachka; 08.11.2019
comment
Так что удалите эту строку - person HackSlash; 09.11.2019
comment
файл загружен, но опять же, он имеет html экрана входа в систему, а не данные, которые он должен иметь - person lalachka; 09.11.2019
comment
Может быть, это последнее открытие начинает все сначала. Я удалил весь этот блок, потому что в конце GetRedirect мы должны оказаться на правильной странице. - person HackSlash; 09.11.2019
comment
еще((( то же самое, файл скачан, html страницы авторизации - person lalachka; 09.11.2019
comment
Похоже, вы не можете войти в систему. Откуда вы знаете, что так много вообще работает? - person HackSlash; 09.11.2019
comment
да, я не могу войти в систему, это то, что я все время говорил. Все работает, когда я загружаю его вручную. Есть и другие люди с такой же проблемой, я дал ссылку на свой ОП, где у парня была такая же проблема. Я просто не понимаю, как он это исправил - person lalachka; 09.11.2019
comment
Вы пропустили & перед словом username. - person HackSlash; 09.11.2019
comment
его не должно быть, но я попытался его добавить. Неа - person lalachka; 09.11.2019
comment
Весь мой код выполняет перенаправления. Вы должны войти. - person HackSlash; 11.11.2019
comment
что вы имеете в виду, мне нужно сначала войти в систему. Вот с чем мне нужна помощь: со входом в систему. - person lalachka; 11.11.2019