I still use Windows PowerShell 5.1 for my personal research scripts, mostly because it's already on every machine I touch. When I added Instagram lookups through HikerAPI, the API itself was the easy part: one x-access-key header and plain JSON back. The work was in three small helpers that made the responses behave in 5.1. None of them is specific to HikerAPI, so here they are.
1. Decode the body as UTF-8 yourself
Invoke-RestMethod in 5.1 falls back to ISO-8859-1 when the server doesn't send a charset, and Instagram captions are full of emoji and accented letters. They arrived mangled until I read the raw bytes:
function GetJson($url, $headers) {
$r = Invoke-WebRequest -UseBasicParsing -Uri $url -Headers $headers
$ms = New-Object IO.MemoryStream; $r.RawContentStream.CopyTo($ms)
(([Text.Encoding]::UTF8.GetString($ms.ToArray())) | ConvertFrom-Json) | ForEach-Object { $_ }
}
The ForEach-Object { $_ } at the end is the second fix hiding in there: ConvertFrom-Json in 5.1 hands back a JSON array as a single object, so .Count and loops quietly misbehave. Piping it through unrolls the list.
2. Read a field by more than one name
Once in a while a field came back with a slightly different name. The one I caught was 1ltaken_at where I expected taken_at. Instead of trusting one exact key, I read fields through a helper that accepts a few candidates and a short prefix:
function Campo($o, [string[]]$nomes) {
if ($null -eq $o) { return $null }
foreach ($n in $nomes) {
$p = $o.PSObject.Properties | Where-Object { $_.Name -eq $n -or $_.Name -match ('^\w{0,3}' + [regex]::Escape($n) + '$') } | Select-Object -First 1
if ($p -and $null -ne $p.Value) { return $p.Value }
}
return $null
}
Campo $post 'taken_at' now finds the value either way, and Campo $post 'id', 'pk' covers endpoints that name the same thing differently.
3. Walk nested results instead of guessing the path
Hashtag results come grouped in sections and layouts rather than as a flat list. Rather than hard-coding that shape, I walk the whole object and keep anything that looks like a post:
function Midias($o, $acc) {
if ($null -eq $o -or $o -is [string] -or $o -is [ValueType]) { return }
if ($o -is [Array]) { foreach ($x in $o) { Midias $x $acc }; return }
$nomes = $o.PSObject.Properties.Name
if ($nomes -contains 'code' -and ($nomes -contains 'like_count' -or $nomes -contains 'media_type')) { $acc.Add($o); return }
foreach ($p in $o.PSObject.Properties) { Midias $p.Value $acc }
}
If the layout changes tomorrow, this keeps working as long as a post still looks like a post.
About the API itself
I'm happy with HikerAPI for this. You get 100 free requests when you sign up. The entry tier is $0.02 per request, and /sys/balance is free, so my script prints what each call cost. The quirks above took an afternoon to sort out, and since then it has been the dependable part of the pipeline.
(The helper names are Portuguese because that's what the rest of my scripts use: Campo means field and Midias means media.)
Comments
Join the discussionNo comments yet. Be the first to comment.