, если .querySelector () поддерживает: nth-of-type (), что не так с .querySelector ("table: nth-of-type (2) tr"), когда я использую его в сценарии, который нене работает
Поддерживается при использовании Microsoft Internet Controls
для автоматизации браузера (IE8 +) и создается HTMLDocument
off ie.Document
. Затем у вас есть доступ к очень небольшому количеству селекторов псевдоклассов . Это не относится к HTMLDocument
, когда innerHTML
предоставляется через MSXML2.XMLHTTP
. Помните, что содержимое, которое вы вводите в переменную HTMLDocument
.innerHTML
, будет отличаться в XHR, где javascript не будет работать, по сравнению с IE
, где будет запускаться js, и браузер будет изменять содержимое / запрашивать дополнительные файлы, оставляя вас с измененным.document
. Как уже упоминалось в начале, конечно, есть и зависимость режима браузера / документа для последнего.
Селектор table:nth-of-type(2) tr
, даже если он поддерживается, здесь не подходит.
Значение элемента (Год постройки), который меня интересует, не всегда совпадает с одним и тем же индексом, поэтому использование индекса здесь неправильная идея
На основании более тщательного изучения вашего кода кажется, чтоизменчивость, которую вы пытаетесь учесть, - это потенциальная разница в количестве столбцов в целевой таблице и, следовательно, вероятность того, что ваш элемент будет находиться в td
с другим индексом в данной строке (вы не пытаетесь учестьизменчивость строк например ...). Таким образом, мы ищем разные отношения в целом;не требуется взаимосвязь между элементами;или динамически определять соответствующий индекс;или, может быть, даже их комбинация.
ИМО:
- Тот же URI, но альтернативный элемент на странице с более коротким, надеюсь, более надежным селектором;
- Другой URI XHR, где желаемый элемент связан с более надежным селектором, например, уникальным идентификатором;
- тег
script
с хорошей цепочкой для регулярных выражений (var yearBuilt = 1234;); - Позиционная стратегия, которая имеет меньше зависимостей и / или, исходя из опыта, более высокую вероятность стабильности во времени
Кроме того,
- Оптимизирована дляболее быстрый поиск
Я понимаю, что вышеизложенное является перефразировкой одной и той же общей идеи.
Глядя на соображения и две предоставленные ссылки:
Годbuild, связанный с MAIN AREA
, присутствует только в одном месте в документе. Примечание: я сохраняю предположение, что это следующая строка ниже соответствующей строки заголовка. Я не изучил достаточно ссылок, чтобы узнать, может ли значение этого года варьироваться в зависимости от области собственности, и вы не указали, что является обязательным. * В этом примере MAIN AREA
является первой частью, перечисленной с датой сборки.
Похоже, что страница не извлекает требуемое содержимое из дополнительных запросов, поэтому альтернативный источник не сразу очевиден. Похоже, что нет выделенного публичного API. функция поиска не предоставляет необходимой информации из своих запросов POST, а загружаемые файлы имеют задержку 3-4 месяца, в основном .txt и не предоставляют никаких реальных возможностей дляболее быстрая идентификация требуемой информации (на самом деле это было бы намного более трудоемким и менее надежным).
Это оставляет рассмотрение 4. Вам нужен способ найти правильный столбец в правой таблице. HTML имеет очень повторяющуюся структуру с несколькими хорошими «крючками». Вместо того, чтобы генерировать более хрупкий путь, зависящий от связей таблиц, вы разумно выбрали цикл за tr
с (поэтому он должен быть в таблице), ища строку заголовка ключа в tr
innerText
. Таким образом, исключается риск появления строки заголовка в другом столбце и / или другой таблице для более короткого пути прохождения и гибкости перехода к следующей строке, которая, как предполагается, содержит интересующие данные.
Пока что я думаю, что хороший выбор, хотя я лично предпочел бы ограничить поиск заголовками (th
), а затем перейти к родителю. Дополнительным преимуществом здесь является то, что я мог бы смягчить для вашей следующей части:
.Item(i).NextSibling.LastChild.PreviousSibling.innerText
Здесь вы ввели ненужное предположение / риск, что ваша колонка интересов всегда будет предпоследней. Хотя вы могли бы зациклить все заголовки и перейти к родительскому узлу, я рискнул бы ограничиться соответствующей таблицей путем поиска уникальной строки в заголовке панели и затем захватить таблицу next-sibling
перед проверкой заголовков. Он вводит IMO разумное предположение относительно отношения panel heading
к table
и panel
контента. Это тогда позволяет нам найти правильный индекс для заголовка на основе table
и использовать этот индекс для индексации в tds
следующей строки. Это смягчает положение, не являющееся предпоследним. Вы могли бы тогда искать дальнейшие оптимизации. Я пошел с установкой соответствий в переменные для более быстрой ссылки.
Несколько больше строк кода, но без большей сложности, большая безопасность по сравнению с соответствующим элементом, подходящие стратегии выхода и меньше циклов (из-за таргетинга на таблицу)несмотря на наличие двух циклических структур.
В целом ваша стратегия хорошая. Лично я бы обменял риск попытки получить правильную таблицу, предполагая, что правильный столбец является предпоследним. Я пошел с немного другими отношениями и динамически определяя правильный индекс. Я не совсем доволен решением, но оно кажется достаточно хорошим.
VBA:
Option Explicit
Public Sub GetInformation()
Dim Http As New XMLHTTP60, links, i&
Dim htmlDoc As New HTMLDocument, link
Dim Wb As Workbook, ws As Worksheet, r&
Set Wb = ThisWorkbook
Set ws = Wb.Worksheets("Sheet1")
links = Array( _
"https://esearch.brazoscad.org/Property/View/114414", _
"https://esearch.brazoscad.org/Property/View/117608" _
)
For Each link In links
With Http
.Open "GET", link, False
.send
htmlDoc.body.innerHTML = .responseText
End With
Dim panels As Object, table As Object, headers As Object
Set panels = htmlDoc.querySelectorAll(".panel-heading")
For i = 0 To panels.Length - 1
If InStr(panels.Item(i).innerText, "Property Improvement - Building") > 0 Then
Set table = panels.Item(i).NextSibling 'assumption on relationship
Exit For
End If
Next i
If Not table Is Nothing Then
Set headers = table.getElementsByTagName("th")
For i = 0 To headers.Length - 1
If InStr(headers(i).innerText, "Year Built") > 0 Then
r = r + 1: ws.Cells(r, 1) = headers(i).ParentNode.NextSibling.Children(i).innerText
Exit For
End If
Next
End If
Set htmlDoc = Nothing: Set table = Nothing
Next link
End Sub
Ссылки (VBE> Инструменты> Ссылки):
- Библиотека объектов Microsoft HTML
- Microsoft XML v (n) 'вашей версии