簡體   English   中英

如何使用Powershell將HTML表格轉換為具有相同結構的CSV文件

[英]How to Convert HTML table to CSV file with same structure with powershell

使用Powershell,我可以使用此表-$ URL =“ http://example.com/yyy.htm ” $ OutputFile =“ $ env:temp \\ tempfile.xml”

# reading website data:
$data = Invoke-WebRequest -Uri $URL 

# get the first table found on the website and write it to disk:
@($data.ParsedHtml.getElementsByTagName("table"))[0].OuterHTML | Set-Content -Path $OutputFile

現在,我希望將此表轉換為CSV ...我該怎么做?

表格范例-

Datacenter | FirstDNS | SecondDNS | ThirdDNS | FourthDNS
-----------------------------------------------------------
NewYork    | 1.1.1.1  | 2.2.2.2   |3.3.3.3   | 4.4.4.4
India      | 1.2.3.4  | 3.2.6.5   |8.2.3.7   | 8.3.66.1

這是一個將HTML表轉換為PSObjects的解決方案,您可以將其通過管道傳輸到Export-CSV或執行所需的任何操作。 請注意:這不是一個干凈的解決方案; 它僅適用於簡單場景,但是存在很多問題:

  • 無法處理特殊字符(  除外,要使其正常工作,您需要根據需要向DocType的實體映射添加新的定義)
  • 無法應付colspanrowspan ; 假定所有表的每一行中的列數與標題中的列數相同(如果列數比標題多,可以進行調整以防止錯誤;但是在這種情況下,您仍然可能會出現對齊錯誤)。
  • 我在轉換為XML之前清理HTML的技術是使用正則表達式而不是解析庫。 因此,那里很可能會有意想不到的問題。
function ConvertFrom-HtmlTableRow {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $htmlTableRow
        ,
        [Parameter(Mandatory = $false, ValueFromPipeline = $false)]
        $headers
        ,
        [Parameter(Mandatory = $false, ValueFromPipeline = $false)]
        [switch]$isHeader

    )
    process {
        $cols = $htmlTableRow | select -expandproperty td
        if($isHeader.IsPresent) {
            0..($cols.Count - 1) | %{$x=$cols[$_] | out-string; if(($x) -and ($x.Trim() -gt [string]::Empty)) {$x} else {("Column_{0:0000}" -f $_)}} #clean the headers to ensure each col has a name        
        } else {
            $colCount = ($cols | Measure-Object).Count - 1
            $result = new-object -TypeName PSObject
            0..$colCount | %{
                $colName = if($headers[$_]){$headers[$_]}else{("Column_{0:00000} -f $_")} #in case we have more columns than headers 
                $colValue = $cols[$_]
                $result | Add-Member NoteProperty $colName $colValue
            } 
            write-output $result
        }
    }
}

function ConvertFrom-HtmlTable {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $htmlTable
    )
    process {
        #currently only very basic <table><tr><td>...</td></tr></table> structure supported
        #could be improved to better understand tbody, th, nested tables, etc

        #$htmlTable.childNodes | ?{ $_.tagName -eq 'tr' } | ConvertFrom-HtmlTableRow

        #remove anything tags that aren't td or tr (simplifies our parsing of the data
        [xml]$cleanedHtml = ("<!DOCTYPE doctypeName [<!ENTITY nbsp '&#160;'>]><root>{0}</root>" -f ($htmlTable | select -ExpandProperty innerHTML | %{(($_ | out-string) -replace '(</?t[rdh])[^>]*(/?>)|(?:<[^>]*>)','$1$2') -replace '(</?)(?:th)([^>]*/?>)','$1td$2'})) 
        [string[]]$headers = $cleanedHtml.root.tr | select -first 1 | ConvertFrom-HtmlTableRow -isHeader
        if ($headers.Count -gt 0) {
            $cleanedHtml.root.tr | select -skip 1 | ConvertFrom-HtmlTableRow -Headers $headers | select $headers
        }
    }
}

clear-host

[System.Uri]$url = 'https://en.wikipedia.org/wiki/List_of_countries_by_carbon_dioxide_emissions' 
$rqst = Invoke-WebRequest $url 
$rqst.ParsedHtml.getElementsByTagName('table') | ConvertFrom-HtmlTable 

僅供參考:我還在CodeReview上發布了此代碼的早期版本,因此請檢查那里是否有人提出任何好的改進。

使用Tee-Object輸出文件,然后您可以通過管道將其導出到Export-CSV:

@($data.ParsedHtml.getElementsByTagName("table"))[0].OuterHTML | Tee-Object -FilePath $OutputFile | Export-CSV $env:temp\tempfile.csv -notype

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM