В Excel VBA, как проверить, полностью ли загружена веб-страница?

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

Do While objIE.Busy = True Or objIE.readyState  4: DoEvents: Loop 

Но иногда я вижу загрузку текстового содержимого после того, как метод определяет, что страница полностью загружена, и поэтому контент не извлекается.

Однако, если я пройду через код через F8, содержимое будет извлекаться каждый раз. Это делается примерно так же быстро, как я могу нажать клавишу F8 несколько раз.

Итак, как я могу проверить, чтобы страница и весь ее контент были полностью загружены до того, как код продолжит извлечение данных?

В обоих случаях IE работает невидимо. Тем не менее, я пробовал это с IE видимым, и на страницах, с которыми я работаю, есть контент в этом конкретном месте.

Это выполняется в Excel 2016, используя скрипт VBA. Конкретный запрос на контент записывается так:

  'get item name from page and write it to the first cell on the first empty row available Set itemName = objIE.document.querySelector(".the-item-name") Worksheets("Results").Range("A1048576").End(xlUp).Offset(1, 0).Value = itemName.innerText 

Я прочитал Excel VBA: дождитесь выполнения JavaScript в Internet Explorer, потому что я думаю, что, возможно, значения добавляются после загрузки документа, чтобы никто не мог очищать данные. Тем не менее, я не могу определить какой-либо скрипт, который может это сделать. Не означает, что его там нет. Я просто этого не вижу.

Конкретным примером страницы с этой проблемой является URL-адрес

https://www.homedepot.ca/en/home/p.dry-cloth-refills-32—count.1000660019.html

Изначально элемент div product-total-price содержит тире (-) перед загрузкой цены, так что запрос будет возвращен: - / each вместо $11.29 / each .

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

 setPriceUM: Set hdPriceUM = objIE.document.querySelector(".product-total-price").innerTe‌​‌​xt hdPriceUMString = hdPriceUM.innerText stringTest = InStr(hdPriceUMString, "-") If stringTest = True Then GoTo setPriceUM Else Debug.Print hdPriceUMString End If 

Спасибо, что нашли время, чтобы прочитать это и рассмотреть.

Функциональность веб-страниц очень различна, поэтому нет решения, которое будет соответствовать всем им.

Что касается вашего примера, ваше обходное решение является рабочим решением, код может выглядеть следующим образом:

 Sub TestIE() Dim q With CreateObject("InternetExplorer.Application") .Visible = True .Navigate "https://www.homedepot.ca/en/home/p.dry-cloth-refills-32---count.1000660019.html" ' Wait IE Do While .readyState < 4 Or .Busy DoEvents Loop ' Wait document Do While .document.readyState <> "complete" DoEvents Loop ' Wait element Do q = .document.querySelector(".product-total-price").innerText If Left(q, 1) <> "-" Then Exit Do DoEvents Loop .Quit End With Debug.Print q End Sub 

Во всяком случае, вам нужно заглянуть в процесс загрузки веб-страницы, изменения XHR и DOM, используя инструменты для разработчиков браузера (F12). Идя таким образом, вы можете обнаружить, что один из многочисленных XHR возвращает цену в формате JSON. Он заносится на вкладку в сети инструментов разработчика браузера прямо перед появлением цены во время загрузки страницы. Этот XHR создается одним из загруженных JS, особенно после события, загруженного страницей. Попробуйте этот URL (я просто скопировал его с вкладки в сети):

https://www.homedepot.ca/homedepotcacommercewebservices/v2/homedepotca/products/1000660019/localized/9999?catalogVersion=Online&lang=en

Таким образом, вы можете просто воспроизвести этот XHR и извлечь цену, разделив:

 Sub TestXHR() Dim q With CreateObject("MSXML2.XMLHTTP") .Open "GET", "https://www.homedepot.ca/homedepotcacommercewebservices/v2/homedepotca/products/1000660019/localized/9999?catalogVersion=Online&lang=en", False .Send q = .ResponseText End With q = Replace(q, " : ", ":") q = Split(q, """displayPrice""", 2)(1) q = Split(q, """formattedValue"":""", 2)(1) q = Split(q, """", 2)(0) Debug.Print q End Sub 

Но опять же, нет общего случая.

Вы также можете использовать парсер JSON, взгляните на некоторые примеры .

Interesting Posts

Используйте функцию динамического ключевого слова / .NET 4.6 в Unity

Почему не удается изменить программу по умолчанию, чтобы открыть расширение в Windows 7?

Как выбрать ВСЕ УДАЛЕННЫЙ (или ВСЕ ДОБАВЛЕННЫЙ) текст (изменение дорожки) в MS Word 2016

Как искать одно значение в любом столбце любой таблицы внутри одной базы данных MS-SQL?

Как настроить CDB в Qt Creator?

Чтение значений в переменную оболочки из трубы

angularjs 1.6.0 (последние сейчас) маршруты не работают

Как создать EditText с помощью кнопки cross (x) в конце?

String.Format целое число, чтобы использовать разделитель тысяч без десятичных знаков или число 0 для малых целых чисел

Обнаруживать, является ли stdin терминалом или трубой?

Существует ли регулярное выражение для определения правильного регулярного выражения?

Каким образом можно использовать угловые2 HTTP-запросы с защитой Django CSRF?

Какой формат жесткого диска я использую для Mac и Windows для записи / чтения?

Почему свойство Set выбрасывает исключение StackOverflow?

ggplot: Как изменить метки фасетов?

Давайте будем гением компьютера.