Журнал, прогресс и безопасный повтор на Python
ctx.log(message, context, level) добавляет сообщение в журнал прогона; progress(done, total, label, percent) показывает этап; metric(name, value) записывает числовую метрику. Они доступны и при пробе, и при рабочем запуске. Не подменяйте журнал вызовом print: используйте структурированные события SDK.
def run(ctx):
urls = ctx.param('urls', [])
if not isinstance(urls, list):
ctx.abort('Укажите список адресов')
ctx.log('Начинаем обход', {'pages': len(urls)})
processed = 0
for url in urls:
if ctx.cancelled():
ctx.abort('Сбор остановлен пользователем')
response = ctx.http().get(str(url))
if not response.ok():
ctx.fail('HTTP ' + str(response.status))
processed += 1
ctx.metric('pages_processed', 1)
ctx.progress(processed, len(urls), 'Загрузка страниц')
ctx.log('Обход завершён', {'processed': processed})
Если total неизвестен, передайте None. Не придумывайте точный процент и не показывайте 100% до обработки всех записей. Диагностические сообщения должны объяснять действие или причину пропуска, без паролей, токенов, текста личной почты и содержимого приватных документов.
Состояние между запусками
def run(ctx):
state = ctx.state()
number = int(state.get('next_page', 1))
url = ctx.url().with_param(ctx.param('catalog_url'), 'page', number)
response = ctx.http().get(url)
if not response.ok():
ctx.fail('HTTP ' + str(response.status))
cards = response.dom().qa('.product-card')
for card in cards:
sku = card.attr('data-sku')
if sku:
ctx.emit({'sku': sku, 'name': card.text()}, sku)
ctx.flush()
if cards:
state.set('next_page', number + 1)
Состояние хранит небольшой курсор, а не каталог. flush() отправляет пачку записей в конвейер и не является подтверждением окончательного успешного сохранения. Поэтому после сбоя страница может быть обработана снова. Стабильный ключ делает это безопаснее. Для полного обновления каталога продумайте, когда курсор возвращается к началу; не храните единственный возрастающий номер навсегда.
state имеет общие пределы числа ключей и размера значения, а проба и рабочий запуск могут иметь разный контекст сохранения. Проверяйте ожидаемое поведение на тестовом запуске. KeyValue описывает методы.