【问题标题】:How to change multiple headers in a table using Powershell如何使用 Powershell 更改表格中的多个标题
【发布时间】:2020-01-21 19:39:48
【问题描述】:

我正在尝试更改从this site 拉出Team Statistics 表的代码中的多个标题名称 我不确定在我的代码中手动更改它们的位置。

例如,我尝试在添加“TEAM”标题的行中手动将标题 8、GF 更改为 GFPG,但出现错误:

使用“2”参数调用“添加”的异常:“项目已添加。字典中的键:'GF' 正在添加的键:'GF'” 在 C:\NHLScraper.ps1:32 字符:5 + $objHash.Add($headers[$j],$rowdata[$j])

我的代码:

$url = "https://www.hockey-reference.com/leagues/NHL_2020.html"

#getting the data
$data = Invoke-WebRequest $url

#grab the third table
$table = $data.ParsedHtml.getElementsByTagName("table") | Select -skip 2 | Select -First 1


#get the rows of the Team Statistics table
$rows = $table.rows

#get table headers
$headers = $rows.item(1).children | select -ExpandProperty InnerText

#count the number of rows
$NumOfRows = $rows | Measure-Object

#Manually injecting TEAM header
$headers = @($headers[0];'TEAM';$headers[1..($headers.Length-1)])

#enumerate the remaining rows (we need to skip the header row) and create a custom object
$out = for ($i=2;$i -lt $NumofRows.Count;$i++) {
 #define an empty hashtable
 $objHash=[ordered]@{}
 #getting the child rows
 $rowdata = $rows.item($i).children | select -ExpandProperty InnerText 
 for ($j=0;$j -lt $headers.count;$j++) {
    #add each row of data to the hash table using the correlated table header value
    $objHash.Add($headers[$j],$rowdata[$j])
  }

  #turn the hashtable into a custom object
  [pscustomobject]$objHash
}

$out | Select TEAM,AvAge,GP,W,L,OL,PTS,PTS%,GF,GA,SOW,SOL,SRS,SOS,TG/G,EVGF,EVGA,PP,PPO,PP%,PPA,PPOA,PK%,SH,SHA,PIM/G,oPIM/G,S,S%,SA,SV%,SO -SkipLast 1 | Export-Csv -Path "C:\$((Get-Date).ToString("'NHL Stats' yyyy-MM-dd")).csv" -NoTypeInformation

【问题讨论】:

  • 我刚刚运行了你的代码几次,第 9 个元素是 GFPG 并且没有错误。你确定你得到那个错误吗?是否有可能在每次循环时都没有创建新的哈希表?
  • 你在哪里改的?在我实施了你的解决方案之后,我仍然不知道在哪里将 GF 更改为 GFPG

标签: windows powershell web-scraping html-parsing powershell-4.0


【解决方案1】:

您可以添加条件来检查密钥是否已添加,如果已添加,则更新或忽略它,

if (!$objHash.Contains(headers[$j]))
    $objHash.Add($headers[$j],$rowdata[$j])

else
    $objHash[$headers[$j]] = $rowdata[$j] # Overwrite values

但是看了几遍你的代码,这没有意义,

$out = for ($i=2;$i -lt $NumofRows.Count;$i++) {
 #define an empty hashtable
 $objHash=[ordered]@{}         # Overwritten each loop???
 #getting the child rows
 $rowdata = $rows.item($i).children | select -ExpandProperty InnerText 
 for ($j=0;$j -lt $headers.count;$j++) {
    #add each row of data to the hash table using the correlated table header value
    $objHash.Add($headers[$j],$rowdata[$j])   # Dictionary cannot have duplicate keys
  }

  #turn the hashtable into a custom object
  [pscustomobject]$objHash    # what do you do with this?
}

您循环了 x 次,每次都覆盖 $objHash。唯一会返回的是在最后一个循环中创建的内容。

建议的解决方案

您可以使用另一个变量来跟踪您正在创建的所有哈希表,同时确保不会插入会引发异常的重复键。

# If you want to change the header value from GF to GFPG, you can do that in the place you have defined $headers


#get table headers
$headers = $rows.item(1).children | select -ExpandProperty InnerText
$headers = $headers | % { if ($_ -eq "GF") { "GFPG" }  else { $_ }} 

#count the number of rows
$NumOfRows = $rows | Measure-Object

#Manually injecting TEAM header
$headers = @($headers[0];'TEAM';$headers[1..($headers.Length-1)])

#enumerate the remaining rows (we need to skip the header row) and create a custom object
$allData = @{}
$out = for ($i=2;$i -lt $NumofRows.Count;$i++) {
 #define an empty hashtable
 $objHash=[ordered]@{}
 #getting the child rows
 $rowdata = $rows.item($i).children | select -ExpandProperty InnerText 
 for ($j=0;$j -lt $headers.count;$j++) {
    #add each row of data to the hash table using the correlated table header value
    $objHash[$headers[$j]] = $rowdata[$j]        
  }

  #turn the hashtable into a custom object
  [pscustomobject]$objHash
  $allData.Add($i, $objHash)
}

我使用$AllData 和i 作为键来存储每个结果,以便以后访问。

【讨论】:

  • 如果我在上面添加您的解决方案,我可以在哪里更改所需的标题?
  • 只是添加到上面的解决方案中,如果您不需要基于密钥已经存在的事实执行操作,您实际上可以使用$objHash."$($headers[$j])" = $rowdata[$j]。该语句将添加或编辑现有项目而无需额外检查。
  • @SagePourpre 你知道我可以在哪里更改标题吗?添加 Jawad 的新变量后仍然坚持这一点
  • 我刚刚更新了代码以包含可以更新 Headers 变量的位置。您可以使用 replace 方法将 GF 替换为 GFPG。 @jackrabbit 让我知道这是否有帮助
  • @SagePourpre 将您的建议纳入关键分配
猜你喜欢
  • 1970-01-01
  • 2016-12-23
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多