От простого случая к сложному: как писать скрипты, работающие на разных документах
... А так же немного про поисковые запросы poisktenderov.ru
При написании скриптов важно обращать внимание на следующие моменты:
$s_route_number — номер маршрута$s_rasp_forward — расписание движенияif $b_res then или while $b_res или другую булеву переменную$s_rasp_forward только расписания. Улицы и остановки могут менять форму написания («ул.» → «улица»), что вызывает ложные срабатывания.Парсер должен уметь находить нужные параметры маршрута в документе, как правило, называющемся «Проект контракта».
Перед вами контракт города Кузнецка. Нас интересуют:
Как это выглядит в документе:
Маршрут №10А «ул. Каткова – ул. Минская»Начало выполнения работ – с даты заключения контракта.Окончание выполнения работ – 30.04.2026 года.Для извлечения дат используем команду find_between, так как начало и конец фраз фиксированы.
Пример текста:
Начало выполнения работ – с даты заключения контракта.
Окончание выполнения работ – 30.04.2026 года.
Код:
$s_contract_start = find_between("Начало выполнения работ – ", "")
$s_contract_finish = find_between("Окончание выполнения работ – ", " года.")
Функция find_between автоматически найдёт параграф и извлечёт текст между указанными строками.
Сайт умеет преобразовывать типовые фразы: "с даты заключения контракта.", "5 лет с даты заключения контракта" и некоторые другие в правильный формат дат
Строка с маршрутом в документе выглядит так:
Маршрут №7 «ул. Пригородная (кольцевой)»
Нам нужно отсечь начало и конец строки. Используем find_between.
Код:
$n_route_marker = find("Маршрут № ")
$s_route_number = find_between("Маршрут № ", " «", $n_route_marker)
$s_route_name = find_between("«", "»", $n_route_marker)
Наш маршрут кольцевой, и расписание есть только в одну сторону. Оно хранится в таблицах после заголовка:
7. Сводное расписание отправления транспортных средств из остановочных пунктов
И до следующего раздела:
8. Количество рейсов и пробег транспортных средств.
Находим таблицы:
$n_start = find("7. Сводное расписание отправления транспортных средств из остановочных пунктов ")
$n_end = find("8. Количество рейсов и пробег транспортных средств.")
$t_tables = find_all_tables($n_start, $n_end)
Чтобы совершить обход по каждой таблице, используется конструкция
foreach_table $t_current in $t_tables do enter_table $t_current ... # действия
Обрабатываем каждую таблицу:
$a_rasp = []
add_to_array $a_rasp, "Рабочие дни"
foreach_table $t_current in $t_tables do
enter_table $t_current
move_to_cell(3, 1)
$s_val = read_cell
add_to_array $a_rasp, $s_val
end
add_to_array $a_rasp, "\nВыходные дни"
foreach_table $t_current in $t_tables do
enter_table $t_current
move_to_cell(3, 2)
$s_val = read_cell
add_to_array $a_rasp, $s_val
end
$s_rasp_forward = join $a_rasp
$n_route_marker = find("Маршрут № ")
$s_route_number = find_between("Маршрут № ", " «", $n_route_marker)
$s_route_name = find_between("«", "»", $n_route_marker)
$s_contract_start = find_between("Начало выполнения работ – ", "")
$s_contract_finish = find_between("Окончание выполнения работ – ", " года.")
$n_sched_start = find("7. Сводное расписание отправления транспортных средств из остановочных пунктов ")
$n_sched_end = find("8. Количество рейсов и пробег транспортных средств.")
$t_tables = find_all_tables($n_sched_start, $n_sched_end)
$a_rasp = []
add_to_array $a_rasp, "Рабочие дни"
foreach_table $t_current in $t_tables do
enter_table $t_current
move_to_cell(3, 1)
$s_val = read_cell
add_to_array $a_rasp, $s_val
end
add_to_array $a_rasp, "\nВыходные дни"
foreach_table $t_current in $t_tables do
enter_table $t_current
move_to_cell(3, 2)
$s_val = read_cell
add_to_array $a_rasp, $s_val
end
$s_rasp_forward = join $a_rasp
return $s_route_number, $s_rasp_forward
Иногда встречается другой формат данных на сайте госзакупок. Система поддерживает DOC и ZIP. Преобразование этих форматов происходит автоматически, но для архива требуется указать имя файла, которое нужно прочитать из архива.
unpack - Команда, которая распаковывает архив
convert - Помогает сконвертировать DOC в DOCX
read "file_name". Имя документа - строка, указывается в кавычках. Или перечисление нескольких документов через запятую.
read_r "file_name". Вариант команды с регулярным выражением. Если используется регулярное выражение, парсятся все документы, попадающие под регулярное выражение.
Рассмотрим сложный случай: в документе несколько маршрутов. Например:
Маршрут №10А «ул. Каткова – ул. Минская» ... Маршрут №15 «Центр – Завод»
Вам нужно обработать сначала первый маршрут, затем второй и т.д.
Шаблон кода:
find("Маршрут № ")
if $b_res then
# Обработка первого маршрута
$s_route_number = find_between("Маршрут № ", " «", $n_route_marker)
# ... извлечение данных ...
add_to_array $a_all_routes, $s_route_number + ": " + $s_rasp_forward
end
find("Маршрут № ")
if $b_res then
# Обработка второго маршрута
$s_route_number = find_between("Маршрут № ", " «", $n_route_marker)
# ... извлечение данных ...
add_to_array $a_all_routes, $s_route_number + ": " + $s_rasp_forward
end
Каждый find("Маршрут № ") ищет следующее вхождение после предыдущего.
Если количество маршрутов заранее неизвестно, можно использовать цикл:
$a_all_routes = []
$n_last_found = 0
while $b_true do
$n_pos = find("Маршрут № ", $n_last_found)
if not $b_res then
break
end
# Устанавливаем старт для поиска внутри этого маршрута
set $n_last_found = $n_pos + 1
# Обработка одного маршрута
$s_route_number = find_between("Маршрут № ", " «", $n_pos)
# ... извлечение расписания ...
add_to_array $a_all_routes, $s_route_number + ": " + $s_rasp_forward
end
$s_result = join $a_all_routes with " | "
return $s_result
Такой подход универсален и работает при любом количестве маршрутов.