Абзацы DOCX-расшифровки в CSV через python-docx: как сохранить связь с источником
Строгий перенос реплик из основного текста документа. Проверка меток говорящих, номера исходных абзацев и ограничения таблиц, сносок и исправлений.
Когда абзацы можно превратить в записи
Редактор может согласовать интервью в Word, а исследователь — работать дальше с колонками говорящий и текст. Автоматический перенос полезен лишь после определения структуры. Сначала сохраните отдельную проверенную копию reviewed.docx; не запускайте скрипт на документе с непонятными вставками и незавершённой редактурой.
В учебном формате одна реплика занимает один абзац и начинается с метки «Интервьюер:» или «Участник:». Префикс отделяется первым двоеточием. Дальнейшие двоеточия остаются частью речи. Перенос строки внутри абзаца не превращается в новую реплику.
Текстовую основу можно получить через Транскрибатор. Разметка DOCX в этом примере готовится отдельно. Код не определяет голоса и не восстанавливает метки, которых в документе нет.
Проверьте, где хранится текст
Откройте DOCX и установите, находятся ли нужные реплики в основном тексте. doc.paragraphs представляет его абзацы; это не список всех видимых надписей документа. Абзацы в таблицах и отдельных частях документа требуют другого обхода.
Документация python-docx отдельно предупреждает, что абзацы внутри меток исправлений w:ins и w:del не попадают в этот список. Завершите согласование нужной копии в редакторе и проверьте фактический состав. Не считайте отсутствие ошибки доказательством переноса всех видимых исправлений.
Для контроля разных версий полезна проверка изменений двух DOCX. Пример ниже дополнительно останавливается при таблице, чтобы не пропустить её незаметно. Сноски, колонтитулы и текстовые поля проверяйте вручную до экспорта.
Сохраните строгий формат и запустите код
Понадобятся Python и пакет python-docx; команда установки в вашем окружении — python -m pip install python-docx. Название пакета отличается от импортируемого docx. Поместите скрипт рядом с reviewed.docx.
Измените множество allowed на реальные согласованные метки. Не добавляйте туда автоматически каждое слово перед двоеточием: заголовок «Примечание:» иначе может стать участником. Если формат не соответствует правилу, скрипт указывает номер абзаца и прекращает работу до создания CSV.
Пустые абзацы пропускаются, но номера исходных абзацев сохраняются. Поэтому source_paragraph может иметь пропуски: это правильно и помогает вернуться к источнику. Режим x не позволяет перезаписать уже существующий результат.
Проверьте перенос на контрольных репликах
Прочитайте paragraphs.csv через csv.reader. Сверьте количество реплик, первую и последнюю записи, текст с кавычками и фрагмент с несколькими двоеточиями. CSV следует разбирать библиотекой: запятая внутри высказывания не становится новым полем.
В учебном тесте «Участник: Вариант: да, но позже» сохранился как одна реплика с внутренним двоеточием. Номер абзаца после пустой строки остался исходным. Добавленный заголовок без согласованной метки вызвал остановку до записи результата.
Номер абзаца относится только к зафиксированной версии DOCX. Если вставить абзац в начале документа, последующие номера изменятся. Храните имя и контрольную версию источника вместе с CSV, а не используйте source_paragraph как вечный идентификатор.
Отделите текстовый перенос от проверки речи
Этот процесс переносит текст и метку по вашему правилу. Он не проверяет произнесённые слова, правильность атрибуции, точность чисел или отсутствие редакторских добавлений. Спорные места нужно прослушать и согласовать.
Не обещайте сохранение жирного шрифта, комментариев и полной структуры DOCX в CSV. Для дальнейшей проверки данных используйте контроль колонок и пустых реплик. Если формат сложнее примера, сначала разработайте другое явное правило переноса.
В паспорте результата укажите состав: основной текст, два разрешённых префикса, пропуск пустых абзацев и известные исключения. Не передавайте выборку как полный документ, пока фактическая полнота не проверена.
Учебный пример разбора первого двоеточия
Вымышленные реплики показывают, как сохраняется внутренний текст.
| Абзац | Результат | Контроль |
|---|---|---|
| Участник: Вариант: да, но позже | Участник / Вариант: да, но позже | Внутреннее двоеточие сохранено |
| Пустой абзац | Пропуск записи | Следующий номер не перенумерован |
| Примечание: проверить имя | Остановка | Не выдавать за речь участника |
Для документа с таблицами или сложной редактурой нужен отдельный разбор; этот учебный скрипт не должен применяться без подготовки.
Перенос согласованных абзацев в CSV
import csv
from docx import Document
allowed = {"Интервьюер", "Участник"}
doc = Document("reviewed.docx")
if doc.tables:
raise ValueError("Таблицы требуют отдельного правила переноса")
rows = []
for number, paragraph in enumerate(doc.paragraphs, 1):
value = paragraph.text
if not value.strip():
continue
speaker, separator, text = value.partition(":")
speaker = speaker.strip()
text = text.lstrip()
if not separator or speaker not in allowed or not text.strip():
raise ValueError("Проверьте абзац " + str(number))
rows.append([number, speaker, text])
with open("paragraphs.csv", "x", encoding="utf-8", newline="") as f:
writer = csv.writer(f)
writer.writerow(["source_paragraph", "speaker", "text"])
writer.writerows(rows)
print("Реплик:", len(rows))Частые вопросы
Будут извлечены таблицы?
Нет. Пример останавливается при наличии таблицы.
Номер абзаца — таймкод?
Нет, это позиция в одной зафиксированной версии DOCX.
Внутреннее двоеточие делит реплику?
Нет. partition отделяет только первое двоеточие.
Можно определить говорящего автоматически?
Этот код читает явные согласованные метки и не анализирует аудио.