В коде парсинга не распознаётся объект

Автор Посетитель 02.09.2024, 06 августа 2025, 10:17

Посетитель 02.09.2024

Скажите, пожалуйста, выдаётся ошибка 424. Не распознаётся объект. Что неправильно ?

Sub ExtractData()
    Dim http As Object
    Dim html As Object
    Dim productNames As Object
    Dim productPrices As Object
    Dim url As String
    Dim i As Integer
   
    ' Define the target URL
    url = "https://autoshini.ru/podbor-shin"
   
    ' Fetch the HTML content
    Set http = CreateObject("MSXML2.XMLHTTP")
    http.Open "GET", url, False
    http.send
   
    ' Load the HTML into an HTMLDocument object
    Set html = CreateObject("HTMLFile")
    html.body.innerHTML = http.responseText
   
    ' Find elements by class name
    Set productNames = html.getElementsByClassName("data-name")
    Set productPrices = html.getElementsByClassName("data-price")
   
    ' Test the extraction (display the first product name and price)
    MsgBox "First product: " & productNames(0).innerText & " - " & productPrices(0).innerText

End Sub

Администратор

На веб-странице такой фрагмент:
<div data-merchant="list" data-id="706568" data-cid="49905" data-currencyCode="RUB" data-name="Goodride ZuperEco Z-107 195/65 R15 91V" data-price="4760" data-brand="Goodride" data-category="Шины" data-category2="Goodride" data-category3="ZuperEco Z-107" data-position="1" data-page="Search results"></div>

Вы указываете в коде:
Set productNames = html.getElementsByClassName("data-name")

Обратите внимание на "ByClassName". Если перевести на русский: получить элементы по имени класса.
Но data-name не является классом, а является параметром тега "div". В HTML "параметр" тега называется  "атрибут" тега. Поэтому вам надо научиться получать информацию об атрибутах и в частности об атрибуте "data-name".

Значит нужно извлекать по-другому принципу.

Посетитель 02.09.2024

Заменил на TagName. Результат такой же.

' Find elements by Tag name
    Set productNames = html.getElementsByTagName("data-name")
    Set productPrices = html.getElementsByTagName("data-price")

Администратор

TagName - это имя тега.
В представленном коде тег это <div>. А "data-name" это атрибут тега.

Пока порядок действий такой нарисовывается:
в цикле просматриваете все теги <div>, а в каждом теге "div" просматриваете атрибут "data-name".

Администратор


Посетитель 02.09.2024

Ошибка, кажется, ещё получается в том, что код сайта выдаётся не полностью. Совсем какой-то урезанный. И там нечего искать.

Sub ПарсингПервый()
    Dim http As Object
    Dim html As Object
    Dim productNames As Object
    Dim productPrices As Object, s As Object
    Dim url As String
    Dim i As Integer
   
    ' Define the target URL
    url = "https://autoshini.ru/podbor-shin"
   
    ' Fetch the HTML content
    Set http = CreateObject("MSXML2.XMLHTTP")
   
    http.Open "GET", url, False
    http.send
   
    ' Load the HTML into an HTMLDocument object
    Set html = CreateObject("HTMLFile")
    html.body.innerHTML = http.responseText
   
    MsgBox http.responseText
   
    ' Find elements by tag name
    Set productNames = html.getElementsByTagName("div")
   
    Debug.Print productNames(0).getAttribute("data-name")
   
    End Sub




Администратор

В представленном коде вы смотрите атрибут "data-name" только у первого тега <div>.
Но тег <div> это общий тег, а не специфический и используется очень часто.
Поэтому в теге <div> необязательно может быть атрибут "data-name".

Вам нужно просматривать все теги <div> и внутри каждого тега <div> вам нужно искать атрибут "data-name".
В каких-то тегах <div> будет атрибут "data-name", в каких-то тегах <div> не будет атрибута "data-name".

И в данном коде нет ошибки. Вы неточно сформулировали свою мысль.

Посетитель 02.09.2024

Но во многих div эти атрибуты есть. Тут пока, как я вижу, дело в том, что сайт не даёт загрузить его код. Потому что написав кода вот так :

Sub ПарсингChrome()
    Dim driver As New WebDriver ' Переменная будет новым вебдрайвером (инициализируется новый драйвер Селениум)
    driver.Start "Chrome" ' Открывается новая страница Chrome
    driver.Get "https://autoshini.ru/podbor-shin" ' Драйвер направляет к заданной странице
    Application.Wait Now + TimeValue("0:00:05") ' Ждём (Application.Wait приостанавливает дальнейшее действие макроса) 5 секунд, чтобы сайт полностью загрузился.

   
    Dim name As Object
    Dim price As Object
       
    Dim http As Object
    Dim html As Object
   
    Set html = CreateObject("HTMLFile")
    Set http = CreateObject("MSXML2.XMLHTTP")
    Application.Wait Now + TimeValue("0:01:00") ' Ждём (Application.Wait приостанавливает дальнейшее действие макроса) 5 секунд, чтобы сайт полностью загрузился.
    html.body.innerHTML = http.responseText
   
    MsgBox http.responseText
   
    ' Find elements by tag name
    Set productNames = html.getElementsByTagName("div")
   
    Debug.Print productNames(0).getAttribute("data-name")
   
    driver.Quit

End Sub

В строке html.body.innerHTML = http.responseText
программа через минуту останавливается с сообщением "Данные, необходимые для завершения этой операции, ещё не доступны. Ошибка -2147483638 (8000000а)"

Получается, как сайт не даёт парсить.
Вот если бы каким-то образом скачать/получить его код. Тогда можно было бы найти атрибуты.

Администратор

Эти три команды ждут, когда все данные скачаются, и только потом макрос двигается дальше:
  ' Fetch the HTML content
    Set http = CreateObject("MSXML2.XMLHTTP")
    http.Open "GET", url, False
    http.send

Это настраивается в этой строке:
http.Open "GET", url, False

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

Поэтому вам не нужно писать код, который что-то ждёт. Для этих трёх команд не нужно писать дополнительный код, который будет ждать что-то.


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

Посетитель 02.09.2024

Ясно, спасибо большое.
В общем, нужно искать, как скачать код всего сайта.

Администратор

Как я понял, у сайта есть защита.
Значит у вас задача - как обойти защиту сайта.
Если у сайта нет защиты, то эти три команды дают код всего сайта:
  ' Fetch the HTML content
    Set http = CreateObject("MSXML2.XMLHTTP")
    http.Open "GET", url, False
    http.send

Если сайт блокирует макрос, то вы вообще не получите код сайта.

Посетитель 02.09.2024

Ясно. Код есть лишь маленький. Я высылал его скрин. Наверное, блокирует частично.

Администратор

На фото MsgBox - в него не помещается весь код.
Сохраните код сайта в текстовый файл.