YuS 2
Silver Member | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Код: <# .SYNOPSIS Парсер таблиц .html .Description Скрипт парсит таблицы в формате HTML и записывает данные в формате CSV - для каждой таблицы отдельный файл. Учитываются объединенные ячейки по строкам и(или) по колонкам, ROWSPAN и COLSPAN. Число колонок определяется автоматически, по тегам TH. Имена заголовков присваиваются из значений элементов TH. При отсутствии тегов TH, число колонок определяется по максимальному числу ячеек в строках, при этом наименование заголовков будет формироваться автоматически, с префиксом 'H' и с номерами по порядку. Размеры строк таблицы должны быть в пределах количества заголовков, т.е. структура таблицы должна быть правильной, в том числе, с учетом ROWSPAN и COLSPAN Для парсинга используется внешний модуль PowerHTML. Внутри скрипта есть код для установки этого модуля - после установки можно удалить. .Parameter Uri Необязательный: Указывается web-ссылка на страницу, на которой необходимо распарсить таблицу(ы). .Parameter Infile Необязательный: Указывается локальный файл в котором необходимо распарсить таблицу(ы). Используется только в паре с переключателем Local .Parameter Outfile Необязательный: Имя для выходных файлов .csv. Указывается только имя, без расширения. К имени будет добавлен номер таблицы по порядку. .Parameter Encode Необязательный: Кодировка для чтения локального файла. По умолчанию - UTF8 .Parameter Enc1 Необязательный: Исходная кодировка для конвертации скачанного файла, если командлет inwoke-webrequest неправильно её определяет. По умолчанию - UTF8 .Parameter Enc2 Необязательный: Результирующая кодировка для конвертации скачанного файла, если командлет inwoke-webrequest неправильно её определяет. По умолчанию - iso-8859-1 .Parameter SelectTable Необязательный: Массив для указания номеров таблиц (начальный номер 0), которые требуется парсить. По умолчанию - все, не имеющие вложенных элем. TABLE .Parameter Local Переключатель: Используется для указания того, что для парсинга используется локальный файл. Требуется правильное указание наименования локального файла, можно с путем. .Example .\script.ps1 -Infile 'test.html' -local .Example .\script.ps1 -Infile 'test.html' -Outfile 'd:\folder\name_file' -local .Example .\script.ps1 -Uri 'https://www.example.com/test.html' -outfile 'name_file' .Example .\script.ps1 .Notes Created By YuS Version: 1.0 Date: 24/04/2020 Purpose/Change: Первая версия. .Link http://forum.oszone.net/showpost.php?p=2915883&postcount=25 http://forum.oszone.net/post-2918581.html#post2918581 https://stackoverflow.com/questions/60655737/how-to-parse-html-table-with-powershell-core-7 #> param ( #[parameter(Mandatory=$true)] [string]$uri = 'https://www.worldometers.info/coronavirus/', [string]$infile= 'test1.html', [string]$outfile = 'table_phtml', $Encode = 'utf8', $enc1 = 65001, $enc2 = 28591, [int[]]$SelectTable, [switch]$Local ) #---Эту секцию можно удалить после однократного запуска скрипта от имени админа ------------------ # Установка дополнительного модуля PowerHTML, для независимого парсинга HTML # Может потребоваться ручное подтверждение установки. if (!(get-module -list powerhtml)) { write-verbose "Installing PowerHTML module for the current user..." install-module powerhtml #-scope currentuser } #----------------------------------------------------------------------------------------- function convert ($from, $to){ begin{ $fenc = [text.encoding]::getencoding($from) $tenc = [text.encoding]::getencoding($to) } process{ $a = $tenc.getbytes($_) $fenc.getstring($a) } } if ($pscore = $psversiontable.psversion.major -gt 5){ import-module bitstransfer #if ($encode -eq 'utf8'){$encode = 'utf-8'} [net.servicepointmanager]::securityprotocol = 0 } else { [net.servicepointmanager]::securityprotocol = 'ssl3,tls,tls11,tls12' } if ($local) {$a = gc $infile -raw -enc $encode} else {$a = (iwr $uri).content} $content = if ($a -match [char]208){ if ($a -match 'windows-1251'){$enc1,$enc2 = 1251,1252} $a|convert $enc1 $enc2 } else {$a} $html = [net.webutility]::htmldecode($content)|convertfrom-html [array]$tables = $html.selectnodes('//table') # Исключение вложенных таблиц: $tables = $tables|?{$_.selectnodes('.//table') -eq $null} if ([string]::isnullorempty($selecttable)){ $number = 0..($tables.count-1) } else {$number = $selecttable} $tables[$number]|%{$n=0}{ $tr = $_.selectnodes('.//tr') if ($headers = $_.selectnodes('.//th')){ $headers = ($headers|select -exp innertext).trim() } else { $headers = 1..([linq.parallelenumerable]::max( [linq.parallelenumerable]::asparallel( ($tr|%{$_.selectnodes('.//td').count}) ) ))|%{"H$_"} } $rowind = ,1 * $headers.count $tr|?{$_.selectnodes('.//td') -ne $null}|%{ $row = $_.selectnodes('.//td')|%{ $attr = $_.attributes if ($attr){ $rowspan = ($attr|? name -eq 'rowspan').value $colspan = ($attr|? name -eq 'colspan').value } [pscustomobject]@{ 'InnerText' = $_.innertext 'RowSpan' = if($rowspan){[int]$rowspan} else {1} 'ColSpan' = if($colspan){[int]$colspan} else {1} } } $str = [ordered]@{} $k=0 foreach ($item in $row){ if ($rowind[$k] -gt 1){ while ($rowind[$k] -gt 1){ $str[$headers[$k]] = $null $rowind[$k] -= 1 $k++ } } if (($colspan = $item.colspan) -gt 1) { $str[$headers[$k]] = if($item.innertext){ switch -regex ($uri){ 'https://www\.worldometers\.info/coronavirus/' { $item.innertext.trim() -replace ',' -replace '\.',',' } default {$item.innertext.trim()} } } else {$null} if ($item.rowspan -gt 1){$rowind[$k] = $item.rowspan} $k++ while ($colspan -gt 1){ $str[$headers[$k]] = $null $colspan -=1 if ($rowind[$k] -gt 1){$rowind[$k]-=1} $k++ } } else { $str[$headers[$k]] = if($item.innertext){ switch -regex ($uri){ 'https://www\.worldometers\.info/coronavirus/' { $item.innertext.trim() -replace ',' -replace '\.',',' } default {$item.innertext.trim()} } } else {$null} if ($item.rowspan -gt 1){$rowind[$k] = $item.rowspan} $k++ } } [pscustomobject]$str } |export-csv $($outfile+"_"+$n+'_'+(get-date -f 'yyyyMMdd')+'.csv') -notype -enc $encode -d ';' $n++ } |
| Всего записей: 3218 | Зарегистр. 03-02-2009 | Отправлено: 12:19 25-04-2021 | Исправлено: YuS 2, 12:19 25-04-2021 |
|