Делал тут чтение с одного сайта, да и написал функцию... Дай, думаю, выложу - авось прямо в таком виде кому пригодится. Что умеет: умеет из файла или из html-фрагмента читать все находящиеся в нём таблицы, включая вложенные друг в друга. Итоговый результат - массив из таблиц значений. В ячейки таблиц пишется либо простое значение (обычно строковое), либо вложенная таблица значений, либо массив значений (если ещё были узлы, в т.ч. вложенные таблицы). Колонки - произвольного типа, их именование примитивное, "к1", "к2" и т.д. На правильность чтения вертикально объединённых ячеек (rowSpan) не рассчитана.
Прошу пардону, но раскраска исходников лежит вне досягаемости; потом разрисую, а копипастить уже и так можно.
Функция ПолучитьТаблицыЗначенийИзHTML(рИсходныйДокумент,мТаблиц=Неопределено)
Если мТаблиц=Неопределено Тогда // первый запуск, читаем сам документ
мТаблицИтого=Новый Массив;
рКодировка="UTF-8";
чтен=Новый ЧтениеHTML;
Если ТипЗнч(рИсходныйДокумент)=Тип("Строка") Тогда
// считаем, что передали строку HTML-кода (фрагмент)
чтен.УстановитьСтроку(рИсходныйДокумент,рКодировка);
ИначеЕсли ТипЗнч(рИсходныйДокумент)=Тип("Файл") Тогда
// считаем, что передали файл, проверенно существующий и читающийся оттуда, где он есть
чтен.ОткрытьФайл(рИсходныйДокумент.ПолноеИмя,рКодировка);
Иначе
Сообщить("Передан неверный аргумент: "+СокрЛП(рИсходныйДокумент)+", недопустимый тип!",СтатусСообщения.Важное);
Возврат мТаблицИтого;
КонецЕсли;
пострДОМ=Новый ПостроительDOM;
гдок=пострДОМ.Прочитать(чтен);
// запускаем уже рекурсивное чтение
ПолучитьТаблицыЗначенийИзHTML(гдок.ЭлементДокумента,мТаблицИтого);
// возвращаемся с верхнего уровня и вообще выходим
Возврат мТаблицИтого;
Иначе
// рекурсивный запуск, уже читается ДокументHTML
Для каждого элдок Из рИсходныйДокумент.ДочерниеУзлы Цикл
Если ТипЗнч(элдок)=Тип("ЭлементТаблицаHTML") Тогда // таблица, переходим непосредственно к её обработке
//===========================================================================================
Если элдок.ДочерниеУзлы.Количество()=1 Тогда
рЭлемент=элдок.ДочерниеУзлы.Элемент(0);
Если ТипЗнч(рЭлемент)=Тип("ЭлементHTML") Тогда
Если рЭлемент.ЕстьДочерниеУзлы() Тогда
// колонки добавляются по факту и по порядку
тзнч=Новый ТаблицаЗначений;
Для каждого рСтрока Из рЭлемент.ДочерниеУзлы Цикл
ОбработкаПрерыванияПользователя();
мЗначенийКолонок=Новый Массив;
Для каждого рЯчейка Из рСтрока.ДочерниеУзлы Цикл
ОбработкаПрерыванияПользователя();
Если ТипЗнч(рЯчейка)<>Тип("ЭлементЯчейкаТаблицыHTML") Тогда Продолжить КонецЕсли;
// в ячейке может быть как один элемент (тогда вносится простое значение), так и несколько (тогда их массив)
мЗначенийЯчейки=Новый Массив;
Для каждого рУзел Из рЯчейка.ДочерниеУзлы ЦИкл
Если ТипЗнч(рУзел)=Тип("ТекстDOM") Тогда
рЗначение=СокрЛП(рУзел.ТекстовоеСодержимое);
ИначеЕсли ТипЗнч(рУзел)=Тип("ЭлементТаблицаHTML") Тогда
// идём ещё глубже, обрабатывая таблицу через вызов обработки её родителя
мПодтаблиц=Новый Массив;
ПолучитьТаблицыЗначенийИзHTML(рУзел.РодительскийУзел,мПодтаблиц);
Если мПодтаблиц.Количество()=0 Тогда // ни одной таблицы не было
рЗначение=Неопределено;
ИначеЕсли мПодтаблиц.Количество()=1 Тогда
рЗначение=мПодтаблиц.Получить(0);
Иначе
рЗначение=мПодтаблиц; // прямо как массив и идёт
КонецЕсли;
Иначе
// идём ещё глубже в общем виде
мПодтаблиц=Новый Массив;
ПолучитьТаблицыЗначенийИзHTML(рУзел,мПодтаблиц);
Если мПодтаблиц.Количество()=0 Тогда // ни одной таблицы не было
рЗначение=Неопределено;
ИначеЕсли мПодтаблиц.Количество()=1 Тогда
рЗначение=мПодтаблиц.Получить(0);
Иначе
рЗначение=мПодтаблиц; // прямо как массив и идёт
КонецЕсли;
КонецЕсли;
Если ТипЗнч(рЗначение)=Тип("Массив") Тогда // перекидываем в итоговый
Для каждого знчм Из рЗначение Цикл мЗначенийЯчейки.Добавить(знчм) КонецЦикла;
Иначе // просто добавляем
мЗначенийЯчейки.Добавить(рЗначение);
КонецЕсли;
КонецЦикла;
рЗначениеЯчейки=?(мЗначенийЯчейки.Количество()=1,мЗначенийЯчейки[0],мЗначенийЯчейки);
// определяем, сколько колонок вмещает текущая ячейка (возможно объединение, тогда будет повтор значения)
квокол=?(рЯчейка.ОбъединениеКолонок=0,1,рЯчейка.ОбъединениеКолонок);
//Если рЯчейка.Атрибуты.Количество()<>0 Тогда // можно и так, оставил для общего интересу...
// рАтрОбъКол=рЯчейка.Атрибуты.ПолучитьИменованныйЭлемент("colspan"); // именно в нижнем регистре
// Если рАтрОбъКол<>Неопределено Тогда квокол=рАтрОбъКол.Значение КонецЕсли;
//КонецЕсли;
Для й=1 По квокол Цикл
мЗначенийКолонок.Добавить(рЗначениеЯчейки);
КонецЦикла;
КонецЦикла;
// теперь массив значений для строки таблицы значений готов
стротзнч=тзнч.Добавить();
Для ы=0 По мЗначенийКолонок.Количество()-1 Цикл
Если ы>тзнч.Колонки.Количество()-1 Тогда // по ситуации добавляем колонку произвольного типа
тзнч.Колонки.Добавить("к"+СокрЛП(ы));
КонецЕсли;
стротзнч[ы]=мЗначенийКолонок.Получить(ы);
КонецЦикла;
КонецЦикла;
Иначе
тзнч=Неопределено;
КонецЕсли; // если есть дочерние/нет дочерних
Иначе
тзнч=Неопределено;
КонецЕсли; // по типу исходного основного элемента таблицы
Иначе
тзнч=Неопределено;
КонецЕсли; // по количеству исходных узлов
//===========================================================================================
Если тзнч<>Неопределено Тогда мТаблиц.Добавить(тзнч) КонецЕсли;
Иначе
Если элдок.ЕстьДочерниеУзлы() Тогда
ПолучитьТаблицыЗначенийИзHTML(элдок,мТаблиц);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат Неопределено; // тут результат нас не интересует
КонецФункции