если .querySelector () поддерживает: nth-of-type (), что не так с .querySelector ("table: nth-of-type (2) tr"), когда я использую его в скрипте, который не работает
Он поддерживается при использовании Microsoft Internet Controls
для автоматизации браузера (IE8 +) и создается HTMLDocument
с 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;);
- Позиционная стратегия, которая имеет меньше зависимостей и / или, исходя из опыта, более высокую вероятность стабильности во времени.
Кроме того,
- Оптимизирован для более быстрого поиска
Я понимаю, что вышесказанное является повторным хешированием той же общей идеи.
Глядя на соображения и две предоставленные ссылки:
Год постройки, связанный с MAIN AREA
, присутствует только в одном месте в документе. Примечание: я сохраняю предположение, что это следующая строка после соответствующей строки заголовка. Я не изучил достаточно ссылок, чтобы узнать, может ли стоимость в этом году варьироваться в зависимости от площади собственности, и вы не указали, что является обязательным. В этом примере MAIN AREA
отображается как первая часть с датой сборки.
Страница, похоже, не извлекает необходимый контент из дополнительных запросов, поэтому альтернативный источник не сразу очевиден. Похоже, что нет специального общедоступного API. функция поиска не предоставляет необходимую информацию из своих запросов POST, а загружаемые файлы имеют задержку на 3-4 месяца, в основном это .txt и не предлагают никаких реальных возможностей для более быстрое определение необходимой информации (на самом деле было бы намного труднее и менее надежно).
Остается рассмотреть вопрос 4. Вам нужен способ найти правый столбец в правой таблице. HTML имеет очень повторяющуюся структуру с несколькими хорошими «зацепками». Вместо того, чтобы создавать более хрупкий путь, зависящий от взаимосвязей таблиц, вы разумно выбрали цикл по tr
s (следовательно, должен быть в таблице), ища строку заголовка ключа в tr
innerText
. Таким образом, риск появления строки заголовка в другом столбце и / или другой таблице был снижен в пользу более короткого пути обхода и гибкости для перехода к следующей строке, которая, как предполагается, содержит интересующие данные.
Пока что я считаю хороший выбор, хотя лично я бы предпочел ограничить поиск заголовками (th
), а затем перейти к родительскому. Дополнительным преимуществом здесь является то, что я мог бы смягчить вашу следующую часть:
.Item(i).NextSibling.LastChild.PreviousSibling.innerText
Здесь вы создали ненужное предположение / риск, что интересующая вас колонка всегда будет предпоследней. Хотя вы могли бы зациклить все заголовки и перейти к родительскому узлу, я бы рискнул ограничиться соответствующей таблицей, ища уникальную строку в заголовке панели, а затем возьму таблицу next-sibling
перед исследованием заголовков. Он вводит ИМО разумное предположение относительно отношения 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) 'ваша версия
person
QHarr
schedule
09.11.2019