Skip to content

Instantly share code, notes, and snippets.

@Ascor8522
Created November 27, 2025 23:50
Show Gist options
  • Select an option

  • Save Ascor8522/2e14c05654ca1c58ff8e1877f04b7dca to your computer and use it in GitHub Desktop.

Select an option

Save Ascor8522/2e14c05654ca1c58ff8e1877f04b7dca to your computer and use it in GitHub Desktop.
Script to download goalie statistics from hockeylinea.fmp.es for a given league and save them into an Excel workbook, with one worksheet per game.
# hockey.ps1
#
# DESCRIPTION:
# ============
# Script to download goalie statistics from hockeylinea.fmp.es for a given league
# and save them into an Excel workbook, with one worksheet per game.
#
# COPYRIGHT AND LICENSE:
# ======================
# Copyright (c) 2025 Ascor8522
# Licensed under the MIT License
#
# REQUIREMENTS:
# =============
# - PowerShell 7+
# - Excel installed on the machine running the script
$lang = "es"
$idc = "4169" # <---- League ID (4169 for "LIGA SENIOR 3 GRUPO A 2025/26")
$idm = "2"
Function Fetch-Games($Idc, $Idm) {
$url = "https://www.server2.sidgad.es/fmp/fmp_cal_idc_${Idc}_${Idm}.php"
$regex = '<i class="fa fa-search game_report" idp="(?<idp>\d+?)" idc="(?<idc>\d+?)" idm="(?<idm>\d+?)"'
return Invoke-WebRequest -Uri $url `
-Method POST `
-Headers @{ Origin = "http://www.hockeylinea.fmp.es" } `
-Body @{ idc = $Idc; site_lang = $lang }
| Select-Object -ExpandProperty Content
| % { [regex]::Matches($_, $regex) }
| ForEach-Object {
[PSCustomObject]@{
idp = $_.Groups['idp'].Value
idc = $_.Groups['idc'].Value
idm = $_.Groups['idm'].Value
}
}
}
Function Fetch-GameDetails($Idp, $Idm, $Idc) {
$url = "https://www.server2.sidgad.es/fmp/fmp_gr_${Idp}_${Idm}.php"
$tablesRegex = '<table width="100%" class="competiciones_tabla_basic"(?:.|\n)+?<\/table>'
$teams = Invoke-WebRequest -Uri $url `
-Method POST `
-Headers @{ Origin = "http://www.hockeylinea.fmp.es" } `
-Body @{ idm = $Idm; idc = $Idc; idp = $Idp; tab = "tab_ficha_resumen"; site_lang = $lang } `
| Select-Object -ExpandProperty Content
| % { [regex]::Matches($_, $tablesRegex) }
| % { $_.Value }
| ForEach-Object {
$fixRegex = [regex]'(?<=<th>\s*(?:<span class="lang_label lang_..">.+?<\/span>\s*)+)(?=\s*<th>)'
$fixed = $_
| % { $_ -replace '<img(.*?)\/?>', '<img$1></img>' }
| % { $fixRegex.replace($_, '</th>', 1) }
$xml = $fixed
| % { [xml]($_) }
$nameXpath = '//table/thead/tr/td/div[@class="nombre_equipo_thickbox_stats"]'
$teamName = $xml.SelectNodes($nameXpath) | ForEach-Object { $_.'#text' }
$goaliesXpath = '//table/tbody/tr[preceding-sibling::thead[1] = //table/tbody/thead[1]]'
$goalies = $xml.SelectNodes($goaliesXpath) | ForEach-Object {
[PSCustomObject]@{
Number = $_.td[0].'#text' | Select-Object -First 1 | % { $_.Trim() }
Position = $_.td[1].'#text' | Select-Object -First 1 | % { $_.Trim() }
Flag = $_.td[2].img.'@src' | Select-Object -First 1 | % { $_.Trim() }
LastName = $_.td[3].a.'#text' | Select-Object -First 1 | % { $_.Trim() }
FirstName = $_.td[3].a.span.'#text' | Select-Object -First 1 | % { $_.Trim() }
GA = $_.td[4].'#text' | Select-Object -First 1 | % { $_.Trim() }
TR = $_.td[5].'#text' | Select-Object -First 1 | % { $_.Trim() }
Pct = $_.td[6].'#text' | Select-Object -First 1 | % { $_.Trim() }
PIM = $_.td[7].'#text' | Select-Object -First 1 | % { $_.Trim() }
Min = $_.td[8].'#text' | Select-Object -First 1 | % { $_.Trim() }
Pm = $_.td[9].'#text' | Select-Object -First 1 | % { $_.Trim() }
}
}
[PSCustomObject]@{
TeamName = $teamName
Goalies = $goalies
}
}
[PSCustomObject]@{
Idp = $Idp
Idm = $Idm
Idc = $Idc
Teams = $teams
}
}
Function Insert-MatchInWorkbook($Workbook, $Game) {
$ws = $Workbook.Worksheets.Add([System.Type]::Missing, $Workbook.Worksheets[$Workbook.Worksheets.Count], 1, -4167)
$ws.Name = "Game_$($Game.Idp)_$($Game.Teams[0].TeamName -replace '\s','_')_vs_$($Game.Teams[1].TeamName -replace '\s','_')"
| % { $_.Substring(0, [Math]::Min(31, $_.Length)) }
$row = 1
$Game.Teams | ForEach-Object {
$ws.Cells.Item($row, 1).Value2 = $_.TeamName -join ' '
$row++
$col = 1
$headers = @("N°", "Pos.", "Flag", "Last Name", "First Name", "GA", "TR", "%", "PIM", "Min", "+/-")
$widths = @(20, 5, 5, 20, 15, 5, 5, 8, 5, 5, 5)
$headers | ForEach-Object {
$ws.Cells.Item($row, $col).Value2 = $_
$ws.Columns.Item($col).ColumnWidth = $widths[$col - 1]
$col++
}
$row++
$_.Goalies | ForEach-Object {
$ws.Cells.Item($row, 1).Value2 = $_.Number
$ws.Cells.Item($row, 2).Value2 = $_.Position
$ws.Cells.Item($row, 3).Value2 = $_.Flag
$ws.Cells.Item($row, 4).Value2 = $_.LastName
$ws.Cells.Item($row, 5).Value2 = $_.FirstName
$ws.Cells.Item($row, 6).Value2 = $_.GA
$ws.Cells.Item($row, 7).Value2 = $_.TR
$ws.Cells.Item($row, 8).Value2 = $_.Pct
$ws.Cells.Item($row, 9).Value2 = $_.PIM
$ws.Cells.Item($row, 10).Value2 = $_.Min
$ws.Cells.Item($row, 11).Value2 = $_.Pm
$row++
}
}
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ws) | Out-Null
}
Function Main() {
$ErrorActionPreference = "Stop"
$PSNativeCommandUseErrorActionPreference = $true
$xl = New-Object -ComObject Excel.Application
$wb = $xl.Workbooks.Add()
$games = Fetch-Games $idc $idm
foreach ($game in $games) {
$gameDetails = Fetch-GameDetails $game.idp $game.idm $game.idc
Insert-MatchInWorkbook $wb $gameDetails
}
$wb.Worksheets.Item(1).Delete()
$wb.Worksheets.Item(1).Activate()
$savePath = ".\goalie_stats_of_league_$idc`_on_$((Get-Date).ToString("yyyy-MM-dd-a\t_HH-mm-ss")).xlsx"
'' | Out-File $savePath
$xl.DisplayAlerts = $false
$wb.SaveAs((Resolve-Path $savePath).Path)
$wb.Close()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($wb) | Out-Null
$xl.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl) | Out-Null
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
}
Main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment