Я пытаюсь сделать некоторые веб-скребки с помощью PowerShell, так как я недавно обнаружил, что это можно сделать без особых проблем.Использование querySelectorAll в объекте mshtml.HTMLDocumentClass в PowerShell вызывает сбой
Хорошая отправная точка, чтобы просто принести HTML, используйте Get-Member, и посмотреть, что я могу сделать, оттуда, например, так:
$html = Invoke-WebRequest "https://www.google.com"
$html.ParsedHtml | Get-Member
методы доступны мне для извлечения конкретных элементов, по всей видимости быть следующим:
getElementById()
getElementsByName()
getElementsByTagName()
Например, я могу получить первый тег IMG в документе следующим образом:
$html.ParsedHtml.getElementsByTagName("img")[0]
Однако после того, как делать некоторые дополнительные исследования в том, могу ли я использовать CSS селекторы или XPath, я обнаружил, что есть приватные методы доступны, так как мы только с помощью HTML объекта Document documented here:
querySelector()
querySelectorAll()
Так вместо того, чтобы делать:
$html.ParsedHtml.getElementsByTagName("img")[0]
я могу сделать:
$html.ParsedHtml.querySelector("img")
Так что я ожидал, чтобы быть в состоянии сделать:
$html.ParsedHtml.querySelectorAll("img")
... для того, чтобы получить все элементы IMG. Вся документация, которую я нашел, и поиск в Google, я сделал, поддерживает это. Тем не менее, во всем моем тестировании эта функция выдает вызывающий процесс и сообщает код исключения кучи коррупции в журнале событий (0xc0000374).
Я использую PowerShell 5 на Windows 10 x64. Я пробовал это в Win10 x64 VM, которая является чистой сборкой и просто исправлена. Я также попробовал это в Win7 x64, обновленном до PowerShell 5. Я не пробовал его ни перед чем до PowerShell 5, поскольку все наши системы здесь обновлены, но я, вероятно, когда-нибудь успею создать новую виртуальную виртуальную машину для тестирования ,
Неужели кто-нибудь сталкивается с этим вопросом раньше? Все мои исследования до сих пор являются тупиком. Существуют ли альтернативы запросуSelectorAll? Мне нужно очистить страницы, которые будут иметь предсказуемые наборы тегов внутри непредсказуемых макетов, и, возможно, нет идентификаторов или классов, назначенных для тегов, поэтому я хочу иметь возможность использовать селектор, который допускает структуру/вложенность/подстановочные знаки.
P.S. Я также пробовал использовать объект InternetExplorer.Application COM в PowerShell, результат тот же, за исключением того, что PowerShell рушится сбой Internet Explorer. Это было на самом деле мой оригинальный подход, вот код:
# create browser object
$ie = New-Object -ComObject InternetExplorer.Application
# make browser visible for debugging, otherwise this isn't necessary for function
$ie.Visible = $true
# browse to page
$ie.Navigate("https://www.google.com")
# wait till browser is not busy
Do { Start-Sleep -m 100 } Until (!$ie.Busy)
# this works
$ie.document.getElementsByTagName("img")[0]
# this works as well
$ie.document.querySelector("img")
# blow it up
$ie.document.querySelectorAll("img")
# we wanna quit the process, but since we blew it up we don't really make it here
$ie.Quit()
Надежда Я не нарушая никаких правил и этот пост имеет смысл и имеет отношение, спасибо.
UPDATE
я тестировал ранее PowerShell версии. v2-v4 с использованием метода InternetExplorer.Application COM. v3-4 с использованием метода Invoke-WebRequest, v2 не поддерживает его.
Спасибо за ваш ответ, это, безусловно, проницательно. Я смог следовать вашему предложению, и я могу получить доступ к элементам '$ NodeList' после того, как они заполнены массивом' $ PsNodeList'. Однако я заметил, что это работает только при использовании 'Invoke-WebRequest'. Если вы используете «New-Object -ComObject InternetExplorer.Application», он бросает меня «Исключение из HRESULT: 0x80020101' :( Я пытаюсь создать интерактивный скребок, поэтому, если возможно, я предпочел бы использовать IE ComObject. Продолжайте исследовать. На данный момент, по крайней мере, приятно знать, что есть способ обхода решения «Invoke-WebRequest». – TheKojukinator
Хмм. Я не смог заставить код IE работать «работает», пока не использовал 32-разрядную версию Powershell Но мои самые лучшие усилия не могли заставить его вернуть результат '.item()'. oops hit enter ... still edit Я действительно получил атаку действительно умников и сделал что-то классное, но не смог верните его в Powershell до сих пор. Я сказал: «Вверните его, у нас есть DOM, давайте вставим JavaScript». И поэтому этот код Powershell вводит '
Решение @ midnightfreddie отлично работало для меня раньше, но теперь оно выдает
Exception from HRESULT: 0x80020101
при вызове$NodeList.item($i)
.Я нашел следующий обходной путь:
Это один работает для
New-Object -ComObject InternetExplorer.Application
, а также.источник
2016-12-06 18:30:58