如何使用 PowerShell 解析网站的 HTML

How to parse the HTML of a website with PowerShell

提问人:David Trevor 提问时间:6/28/2019 最后编辑:David Trevor 更新时间:11/15/2023 访问量:38650

问:

我正在尝试检索有关网站的一些信息,我想查找特定的标签/类,然后返回包含的文本值(innerHTML)。这就是我到目前为止所拥有的

$request = Invoke-WebRequest -Uri $url -UseBasicParsing
$HTML = New-Object -Com "HTMLFile"
$src = $request.RawContent
$HTML.write($src)


foreach ($obj in $HTML.all) { 
    $obj.getElementsByClassName('some-class-name') 
}

我认为将 HTML 转换为 HTML 对象存在问题,因为当我尝试“选择对象”它们时,我会看到很多未定义的属性和空结果。

那么,在花了两天时间之后,我应该如何使用 Powershell 解析 HTML?

因此,既然使用正则表达式解析 HTML 是一个很大的禁忌,那么我该怎么做呢?似乎没有任何效果。

PowerShell DOM HTML 解析

评论

1赞 Maximilian Burszley 6/28/2019
查看 HTMLAgility nuget 包。它是原始的 .NET,但在处理 HTML 时会对你有很大帮助。

答:

9赞 David Trevor 10/8/2019 #1

由于没有其他人发布答案,我设法使用以下代码获得了一个有效的解决方案:

$request = Invoke-WebRequest -Uri $URL -UseBasicParsing
$HTML = New-Object -Com "HTMLFile"
[string]$htmlBody = $request.Content
$HTML.write([ref]$htmlBody)
$filter = $HTML.getElementsByClassName($htmlClassName)

对于某些 URL,我遇到 $filter 变量在为其他 URL 填充时为空。总而言之,这可能适用于您的情况,但似乎 Powershell 不是进行更复杂解析的方法。

评论

4赞 KUTlime 6/2/2021
我要指出的是,此解决方案仅适用于部署在 Windows 上的 PowerShell。COM 对象通常在 PowerShell v7.x.x 中不可用。
0赞 stackprotector 9/21/2021
如果引发错误,请使用此答案.write()
5赞 Ben R 2/11/2020 #2

在 2020 年,使用 PowerShell 5+ 可以做到这一点:

$searchClass = "banana" <# in this example we parse all elements of class "banana" but you can use any class name you wish #>
$myURI = "url.com" <# replace url.com with any website you want to scrape from #>

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 <# using TLS 1.2 is vitally important #>
$req = Invoke-Webrequest -URI $myURI
$req.ParsedHtml.getElementsByClassName($searchClass) | %{Write-Host $_.innerhtml}

#for extra credit we can parse all the links
$req.ParsedHtml.getElementsByTagName('a') | %{Write-Host $_.href} #outputs all the links

评论

0赞 silicontrip 7/23/2020
当我查找 IHTMLDocument2 时,我只看到 2 个方法,写入和关闭。getElementsByClassName 在哪里声明?如何找到可用于 ParsedHtml 属性的其他方法?
15赞 Chris 10/1/2020
不幸的是,在 2020 年的 PowerShell 7.0.3 中,这不起作用。响应 (“$req”) 将没有名为 ParsedHtml 的属性。这是仅限 powershell 经典的功能吗?
0赞 Ben R 3/11/2021
尝试$req = Invoke-Webrequest -URI $myURI -usebasicparsing
2赞 N. I. 11/18/2021
@BenR “此参数已被弃用。从 PowerShell 6.0.0 开始,所有 Web 请求仅使用基本分析。包含此参数只是为了向后兼容,任何使用它都不会影响 cmdlet 的操作。
1赞 mklement0 11/9/2023 #3

如果可以选择安装第三方模块

  • PSParseHTML 模块包装 HTML Agility Pack[1]AngleSharp .NET 库(NuGet 包);您可以使用任何一个进行 HTML 解析;后者需要作为选择加入;至于它们各自的 DOM(对象模型):-Engine AngleSharp

    • 默认情况下使用的 HTML Agility Pack 提供了一个对象模型,该模型类似于标准 System.Xml.XmlDocument NET 类型 () 提供的 XML DOM。有关其使用示例,请参阅此答案[xml]

    • AngleSharp 需要通过 选择加入,它建立在官方的 W3C 规范之上,因此提供了 Web 浏览器中可用的 HTML DOM。值得注意的是,这意味着 its 和 方法可以与通常的 CSS 选择器一起使用,如下所示。-Engine AngleSharp.QuerySelector().QuerySelectorAll()

  • 使用此模块的另一个优点是它不仅是跨版本的,而且是跨平台的;也就是说,您可以在 Windows PowerShell 和 PowerShell (Core) 7+ 中使用它,也可以通过后者在类 Unix 平台上使用它。


一个基于 AngleSharp 引擎独立示例,它解析英语维基百科的主页并提取属性值为 :classvector-menu-content-list

# Install the PSParseHTML module on demand
If (-not (Get-Module -ErrorAction Ignore -ListAvailable PSParseHTML)) {
  Write-Verbose "Installing PSParseHTML module for the current user..."
  Install-Module -Scope CurrentUser PSParseHTML -ErrorAction Stop
}

# Using the AngleSharp engine, parse the home page of the English Wikipedia
# into an HTML DOM.
$htmlDom = ConvertFrom-Html -Engine AngleSharp -Url https://en.wikipedia.org

# Extract all HTML elements with a 'class' attribute value of 'vector-menu-content-list'
# and output their text content (.TextContent)
$htmlDom.QuerySelectorAll('.vector-menu-content-list').TextContent