【问题标题】:How to extract specific tables from html file using native powershell commands?如何使用本机 powershell 命令从 html 文件中提取特定表?
【发布时间】:2014-11-14 10:30:09
【问题描述】:

我使用 PAL 工具 (https://pal.codeplex.com/) 从 Windows 中的 perfmon 日志生成 HTML 报告。在 PAL 处理来自 perfmon 的 .blg 文件后,它会将信息转储到 HTML 文档中,该文档包含带有关于系统如何执行的各种数据点的表格。我目前正在编写一个脚本,该脚本查看所有 HTML 文件的目录内容,并对所有 HTML 文件执行获取内容。

我想做的是为具有不同行数的特定表刮取这个 get-content blob 的转储。是否可以使用本机 powershell cmdlet 来查找特定表,计算每个表中有多少行,并转储 just 所需的表和表行?

这是我尝试抓取的表格格式示例:

<H3>Overall Counter Instance Statistics</H3>
<TABLE ID="table6" BORDER=1 CELLPADDING=2>
<TR><TH><B>Condition</B></TH><TH><B>\LogicalDisk(*)\Disk Transfers/sec</B></TH><TH><B>Min</B></TH><TH><B>Avg</B></TH><TH><B>Max</B></TH><TH><B>Hourly Trend</B></TH><TH><B>Std Deviation</B></TH><TH><B>10% of Outliers Removed</B></TH><TH><B>20% of Outliers Removed</B></TH><TH><B>30% of Outliers Removed</B></TH></TR>
<TR><TD>No Thresholds</TD><TD>MACHINENAME/C:</TD><TD>1</TD><TD>7</TD><TD>310</TD><TD>0</TD><TD>11</TD><TD>5</TD><TD>5</TD><TD>5</TD></TR>
<TR><TD>No Thresholds</TD><TD>MACHINENAME/D:</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD></TR>
<TR><TD>No Thresholds</TD><TD>MACHINENAME/E:</TD><TD>0</TD><TD>24</TD><TD>164</TD><TD>-1</TD><TD>11</TD><TD>22</TD><TD>21</TD><TD>20</TD></TR>
<TR><TD>No Thresholds</TD><TD>MACHINENAME/HarddiskVolume5</TD><TD>0</TD><TD>0</TD><TD>2</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD></TR>
<TR><TD>No Thresholds</TD><TD>MACHINENAME/L:</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD><TD>0</TD></TR>
<TR><TD>No Thresholds</TD><TD>MACHINENAME/T:</TD><TD>0</TD><TD>7</TD><TD>430</TD><TD>0</TD><TD>21</TD><TD>3</TD><TD>2</TD><TD>2</TD></TR>
</TABLE>

所有输出文件的表 ID 是恒定的,但表行数不是。任何帮助表示赞赏!

【问题讨论】:

  • 您需要表格中的特定行还是整个表格?
  • 我需要整张桌子。我也不需要一张桌子。我将抓取几个表格并将信息汇总到一个 CSV 文件中,以便轻松导入 Excel。
  • 你认为“本机命令”是什么? PS 没有任何可以解析 HTML 文件 的常用 cmdlet,但如果您安装了 IE,您可以通过 New-Object -ComObject InternetExplorer.Application 进行 IE 自动化。然后你可以使用GetElementById .NET method获取表格。
  • 您也许可以使用正则表达式找到开始的&lt;table id= 标记,然后找到结束的&lt;/table&gt; 标记。转储正则表达式的结果。您要转储的所有表都将使用相同的ID="table6" 吗?
  • @Alexander:我认为“本机命令”是 powershell 中“开箱即用”的命令,无需导入任何第三方模块。最终,这是对一大堆结构化文本的解析练习,所以我想这将涉及一种在 blob 中定位所需表的方法,一个计算表中有多少行的循环,一种回显过滤后的方法结果。然后我将对结果运行 ConvertTo-CSV。

标签: html powershell csv cmdlets


【解决方案1】:

好的,这没有经过全面测试,但适用于带有 IE11 的 PS 2.0 中的示例表:

# Parsing HTML with IE.
$oIE = New-Object -ComObject InternetExplorer.Application
$oIE.Navigate("file.html")
$oHtmlDoc = $oIE.Document

# Getting table by ID.
$oTable = $oHtmlDoc.getElementByID("table6")

# Extracting table rows as a collection.
$oTbody = $oTable.childNodes | Where-Object { $_.tagName -eq "tbody" }
$cTrs = $oTbody.childNodes | Where-Object { $_.tagName -eq "tr" }

# Creating a collection of table headers.
$cThs = $cTrs[0].childNodes | Where-Object { $_.tagName -eq "th" }
$cHeaders = @()
foreach ($oTh in $cThs) {
    $cHeaders += `
        ($oTh.childNodes | Where-Object { $_.tagName -eq "b" }).innerHTML
}

# Converting rows to a collection of PS objects exportable to CSV.
$cCsv = @()
foreach ($oTr in $cTrs) {
    $cTds = $oTr.childNodes | Where-Object { $_.tagName -eq "td" }
    # Skipping the first row (headers).
    if ([String]::IsNullOrEmpty($cTds)) { continue }
    $oRow = New-Object PSObject
    for ($i = 0; $i -lt $cHeaders.Count; $i++) {
        $oRow | Add-Member -MemberType NoteProperty -Name $cHeaders[$i] `
            -Value $cTds[$i].innerHTML
    }
    $cCsv += $oRow
}

# Closing IE.
$oIE.Quit()

# Exporting CSV.
$cCsv | Export-Csv -Path "file.csv" -NoTypeInformation

老实说,我的目标不是优化代码。这只是一个示例,说明如何在 PS 中使用 DOM 对象并将它们转换为 PS 对象。

【讨论】:

  • 谢谢!你帮了大忙!我刚刚使用我的一个本地 HTML 文件对此进行了测试,它解析了表 6 中的信息。我将破解您的脚本,看看是否可以让它输出其他表的内容。
【解决方案2】:

我看到你接受了一个答案,但我想我也会在这里添加一个 RegEx 解决方案。这个不需要 COM 对象,我很确定应该是 PSv2 友好的。

$Path = 'C:\Path\To\File.html'
[regex]$regex = "(?s)<TABLE ID=.*?</TABLE>"
$tables = $regex.matches((GC C:\Temp\test.txt -raw)).groups.value
ForEach($String in $tables){
    $table = $string.split("`n")
    $CurTable = @()
    $CurTableName = ([regex]'TABLE ID="([^"]*)"').matches($table[0]).groups[1].value
    $CurTable += ($table[1] -replace "</B></TH><TH><B>",",") -replace "</?(TR|TH|B)>"
    $CurTable += $table[2..($table.count-2)]|ForEach{$_ -replace "</TD><TD>","," -replace "</?T(D|R)>"}
    $CurTable | convertfrom-csv | export-csv "C:\Path\To\Output\$CurTableName.csv" -notype
}

这应该为找到的每个表输出一个 CSV 文件。例如 table6.csv、table9.csv 等。如果您想为每个 HTML 文件输出 CSV,您可以将整个内容包装在 ForEach 循环中,例如:

ForEach($File in (Get-ChildItem "$Path\*.html")){
    Insert above code here
}

您需要修改$tables = 行,使其为GC $file.fullname,以便在迭代时加载每个文件。

然后只需将 Export-Csv 修改为:

$CurTable | convertfrom-csv | export-csv "C:\Path\To\Output\$($File.BaseName)\$CurTableName.csv" -notype

因此,如果您的 Server01.html 中包含 3 个表,您将获得一个名为 Server01 的文件夹,其中包含 3 个 CSV 文件,每个表一个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 2017-03-21
    • 2022-06-23
    • 1970-01-01
    • 2018-08-18
    • 1970-01-01
    • 2023-03-12
    • 2019-01-23
    相关资源
    最近更新 更多