Разбираю практичный способ получать рабочие Python-скрипты для таблиц, парсинга и API, а затем доводить их до безопасного запуска.

Когда мне нужен одноразовый скрипт, я больше не начинаю с пустого файла. Сначала описываю задачу нейросети: откуда взять данные, что преобразовать, куда сохранить результат и какие ошибки надо поймать. Через 30–90 секунд появляется черновик. Его нельзя слепо запускать на рабочих данных, но как стартовая заготовка он экономит много рутины: импорты, структуру функций, базовую обработку исключений, чтение файлов, цикл по строкам.

Скрипты особенно хорошо подходят для задач с понятным входом и выходом. Например, есть CSV на 40 000 строк, нужно нормализовать телефоны, удалить дубли и выгрузить чистую таблицу. Или нужно раз в день забрать JSON из API, отфильтровать записи по статусу и отправить итог в хранилище. Раньше на такой код легко уходил час: вспомнить синтаксис библиотеки, собрать обработку ошибок, проверить кодировки. Сейчас я трачу это время иначе, формулирую задачу, запускаю малый тест и правлю крайние случаи.

Если вы только выстраиваете личный процесс работы с такими инструментами, полезно сначала разобраться, как нейросети встраиваются в рабочие процессы, а затем уже переходить к автоматизации кода. Без процесса скрипты быстро превращаются в папку «разное», где никто не помнит, какой файл что делает.

Где нейросеть особенно сильна в скриптах

Лучший участок для генерации, повторяемая техническая обвязка. У программиста в голове обычно находится бизнес-логика: что считать продажей, какие статусы пропускать, какие поля считать обязательными. Нейросеть быстрее собирает каркас: чтение файла, функцию очистки, логирование, сохранение результата, пример запуска из командной строки.

Я делю задачи на четыре группы.

Сценарий Что просить у нейросети Что проверять руками Типичный риск
Обработка таблиц чтение CSV или XLSX, фильтры, группировки, выгрузка кодировки, пустые значения, типы дат тихая потеря строк
Парсинг страниц запрос страницы, поиск блоков, сохранение результата правила сайта, изменения верстки, задержки блокировка или неверный селектор
Интеграция API авторизация, запросы, пагинация, повтор при ошибке лимиты, статусы ответа, формат токена бесконечный цикл запросов
Служебная автоматизация переименование файлов, архивы, отчёты, уведомления права доступа, путь к файлам, журнал ошибок перезапись нужных данных

Для текста промпта лучше использовать тот же подход, что и для материалов: роль, контекст, входные данные, формат результата, критерии проверки. Подробный разбор есть в статье про формулировку запросов для нейросетей, здесь применим его к коду.

Шаг 1. Описываем задачу так, чтобы код можно было проверить

Слабый запрос звучит так: «Напиши скрипт для обработки файла». Нейросеть угадает половину условий. Потом вы будете ловить ошибки в кодировке, названиях колонок и типах данных.

Рабочий запрос выглядит конкретнее:

Напиши Python-скрипт для файла orders.csv.
Колонки: order_id, created_at, phone, amount, status.
Нужно оставить строки со status = paid, привести phone к формату 79991234567,
amount преобразовать в число, строки с пустым order_id вынести в errors.csv.
Результат сохранить в clean_orders.csv.
Добавь функции, логирование и блок запуска через main.
Перед кодом кратко перечисли допущения.

Такой запрос задаёт шесть проверяемых точек: входной файл, имена колонок, фильтр, преобразование телефона, файл ошибок, формат структуры. Если нейросеть ошибётся, это видно сразу. Если она добавит лишнюю зависимость, можно попросить вариант без неё.

В SoftChat такой диалог удобно вести в обычном текстовом чате: ответы идут потоком, а для текущего разговора можно выбирать модель и настраивать параметры вроде «Креативность» и «Длина ответа». Для кода я обычно снижаю креативность и прошу короткое пояснение перед скриптом. Это уменьшает фантазии в названиях файлов и помогает быстрее перейти к запуску. Если у вас есть повторяемые форматы задач, пригодятся шаблоны промптов и сохранённые ассистенты, потому что роль ревьюера или генератора служебных скриптов не придётся задавать заново каждый раз.

Шаг 2. Получаем черновик и сразу просим тестовый пример

Нейросеть может написать синтаксически корректный код, который логически делает не то. Поэтому я прошу вместе со скриптом дать маленький набор входных строк. Пять строк часто достаточно, чтобы поймать ошибку с пустыми значениями, датой или числом через запятую.

Пример скрипта для очистки CSV:

import csv
import logging
from pathlib import Path

logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')

INPUT_FILE = Path('orders.csv')
OUTPUT_FILE = Path('clean_orders.csv')
ERROR_FILE = Path('errors.csv')


def normalize_phone(value):
    digits = ''.join(ch for ch in str(value) if ch.isdigit())
    if len(digits) == 11 and digits.startswith('8'):
        digits = '7' + digits[1:]
    if len(digits) != 11 or not digits.startswith('7'):
        return None
    return digits


def parse_amount(value):
    try:
        return float(str(value).replace(',', '.'))
    except ValueError:
        return None


def main():
    clean_rows = []
    error_rows = []

    with INPUT_FILE.open('r', encoding='utf-8-sig', newline='') as file:
        reader = csv.DictReader(file)
        for row in reader:
            if not row.get('order_id'):
                error_rows.append(row)
                continue
            if row.get('status') != 'paid':
                continue

            phone = normalize_phone(row.get('phone', ''))
            amount = parse_amount(row.get('amount', ''))

            if phone is None or amount is None:
                error_rows.append(row)
                continue

            row['phone'] = phone
            row['amount'] = amount
            clean_rows.append(row)

    fieldnames = ['order_id', 'created_at', 'phone', 'amount', 'status']

    with OUTPUT_FILE.open('w', encoding='utf-8', newline='') as file:
        writer = csv.DictWriter(file, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(clean_rows)

    with ERROR_FILE.open('w', encoding='utf-8', newline='') as file:
        writer = csv.DictWriter(file, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(error_rows)

    logging.info('Готово: чистых строк %s, строк с ошибками %s', len(clean_rows), len(error_rows))


if __name__ == '__main__':
    main()

Этот код не претендует на промышленный конвейер. Но он уже разделён на функции, не перезаписывает исходник и складывает спорные строки отдельно. Для одноразовой выгрузки или первичной проверки данных этого часто хватает.

Шаг 3. Просим парсер, но задаём границы

Парсинг кажется простой задачей до первой смены верстки. Нейросеть хорошо пишет каркас: загрузить страницу, разобрать HTML, достать заголовки, сохранить CSV. Границы задаёт человек: можно ли обращаться к странице автоматически, какая частота запросов допустима, какие данные разрешено собирать.

Условный пример: для внутренней базы знаний из 120 HTML-страниц можно попросить скрипт пройти по локальной папке, достать заголовок H1, дату обновления и первый абзац, а затем собрать индекс в CSV. Здесь нет нагрузки на чужой сайт, результат легко сверяется вручную по 10 случайным страницам.

from pathlib import Path
import csv
from bs4 import BeautifulSoup

SOURCE_DIR = Path('pages')
OUTPUT_FILE = Path('page_index.csv')


def extract_page_data(path):
    html = path.read_text(encoding='utf-8')
    soup = BeautifulSoup(html, 'html.parser')
    h1 = soup.find('h1')
    date = soup.find(attrs={'data-field': 'updated_at'})
    first_paragraph = soup.find('p')
    return {
        'file': path.name,
        'title': h1.get_text(strip=True) if h1 else '',
        'updated_at': date.get_text(strip=True) if date else '',
        'summary': first_paragraph.get_text(' ', strip=True) if first_paragraph else '',
    }


def main():
    rows = [extract_page_data(path) for path in SOURCE_DIR.glob('*.html')]
    with OUTPUT_FILE.open('w', encoding='utf-8', newline='') as file:
        writer = csv.DictWriter(file, fieldnames=['file', 'title', 'updated_at', 'summary'])
        writer.writeheader()
        writer.writerows(rows)


if __name__ == '__main__':
    main()

После генерации я почти всегда задаю уточняющий запрос: «Перепиши так, чтобы код не падал, если поля нет, и добавь отчёт о количестве пустых значений». Такой второй проход обычно ценнее первого. Нейросеть уже видит структуру и улучшает конкретный фрагмент, а не изобретает файл заново.

Шаг 4. Интеграции API: просим устойчивость, а не красивый пример

Большая ошибка, просить «скрипт для API» и остановиться на одном успешном запросе. В рабочей среде нужны таймауты, повтор при временной ошибке, проверка статуса, пагинация и журнал. Без этого скрипт может молча обработать 100 записей из 10 000.

Хороший промпт для интеграции:

Напиши Python-скрипт, который забирает записи из REST API.
Токен читать из переменной окружения SERVICE_TOKEN.
Добавь таймаут 20 секунд, 3 повтора при статусах 429, 500, 502, 503.
Поддержи пагинацию через параметр page.
Сохрани результат в result.jsonl, одна запись на строку.
Не печатай токен в лог.

Здесь я заранее убираю две частые проблемы: секреты в коде и отсутствие повторов. JSONL удобен тем, что файл можно дозаписывать, читать построчно и проверять без загрузки всего массива в память.

import json
import os
import time
from pathlib import Path

import requests

API_URL = 'https://example.internal/api/items'
TOKEN = os.getenv('SERVICE_TOKEN')
OUTPUT_FILE = Path('result.jsonl')


def fetch_page(page):
    headers = {'Authorization': f'Bearer {TOKEN}'}
    params = {'page': page}

    for attempt in range(1, 4):
        response = requests.get(API_URL, headers=headers, params=params, timeout=20)
        if response.status_code == 200:
            return response.json()
        if response.status_code in {429, 500, 502, 503}:
            time.sleep(attempt * 2)
            continue
        response.raise_for_status()

    response.raise_for_status()


def main():
    if not TOKEN:
        raise RuntimeError('Не задана переменная окружения SERVICE_TOKEN')

    page = 1
    total = 0

    with OUTPUT_FILE.open('w', encoding='utf-8') as file:
        while True:
            data = fetch_page(page)
            items = data.get('items', [])
            if not items:
                break
            for item in items:
                file.write(json.dumps(item, ensure_ascii=False) + '\n')
                total += 1
            page += 1

    print(f'Сохранено записей: {total}')


if __name__ == '__main__':
    main()

Адрес API в примере условный. В настоящем проекте я заменяю его на адрес сервиса, читаю документацию по лимитам и запускаю первый прогон на малом диапазоне. Если API отдаёт 1 000 записей на страницу, не надо сразу качать 200 страниц. Сначала 1–2 страницы, затем проверка файла, потом полный запуск.

Шаг 5. Проверяем код в четыре прохода

Генерация экономит время на наборе и поиске синтаксиса, но ответственность за результат остаётся у человека. Мой порядок проверки такой.

  1. Сухое чтение. Проверяю, какие файлы скрипт читает и пишет, нет ли удаления без подтверждения, не печатаются ли токены.
  2. Малый набор данных. Запускаю на 5–20 строках или на одной странице API. Смотрю не только на отсутствие ошибки, а на содержимое результата.
  3. Крайние случаи. Пустой файл, неверная дата, пропущенная колонка, дубль, слишком длинная строка. Эти случаи лучше попросить сгенерировать отдельно.
  4. Журнал и повторяемость. Скрипт должен сообщать, сколько строк прочитал, сколько сохранил, сколько отправил в ошибки. Если цифры не сходятся, код рано пускать дальше.

Если задача превращается в регулярный процесс, стоит оформить её как маленький проект: файл зависимостей, README, пример конфигурации, тесты на функции преобразования. Нейросеть может подготовить такую упаковку, но её надо проверять по тем же правилам. Сначала минимальный рабочий сценарий, затем устойчивость.

Для командной работы полезно заранее договориться, где хранить промпты и принятые шаблоны. В SoftChat для повторяемых стартов есть шаблоны промптов, а история разговоров сохраняется. Это помогает вернуться к задаче и понять, почему скрипт написан именно так. Если тема шире кода, например отчёты, письма и планы, посмотрите материал про нейросети для повседневных задач, там похожая логика разложена без программирования.

Как писать промпт для кода: короткая схема

Я использую одну форму и меняю детали под задачу.

Ты пишешь служебный Python-скрипт.
Цель: ...
Вход: ...
Выход: ...
Ограничения: ...
Ошибки: ...
Безопасность: ...
Проверка: ...
Сначала перечисли допущения, затем дай код, потом команды запуска.

В поле «Ограничения» попадают версии Python, запрет на тяжёлые зависимости, лимит памяти, формат кодировки. В поле «Ошибки» я перечисляю, что делать с пустыми строками, недоступным API, битым JSON, пропущенной колонкой. В поле «Безопасность» прошу не хранить токены в коде, не удалять исходные файлы и не отправлять данные наружу без отдельной команды.

Для обучения такой подход тоже работает. Новичок видит не магию, а связку «условие → код → тест → правка». Если вы используете нейросети для самообразования, пригодится разбор про роль нейросетей в обучении и самопроверке. Для текстовых задач рядом лежит похожий принцип: сначала черновик, потом проверка и редактирование. Я подробно разбирал это в статье про генерацию текста и контроль результата.

Где граница автоматизации

Нейросеть не знает ваших внутренних правил, если вы их не дали. Она может предложить библиотеку, которую нельзя ставить в вашей среде. Может не учесть лимит API. Может выбрать неверную интерпретацию статуса, если в компании статус «done» означает закрытую заявку, а «paid» означает только подтверждённый платёж.

Я не доверяю генератору три вещи: удаление данных, финансовые расчёты без независимой сверки и массовые запросы к внешним сервисам. Для этих участков нужен ручной просмотр, тестовый запуск и ограничитель. Самый простой ограничитель, параметр --dry-run, который показывает действия без записи. Второй, лимит --limit 100, чтобы первый запуск не трогал весь массив.

Модельный кейс: компания из сферы логистики, ~200 сотрудников, может начать с безопасного скрипта, который раз в день читает выгрузку заявок, находит строки без номера телефона и сохраняет отдельный файл для оператора. Здесь нет автозаписи в CRM, нет удаления и нет сложной интеграции. Польза видна быстро: оператор получает список проблемных строк, а разработчик видит, какие правила очистки действительно нужны.

Что бы я сделал на вашем месте

Я бы начал с одной задачи, где цена ошибки мала: очистка копии CSV, локальный индекс HTML-файлов или выгрузка тестового API на 1–2 страницы. Дальше попросил бы нейросеть написать код, тестовые данные и список допущений. После первого запуска я бы не чинил всё руками, а вернул ошибку в диалог и попросил исправить конкретную функцию.

Через 2–3 таких цикла обычно появляется личный шаблон промпта. Его можно сохранить и использовать для следующих задач. А когда скрипт начинает запускаться регулярно, пора добавить README, переменные окружения, журнал и тесты. Генерация даёт скорость на старте, но надёжность появляется после проверки. В этом и есть рабочий баланс: нейросеть пишет черновик за минуты, человек задаёт правила и решает, когда код готов к данным.