Парсеры XLS-прайсов


СОДЕРЖАНИЕ
  1. Описание
  2. Управление обработкой прайса
  3. Коллекция парсеров
  4. Генератор размещений

Описание

Прайсы принимающих туроператоров содержат цены, размещения (формулы размещения туристов разных форматов), названия номеров, пансионов (питания), отелей, курортов и другого рода информации. Данные, переносимые из них в базу отправляющего туроператора, являются основой для расчета конечных прайсов и онлайн-бронирования. Цены, указанные в прайсе принимающего туроператора, называются сырыми ценами. Особенность прайсов и вообще проблемы прайсов в том, что прайс каждого принимающего туроператора уникален в структуре данных, количестве и изощренности опечаток и степени видоизменяемости от года к году, от прайса к прайсу. Эта проблема решается в "Турпутевке", как и в других подобных программах, созданием неограниченного количества программ, содержащим код обработки только одного из форматов. Называются такие программы парсерами (от англ. parse - анализ, разбор). Программа не работает отдельно от модуля "Турпутевки", а является ее частью и используется только для преобразования уникального формата данных из файла прайса в набор данных одного формата, который в дальнейшем обрабатывается и заносится в базу.

Файлы прайсов должны иметь mime-тип application/vnd.ms-excel, в простонаречьи - быть XLS-файлами (формат MS Excel 97/2000/2003/2004). Формально поддерживается также CSV-формат, но на практике таких прайсов не встречается, главным образом из-за поголовного распространения MS Office, а также из-за того, что в CSV не поддерживается несколько листов. Другие форматы файлов не поддерживаются, хотя некоторые предельно непросвещенные принимающие туроператоры могут формировать прайсы в форматах PDF, DOC и прочих. Прайсы подобного рода придется вручную конвертировать в XLS.

Общая политика обработки прайсов: парсеры должны быть написаны таким образом, чтобы минимизировать количество изменений файла прайса вручную оператором. Рутина должна быть перенесена на плечи компьютера. Пусть из-за этого появятся лишние блоки кода и парсер станет более интеллектуальным. Отступать от этого правила стоит только тогда, когда в исходном прайсе явно нарушена логика, либо не хватает входных данных. Также бывают моменты, когда в угоду автоматизации приходится "балансировать на лезвии ножа" и работа кода становится неоднозначной, стремясь компенсировать сухость или ущербность исходной информации и может привести к ошибкам интерпретации. В таком случае стоит выбирать золотую середину между уверенностью распознавания и объемом предварительных ручных правок. Список самых часто встречаемых ошибок в исходных прайсах:

Сырой формат прайса
Прайс, цены в котором разбиты на составляющие. Типичный список составляющих: базовая цена за номер, доплата за детскую кровать, за взрослую кровать, за расширенный пансион, за обязательные ужины. Нетипичные: за вид на более живописную сторону, за кондиционер, и тд. Является более сложным в заливке и просчете, так как приходится генерировать места и калькулировать цены. Зачастую требует доработок в виде указания формулы максимального размещения, например: 1+1/2(2-6,6-12). Распространен среди мелких/молодых принимающих туроператоров или в странах, где отрасль туризма не так сильно развита. Особенность: цены прайса получаются более компактными в базе, главным образом за счет одной-двух строк с формулами размещения, вместо десятка и более строк, по одной на название размещения.

Готовый формат прайса
Прайс, в котором на один тип размещения в один момент времени указана только одна цена. Как правило, список возможных размещений немал (например в диапазоне от SINGLE до TRIPLE+2CHD(2-12) существует 9 различных размещений, каждое со своей ценой. Прайсы этого формата более легки для обработки и просчета, присущи странам с сильно развитым туризмом (Турция, Египет) и крупным туроператорам. Существуют промежуточные формы между сырым и готовым форматом, главным образом за счет доплат в праздники, иногда с другими доплатами. Цен для заливки в таком прайсе больше, чем в сыром виде. При просчете в выходном прайсе количество цен сырого и готового формата прайсов одинаково и зависит главным образом от количества туров, отелей, номеров в отелях, количества или формул размещений.

Типы листов прайса
В зависимости от формата прайса и количества данных, в нем может быть разное количество листов. Кроме листов с ценами, практически всегда существуют листы ссылок (в списке листов идут первыми). Если используется один лист на курорт, листов немного, но каждый из них имеет много информации - данные об отелях указаны один под другим. Второй вариант - каждый отель указан на отдельном листе. В этом случае листов с ценами гораздо больше и необходимость в листах ссылок сильнее. В этом случае в некоторых прайсах привязку отеля к курорту можно определить только по листам ссылок. Если парсер не поддерживает листы ссылок, их нужно пропускать при обработке.


Управление обработкой прайса

При обработке (заливке) прайса в базу возможно управлять объемом загружаемых данных (указывая диапазон обрабатываемых страниц), указывать дополнительные данные, которые будут занесены в базу в момент заливки и манипулировать стадиями обработки файла. Цены, залитые в справочник продукта в пакете, будут привязаны к пакету и продукту - для использования их в другом пакете придется продублировать операцию обработки прайса и заливки цен.

Окно настройки заливки данных доступно на странице ресурсов пакета, в рамках которого вы заливаете прайс. Кнопка открытия окна находится на поле конкретного продукта прайса (отель). Перед началом операции вы можете определить диапазон страниц, указать имя парсера, дополнительные жестко заданные значения полей (например, название страны, области, города, номера SPO и др.) и выбрать стадии, которые пройдет прайс во время обработки. Также можно включить сохранение файла журнала распознавания с полным и частичным журналированием. Будьте осторожны: журналирование потребляет ресурсы, и создает большие файлы журналов, особенно при полном журналировании.

Типичные стадии заливки файла в первый раз (в успешности заливки содержимого которого вы не уверены)

  1. Указываете все листы, содержащие полезную информацию. При этом, если парсер не поддерживает индексные страницы, вы должны исключить их из диапазона обработки (и наоборот). Указываете дополнительные значения (обычно страна, регион, иногда еще город(курорт), название компании-туроператора, номер СПО).
  2. Указываете, что пропускаете стадию заливки ("Только парсинг").
  3. Нажимаете "OK" и переходите на следующую страницу, где указываете загружаемый файл. Нажатие "Продолжить" на втором окне отправит файл на сервер и создаст отдельный процесс парсера файла.
  4. Обновляя страницу, следите за процентом обработки записей и сообщениями парсера. Если появилась ошибка, постарайтесь понять причину. Чаще всего причина в ошибочных данных какой-либо ячейки. При этом в сообщении указывается адрес ячейки и название листа в файле прайса.
  5. Если сообщения об ошибке достаточно для решения проблемы, решите ее, изменив файл прайса, и начните всю последовательность действий сначала, до тех пор, пока не исправите все ошибки, возникающие на стадии обработки записей. При этом осознавайте, что заливки в базу не произойдет - вы лишь подготавливаете файл к конечной, успешной обработке. Рекомендуется записывать все сделанные в файле исправления, чтобы не делать повторную работу с многократными заливками в случае присылания прайса с обновленными ценами.
  6. Если текст ошибки неясен:
    1. Запомните название листа прайса, указанного в ошибке (указан самым последним), откройте файл прайса и запомните номер этого листа в файле.
    2. Откройте снова окно настройки загрузки прайса в продукте. Кроме пункта "Только парсинг" выберите также два пункта "отладка" и "поверхностно".
    3. Укажите диапазон листов, а не все листы и укажите единственный номер - номер проблемного листа в обоих ячейках "с" и "по".
    4. Повторите операцию заливки файла и дождитесь повторения ошибки в сообщении парсера.
    5. Щелкните ссылку "Журнал парсера: предпросмотр".
    6. Визуально проанализируйте ошибку - перед вами будет схематичное изображение листа прайса с ячейками, окрашенными в разные цвета. Цвет, отличный от белого, означает, что ячейка была распознана, как несущая полезную информацию. Разные типы данных окрашивают ячейку в тот или иной цвет. В случае, если ячейка содержит сразу несколько разных типов информации, она будет окрашена только в один цвет. Если полученной информации достаточно для решения проблемы, исправьте файл прайса и повторите обработку без отладки и без вставки данных, пытаясь в итоге завершить чтение файла парсером без ошибок.
    7. Если информации недостаточно или если парсер не поддерживает цветовую отладку, повторите обработку этого листа, сняв галку в пункте "поверхностно". В этом случае размер файла журнала вырастет, а также увеличится объем доступной для анализа информации (используйте раскрывающиеся блоки текста в каждой строке).
    8. Если проблема до сих пор не может быть решенной, прекратите эксперименты и обратитесь к разработчику парсера, передав ему текст ошибки из сообщения парсера и файл прайса.
  7. Если все ошибки исправлены, либо их не возникло, либо вы загодя уверены в успешности операции импорта (обрабатывали этот же файл ранее) - вы можете не использовать пункт "только парсинг". При этом непосредственно после чтения файла и обработки записей посредством парсера, программа перейдет ко вставке всех найденных записей в базу (справочники). При этом также могут возникнуть ошибки. Если ошибки возникли:
    1. Откройте содержимое справочника отелей и укажите в фильтре значения, которые однозначно найдут строки, которые уже успели вставиться до возникновения ошибки. Если база относительно пуста, можно в качестве фильтра указать страну или область. Если существуют другие пакеты, содержащие данные тех же регионов, более верным будет фильтр по ID продукта (поле pid). Удалите все найденные строки.
    2. Затем перейдите на страницу управления справочником "Номера отелей" и выберите и выполните пункт "Очистить потерянное рекурсивно". Эти два шага вернут базу к первоначальному состоянию до начала неудачной операции вставки и вы сможете начать операцию заново.
    3. Исправьте ошибку, если поняли причину её возникновения или обратитесь к разработчику прайса, передав ему текст ошибки из сообщения при вставке и файл прайса.
  8. Если удалось пройти все стадии и залить все цены, переходите к следующим операциям настройки турпакета.

Коллекция парсеров


Генератор размещений

Генератор размещений используется при создании пакетов и только для сырых прайсов. На основе формулы максимального размещения в номере при создании прайса необходимо сгенерировать перечень всех возможных размещений и высчитать цену для каждого из них. На этапе просчета цен и создания выходных прайсов этим занимается функция генерации размещений (ts_price->GenPlace). Формула пишется вручную оператором, готовящим прайс, для каждого номера отеля на основе прочтения политик, указанных в рамках отеля. Некоторые парсеры автоматически создают формулу, если это позволяет смысловая конструкция прайса. Правила, прописанные отелем, зачастую неясны, осознаются косвенно из перечня имеющихся цен за дополнительные детские и взрослые места и тд. В этом случае от оператора требуется знание типовых вариантов и особенностей страны, иногда размера номера или любых других вещей. В конечном счете нужно добиться четких, непротиворечивых формул размещения, из которых генератор без накладок сгенерирует только действительно возможные размещения. В случае двоякой цены за размещение - например, при размещении ребенка на одной кровати с родителем и на отдельной, за более дорогую плату, предпочтение должно отдаваться большей цене, так как легче сделать скидку, чем объяснять, почему Вы продаете по заниженным ценам, а затем требуете неочевидных доплат или (что чаще всего, доплачиваете сами). Для реализации этого может понадобиться удаление строк с более низкими ценами, если этого не умеет сам парсер.

Описание формулы: "число предоплаченных взрослых"+"число дополнительно вмещающихся за отдельную плату взрослых или детей". В случае детей необходимо сразу за числом указывать в круглых скобках диапазон (или несколько диапазонов через любой разделитель) возрастов, например: (0-6|6-12). В случае, если в номер может быть подселен ЛИБО один взрослый за отдельную плату, ЛИБО ребенок (или два), указывать нужно и тех и других через символ косой черты, например: 2+1/2(2-12). В случае верхней планки заселяемости номера название размещения (не формула!) будет выглядеть как: DOUBLE+EXB, либо DOUBLE+2CHD(2-12). C предельными размещениями, равно как и с базовыми (без дополнительных мест) не существует особых сложностей. Проблемы могут возникнуть при генерации промежуточных размещений - именно они могут нарушить реальную политику отеля в отношении какого-либо номера и это может привести к конфликтной ситуации.

Что такое промежуточные размещения? Это размещения, создаваемые для заполнения всех мыслимых вариантов между минимально возможным (базовым) и максимально возможным размещениями. В качестве варьируемых элементов выступают дополнительные взрослые места и детские места (зачастую разных возрастов), как дополнительные, так и заменяющие предоплаченные взрослые. Парсер, обрабатывающий файл, должен иметь представление об особенностях страны или того набора отелей, который указан в прайсе и при необходимости регулировать генерацию размещений указанием политики отеля. Также политику размещений отеля можно редактировать вручную. Чтобы проще донести специфику, можно прибегнуть к примеру:

ФормулаРазмещениеТипЦенообразованиеКоды блокировки
2+1/1(0-6|6-12)DBLБазовоебазовая
DBL PPПсевдо-размещениебазовая/кол-во местnopp
DBL+EXBМаксимальноебазовая+доп.взрослая
DBL+CHD(0-6)Максимальноебазовая+доп.детская1
DBL+CHD(6-12)Максимальноебазовая+доп.детская2
SGL+CHD(0-6)
SGL+CHD(6-12)
Промежуточныебазоваяgenchd2ex, nogenchd
SGL+2CHD(0-6)
SGL+2CHD(0-6|6-12)
SGL+2CHD(6-12)
Промежуточные с доп. местом для 2го ребенкабазовая+доп.детскиеnogenchd
3+1TRIPLEБазовоебазовая
DBL PPПсевдо-размещениебазовая/кол-во местnopp
QUADМаксимальноебазовая+доп.взрослая
TRIPLE+CHD(2-12)Максимальноебазовая+доп.детскаяnogenchd
SINGLE+2CHD(2-12)
DOUBLE+1CHD(2-12)
Промежуточныебазоваяgenchd2ex,nogenchd
SINGLE+3CHD(2-12)
DOUBLE+2CHD(2-12)
Промежуточные с доп. местом для последнего ребенкабазовая+доп.детскаяnogenchd
1+1(0-10)SINGLEБазовое
SGL+CHD(0-10)Максимальноебазовая+доп.детская

Как видно из примеров, все промежуточные размещения могут быть заблокированы политикой отеля. Политика прописывается в виде перечня кодов, разделенных точкой с запятой (без пробелов!), например: nopp;genchd2ex и указывается в соответствующем столбце в справочнике отеля. Чаще всего эту политику указывает сам парсер, переносящий данные в базу из прайса.

Исключение накладок. Часто в прайсах дается две цены или даже три за один номер для каждого возможного базового размещения. Например, для одного номера отдельно указана цена за SINGLE и отдельно за DOUBLE. При этом также могут присутствать цены за extra bed (доп. взрослый) и за extra child (доп. ребенок). В таком случае формулу размещения нужно указывать напротив каждой базовой цены. Чаще всего для цены SINGLE формула будет равна просто "1", для цены DOUBLE - формула, предусматривающая все остальные возможные варианты. В случае, если в прайсе оговаривается отдельная цена для размещения, например, ребенка в каждом из вариантов цен (например, при одном взрослом цена за ребенка одна, при двух - другая) - то после отражения возможности размещения ребенка в SINGLE возникает возможность накладки размещений. Такимо образом, размещение SINGLE+CHD возможно как на основании базовой цены SINGLE (с доплатой за ребенка), так и на основании базовой цены DOUBLE (без доплаты), что приведет к дублированию размещений в прайсе с разными ценами и будет являться явной ошибкой. В этом случае парсер или оператор должен регулировать возможность создания промежуточных конфликтных размещений кодами блокировки в политике отеля.

Пример прайса, который может привести к накладке (желтым отмечены поля, добавленные оператором для парсера после прочтения имеющихся скидок отеля):
Hotel Name IBEROSTAR ALBATROS Region CAVTAT

Category Board Currency

4* HB EUR
Periods 09.05.201129.05.201126.06.201118.09.2011
29.05.201126.06.201118.09.201102.10.2011

Room typeSTANDARD ROOM max
DOUBLE981301501302+1/1(0-7|7-12)
SINGLE7498113981+1(0-7|7-12)

Discounts:
Child 0 -1,99 with 2 adults without bed 100%
Child 0 - 6,99 with 2 adults on extra bed 100%
Child 7 – 11,99 with 2 adults on extra bed 50%
Child 0 - 6,99 with 1 adult on basic bed 50%
Child 7 – 11,99 with 1 adult on basic bed 30%
Adult on extra bed 20%

В этом примере оператор или парсер должен добавить в политику отеля код genchd2ex. Этот код исключит генерирование размещений SINGLE+CHD(0-7) (98 у.е.) и SINGLE+CHD(7-12) (98 у.е.) на основе базовой цены DOUBLE, что конфликтовало по ценам бы с такими же размещениями, но с другими ценами (74+37 у.е. и 74+22 у.е.) на основе базовой цены SINGLE.

Перечень существующих политик и их расшифровка

На данный момент политики размещения поддерживаются на уровне справочника отеля (поле policies) и на уровне справочника номера (поле policy). Политики на уровне номера важнее, чем политики на уровне отеля. Также столбец политик номера может отсутствовать (это не критично для работы системы). Политики на уровне номеров гибче (для каждого номера своя политика), но их тяжелее указывать, чем отельные. Рекомендуется столбец политик номеров заводить на уровне справочника привязки пакетов к номерам отелей, а не в самих номерах - так как от года к году (от пакета к пакету) политика номеров может меняться и несовпадение политик может задублировать номера в отелях при заливке новых прайсов.

Политики на уровне отелей можно указывать прямо в XLS-прайсе (чтобы не настраивать отели в базе после каждой заливки. Для этого в любой строке листа в первой ячейке нужно указать строку вида:
+policies=policy1:value1;policy2:value2


<< Оглавление | Наверх…