PDA

Показать полную графическую версию : Файлы большого объема html сохранить в csv, изменив структуру


Страниц : 1 [2]

YuS_2
02-04-2020, 08:10
героический человек »
Да чего там героического? :)
Как оказалось, глаза боятся, а руки делают... немного гугля, чуть-чуть ковыряния в доках и загашниках со скриптами, в итоге получилось rowspan-ы расковырять. На всё про все, час-полтора с перерывами...
Тем не менее, время обработки, всё равно, невменяемое, имхо. Для небольших таблиц сгодится, а для объемных - лучше таки воспользоваться чем-то другим...

v79italya
03-04-2020, 15:02
YuS_2, вчера запускал и не понимал что происходит и происходит ли что нибудь.
Сегодня еще раз запустил скрипт и ушел на полчаса. Через пол-часа смотрю, появился csv заполненный и txt, в котором узнал что парсило девять минут. Согласен что девять минут - это много.
Вывод такой: по любому парсеры быстро не работают :)

DJ Mogarych
03-04-2020, 16:16
Парсеры всякой неудобоваримой шляпы быстро не работают.

v79italya
03-04-2020, 16:51
Парсеры всякой неудобоваримой шляпы »дам ссылку на эту тему автору темы, от которой ноги растут. Пусть примет к сведению

YuS_2
05-04-2020, 13:34
Выдалось время одновременно с желанием понажимать кнопки... :)
Скрипт теперь "умеет" учитывать и rowspan-ы, и colspan-ы, плюс немного описания:
<#
.SYNOPSIS
Парсер таблиц .html

.Description
Скрипт парсит таблицы в формате HTML и записывает данные в формате CSV
- для каждой таблицы отдельный файл. Учитываются объединенные ячейки по
строкам и(или) по колонкам, ROWSPAN и COLSPAN.
Число колонок определяется автоматически, по тегам TH. Имена заголовков
присваиваются из значений элементов TH. При отсутствии тегов TH, число
колонок определяется по максимальному числу ячеек в строках, при этом
наименование заголовков будет формироваться автоматически, с префиксом
'H' и с номерами по порядку.
Размеры строк таблицы должны быть в пределах количества заголовков, т.е.
структура таблицы должна быть правильной, в том числе, с учетом ROWSPAN
и COLSPAN

.Parameter Infile
Обязательный: Указывается файл в котором необходимо распарсить таблицу(ы)

.Parameter Outfile
Необязательный: Имя для выходных файлов .csv. Указывается только имя, без
расширения. К имени будет добавлен номер таблицы по порядку.

.Example
.\script.ps1 -Infile 'test.html'

.Example
.\script.ps1 -Infile 'test.html' -Outfile 'd:\folder\name_file'

.Example
.\script.ps1 'test.html' 'name_file'

.Example
.\script.ps1

.Notes
Created By YuS
Version: 1.02
Date: 16/04/2020
Purpose/Change: Устранение багов кода. Исключение вложенных таблиц.
Version: 1.01
Date: 06/04/2020
Purpose/Change: Оптимизирован алгоритм чтения ячеек. Удален лишний цикл и
буферный счетчик.
Version: 1.00
Date: 05/04/2020
Purpose/Change: Первая версия

.Link
http://forum.oszone.net/showpost.php?p=2915883&postcount=25
#>

param (
#[parameter(Mandatory=$true)]
[string]$infile= 'test1.html',
[string]$outfile = 'table'
)

measure-command{

$html = new-object -com "HTMLFile"
$html.ihtmldocument2_write($(gc $infile -raw -enc utf8))
$tables = $html.getelementsbytagname("table")

# Исключение вложенных таблиц:
$tables|?{($_.getelementsbytagname('table')|%{$_}).count -eq 0}|%{$n=0}{
# Обработка всех элементов TABLE, включая вложенные (вероятна ошибка структуры таблицы).
# Необходимо закомментировать строку кода выше и раскомментировать эту:
#$tables|%{$n=0}{
$headers = @();$n++
$tr = $_|%{$_.getelementsbytagname("tr")}
if($headers = $tr|?{$_.firstchild().tagname -eq 'th'}|
%{$_.getelementsbytagname("th")}|select -exp innertext){
$headers = $headers.trim()
} else {
$headers = 1..([linq.parallelenumerable]::max(
[linq.parallelenumerable]::asparallel($tr.lastchild().cellindex)
)+1)|%{"H$_"}
}
$rowind = ,1 * $headers.count
$tr.where({$_.firstchild().tagname -eq 'td'})|%{
$row = $_.getelementsbytagname("td") | select innertext,rowspan,colspan
try {
$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){
$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){
$item.innertext.trim()
} else {$null}
if ($item.rowspan -gt 1){$rowind[$k] = $item.rowspan}
$k++
}
}
[pscustomobject]$str
} catch {
write-host Разметка заголовков не соответствует размерам строк -for red
write-host $_ -for cyan
}
} |export-csv $($outfile+"_"+$n+'.csv') -notype -enc utf8 -d ';'
}

} #|out-file time.txt -enc utf8
1. Оптимизировать алгоритм чтения ячеек не удалось, но кое-что оптимизировано.
2. Объемные таблицы, всё также обрабатываются не быстро.
3. Парсит все имеющиеся таблицы в dom-структуре.
Вдруг кому-то ещё пригодится...

v79italya
05-04-2020, 14:20
Парсеры всякой неудобоваримой шляпы »
Там этот парень еще тему открыл. Теперь парсит xmlhttps://www.planetaexcel.ru/forum/index.php?PAGE_NAME=read&FID=1&TID=127252&TITLE_SEO=127252-vygruzka-xml-slozhnaya-arkhitektura-v-excel-sredstvami-power-query&tags=utf-8&%252525252525253BFID=1

Sham
06-04-2020, 18:49
Сколько времени уходит на обработку файла? »
Мой jscript на регулярках за 24 секунды тот файл (14M). Зависит от процессора. Можно, конечно, и через com htmlfile, но это ж все 14М в DOM парсятся - сколько это по памяти будет?

v79italya
07-04-2020, 07:25
jscript на регулярках за 24 секунды тот файл (14M). Зависит от процессора. Можно, конечно, и через com htmlfile, но это ж все 14М в DOM парсятся - сколько это по памяти будет? »Не знаю сколько это по памяти)
У меня на нетбуке за 50 сек обработал. По моему, результат достаточно хороший.
Спасибо

YuS_2
28-04-2020, 22:43
Скрипт теперь "умеет" учитывать и rowspan-ы, и colspan-ы, плюс немного описания »
Ещё вариант скрипта для парсинга html
http://forum.oszone.net/post-2919294.html#post2919294
- работает быстрее, т.к. принцип работы основан на внешнем модуле, по типу парсинга XML.
- парсер не зависит от встроенного парсера html в powershell, который зависит от Internet Explorer
- будет работать в Powershell Core

v79italya
29-04-2020, 16:39
работает быстрее »очень хорошо. Спасибо




© OSzone.net 2001-2012