【问题标题】:How to parse HTML table with Powershell Core 7?如何使用 Powershell Core 7 解析 HTML 表格?
【发布时间】:2020-03-12 14:03:11
【问题描述】:

我有以下代码:

    $html = New-Object -ComObject "HTMLFile"
    $source = Get-Content -Path $FilePath -Raw
    try
    {
        $html.IHTMLDocument2_write($source) 2> $null
    }
    catch
    {
        $encoded = [Text.Encoding]::Unicode.GetBytes($source)
        $html.write($encoded)
    }
    $t = $html.getElementsByTagName("table") | Where-Object {
        $cells = $_.tBodies[0].rows[0].cells
        $cells[0].innerText -eq "Name" -and
        $cells[1].innerText -eq "Description" -and
        $cells[2].innerText -eq "Default Value" -and
        $cells[3].innerText -eq "Release"
    }

代码在 Windows Powershell 5.1 上运行良好,但在 Powershell Core 7 上 $_.tBodies[0].rows 返回 null。

那么,如何在 PS 7 中访问 HTML 表格的行?

【问题讨论】:

标签: html powershell powershell-core


【解决方案1】:

PowerShell [Core] 从 7.2.1 开始,是否带有内置的 HTML 解析器

您必须依赖第三方解决方案,例如包装HTML Agility PackPowerHTML module

对象模型与 Windows PowerShell 中基于 Internet Explorer 的模型不同;它类似于标准System.Xml.XmlDocument提供的XML DOM类型[1];请参阅the documentation 和下面的示例代码。

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

# Create a sample HTML file with a table with 2 columns.
Get-Item $HOME | Select-Object Name, Mode | ConvertTo-Html > sample.html

# Parse the HTML file into an HTML DOM.
$htmlDom = ConvertFrom-Html -Path sample.html

# Find a specific table by its column names, using an XPath
# query to iterate over all tables.
$table = $htmlDom.SelectNodes('//table') | Where-Object {
  $headerRow = $_.Element('tr') # or $tbl.Elements('tr')[0]
  # Filter by column names
  $headerRow.ChildNodes[0].InnerText -eq 'Name' -and 
    $headerRow.ChildNodes[1].InnerText -eq 'Mode'
}

# Print the table's HTML text.
$table.InnerHtml

# Extract the first data row's first column value.
# Note: @(...) is required around .Elements() for indexing to work.
@($table.Elements('tr'))[1].ChildNodes[0].InnerText

[1] 特别是通过.SelectSingleNode().SelectNodes() 方法支持XPath 查询,通过.ChildNodes 集合公开子节点,并提供.InnerHtml / .OuterHtml / .InnerText特性。代替支持子元素名称的 indexer,提供了方法 .Element(<name>).Elements(<name>)

【讨论】:

    【解决方案2】:

    我使用上面的答案作为我的解决方案。我安装了 PowerHTML。 我想从https://www.dicomlibrary.com/dicom/dicom-tags/ 中提取数据表并进行转换。

    从这里:

    <tr><td>(0002,0000)</td><td>UL</td><td>File Meta Information Group Length</td><td></td></tr>

    到这里:

    {"00020000", "ULFile Meta Information Group Length"}

    $page = Invoke-WebRequest https://www.dicomlibrary.com/dicom/dicom-tags/
    $htmldom = ConvertFrom-Html $page
    $table = $htmlDom.SelectNodes('//table') | Where-Object {
      $headerRow = $_.Element('tr') # or $tbl.Elements('tr')[0]
      # Filter by column names
      $headerRow.ChildNodes[0].InnerText -eq 'Tag' 
    }
    
    foreach ($row in $table.SelectNodes('tr'))
     {$a = $row.SelectSingleNode('td[1]').innerText.Trim()  -replace "`n|`r|\s+", " " -replace "\(",'{"' -replace ",","" -replace "\)",'",'
     $c = $row.SelectSingleNode('td[3]').innerText.Trim() -replace "`n|`r|\s+", " "
     $b=$row.seletSingleNode('td[2]').innerText.Trim() -replace "`n|`r|\s+", ""; $c = '"'+$b+$c+'"},'
     $row = New-Object -TypeName psobject
         $row | Add-Member -MemberType NoteProperty -Name Tag -Value $a
         $row | Add-Member -MemberType NoteProperty -Name Value -Value $c
    
         [array]$data += $row
    }
    
    $data | Out-File c:\scripts\dd.txt

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-14
      • 2011-01-04
      • 2011-07-20
      • 2011-09-08
      • 2016-09-20
      • 2019-11-10
      相关资源
      最近更新 更多