Powershell Invoke-WebRequest 和字符编码

问题描述 投票:0回答:3

我正在尝试通过他们的 Web API 从 Spotify 数据库获取信息。 但是,我面临重音元音(ä、ö、ü 等)的问题

让我们以铁斯托为例。 Spotify 的 API Browser 可以正确显示信息: https://developer.spotify.com/web-api/console/get-artist/?id=2o5jDhtHVPhrJdv3cEQ99Z

如果我使用

Invoke-Webrequest
进行 API 调用,我会得到

Ti??sto

如姓名:

function Get-Artist {
param($ArtistID = '2o5jDhtHVPhrJdv3cEQ99Z',
      $AccessToken = 'MyAccessToken')


$URI = "https://api.spotify.com/v1/artists/{0}" -f $ArtistID

$JSON = Invoke-WebRequest -Uri $URI -Headers @{"Authorization"= ('Bearer  ' + $AccessToken)} 
$JSON = $JSON | ConvertFrom-Json
return $JSON
}

我怎样才能得到正确的名字?

json powershell character-encoding spotify
3个回答
8
投票

更新PowerShell(核心)7.0+现在默认为UTF-8对于JSON,以及7.4+UTF-8一般在 HTTP 响应标头中缺少(有效的)

charset
属性,因此问题不再出现。


Jeroen Mostert,在对问题的评论中,很好地解释了问题:

问题是 Spotify(不明智地)没有返回它在标头中使用的编码。 PowerShell 通过假设 ISO-8859-1 遵守 [现已过时] 标准,但不幸的是该站点使用的是 UTF-8。 (PowerShell 应该忽略此处的标准并假定为 UTF-8,但我认为这就像,伙计。)更多详细信息here,以及后续票证。

不需要使用临时文件的解决方法

手动将响应的原始字节流解码为UTF-8:

$JSON = 
  [Text.Encoding]::UTF8.GetString(
    (Invoke-WebRequest -Uri $URI ...).RawContentStream.ToArray()
  )

或者,使用便捷功能

ConvertTo-BodyWithEncoding
;假设它已被定义(见下文),您可以更简单地使用以下内容:

# ConvertTo-BodyWithEncoding defaults to UTF-8.
$JSON = Invoke-WebRequest -Uri $URI ... | ConvertTo-BodyWithEncoding

便利功能
ConvertTo-BodyWithEncoding

注:

  • 函数手动解码构成给定响应正文的原始字节,默认为UTF-8,或者使用给定的编码,可以指定为

    [System.Text.Encoding]
    实例,code-page数字(例如
    1251
    ),或编码name(例如
    'utf-16le'
    )。

  • 该功能也 作为 麻省理工学院许可的 Gist 可用,并且只有后者会继续维护。假设你已经查看了链接的代码以确保它是安全的(我个人可以向你保证,但你应该经常检查),你可以直接如下定义它(关于如何使该功能在未来可用的说明将显示会话或将其转换为脚本):

    irm https://gist.github.com/mklement0/209a9506b8ba32246f95d1cc238d564d/raw/ConvertTo-BodyWithEncoding.ps1 | iex
    
function ConvertTo-BodyWithEncoding {

  [CmdletBinding(PositionalBinding=$false)]
  param(
    [Parameter(Mandatory, ValueFromPipeline)]
    [Microsoft.PowerShell.Commands.WebResponseObject] $InputObject,
    # The encoding to use; defaults to UTF-8
    [Parameter(Position=0)]
    $Encoding = [System.Text.Encoding]::Utf8
  )

  begin {
    if ($Encoding -isnot [System.Text.Encoding]) {
      try {
        $Encoding = [System.Text.Encoding]::GetEncoding($Encoding)
      }
      catch { 
        throw
      }
    }
  }

  process {
    $Encoding.GetString(
       $InputObject.RawContentStream.ToArray()
    )
  }

}

2
投票

问题已通过 Jeron Mostert 提供的解决方法解决。 您必须将它保存在一个文件中,并明确告诉 Powershell 它应该使用哪种编码。 这个解决方法对我有用,因为我的程序可以根据需要花费任何时间(关于读/写 IO)

function Invoke-SpotifyAPICall {
param($URI,
      $Header = $null,
      $Body = $null
      )

if($Header -eq $null) {
    Invoke-WebRequest -Uri $URI -Body $Body -OutFile ".\SpotifyAPICallResult.txt"    
} elseif($Body -eq $null) {
    Invoke-WebRequest -Uri $URI -Headers $Header -OutFile ".\SpotifyAPICallResult.txt"
}

$JSON = Get-Content ".\SpotifyAPICallResult.txt" -Encoding UTF8 -Raw | ConvertFrom-JSON
Remove-Item ".\SpotifyAPICallResult.txt" -Force
return $JSON

}

function Get-Artist {
    param($ArtistID = '2o5jDhtHVPhrJdv3cEQ99Z',
          $AccessToken = 'MyAccessToken')


    $URI = "https://api.spotify.com/v1/artists/{0}" -f $ArtistID

    return (Invoke-SpotifyAPICall -URI $URI -Header @{"Authorization"= ('Bearer  ' + $AccessToken)})
}


Get-Artist

0
投票

你试过类似的东西吗

$output = [System.Text.Encoding]::UTF8.GetString([System.Text.Encoding]::GetEncoding("iso-8859-1").GetBytes($JSON.Name))

我使用在某处找到的这一行将 API 返回文本转换为 UTF-8。我不太确定为什么需要这样做,因为我相信 JSON 应该是 UTF-8。

© www.soinside.com 2019 - 2024. All rights reserved.