Использование Selenium и deepL для автоматизации перевода файлов PowerPoint

Вы когда-нибудь хотели эффективно перевести колоду PowerPoint? Узнайте, как автоматизировать такой процесс с помощью Python!

Необходимость автоматизации

Как и многие консультанты, я привык работать с презентациями PowerPoint. Но в последнее время меня просят особым образом обращаться с этими файлами * .pptx. Вместо того, чтобы представить свою работу или какую-либо стратегию, меня попросили перевести десятки и десятки слайдов с французского на английский. И мои первые мысли были точно такими же, как и ваши: «Как скучно… !!».

Да , очень скучно! Но вы знаете, что? Правда в том, что разработчики очень любят, когда им поручают скучные вещи. Чтобы они могли их автоматизировать! Вот история моего путешествия по переводу десятков тысяч слов, представленных на сотнях слайдов.

В этой статье вы узнаете, как управлять файлами PowerPoint с помощью Python и как извлекать информацию с веб-сайта переводов. Но давайте начнем с небольшого теста, начав с почему, прежде чем перейти к как!

Ищем существующее решение

Сразу после отчаянного «Слишком скучно…» и впереди уверенного «Я потрачу один день на создание фантастического бота, с которым я буду работать в течение следующих 3 дней» , была прагматичная фраза «Конечно, я могу найти в Интернете бесплатный переводчик PowerPoint».

Эффективный инструмент должен согласовать оба:

  • Хороший уровень перевода как для коротких выражений, так и для длинных предложений.
  • Никаких изменений в оригинальном дизайне файла.

В джунглях бесплатных онлайн-инструментов для изменения документов легко найти преобразователи из * .pdf в * .docx, из кратных * .jpgs в один * .pdf, перевод текста, извлечение таблиц, компрессоры файлов и т. д., которые работают очень хорошо. К сожалению, PowerPoints - это сложные документы, в которых можно найти множество различных объектов, которые можно комбинировать.

Я легко нашел веб-сайты, предоставляющие такую ​​услугу, провел несколько тестов на нескольких слайдах и… сразу же полностью уволился. После использования разных переводчиков результаты были весьма разочаровывающими: переводы часто были приблизительными, а шрифты / размеры / цвета время от времени менялись по сравнению с исходным документом. Без сомнения, это сделало бы часть работы. Но мне все равно придется очень осторожно и долго читать документы. И рискну забыть очевидные неверные переводы, которые выдали бы меня с первого взгляда. Ни за что.

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

Тестирование и разработка инструмента

Представление стека

После некоторого исследования я решил, что следующий стек может привести к интересным результатам. Использование пакета python-pptx для взаимодействия с файлами. Он позволяет нам работать с презентациями, слайдами, фигурами, таблицами, абзацами, сгруппированными блоками и многим другим. Инструмент казался очень многообещающим. Что касается перевода, я бы выбрал deepL - переводчик на базе искусственного интеллекта. А поскольку его API не является бесплатным, Selenium идеально подходит для доступа к веб-странице и автоматизации перевода.

Почему Python-pptx?

Python-pptx - это пакет Python, доступный через обычную pip install python-pptx командную строку. Это позволяет нам изучать файлы PowerPoint очень структурированным образом. Сначала вы имеете дело с Presentation объектом, который содержит всю высокоуровневую информацию. Затем вы получаете доступ к Slides объекту, и на каждом слайде вы получаете доступ к Shapes объектам. Фигуры могут быть текстовыми фреймами, таблицами, диаграммами, изображениями или даже группами фигур. Очень интуитивно понятно.

И когда вы имеете дело с экземпляром text_frame, вы можете получить доступ как к тексту, так и к шрифту. Идеально подходит для наших нужд: перевод текста, ничего не меняя!

Кроме того, документация очень обширна и хорошо написана.

Почему DeepL?

DeepL - это переводчик на базе искусственного интеллекта, основанный на сверточных нейронных сетях, который был обучен на базах данных Linguee. Он был запущен в 2017 году и вскоре, как сообщается, превзошел своих конкурентов в слепых тестах, включая Google Translation, Microsoft Translation и Facebook. Он также был бы более точным и более тонким при той же скорости, что и его конкуренты.

Я не могу представить себе полный тест, но вот небольшое сравнение между DeepL и Google Translation.

Оригинальный английский текст

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

Переводчик Google

Autrefois, les fourmis et les cigales étaient amis. Ils étaient très différents. Alors que les fourmis travaillaient dur, les cigales n’ont rien fait. Ils ont chanté et dansé toute la journée.

Перевод DeepL

Autrefois, les fourmis et les cigales étaient amies. Elles étaient très différentes. Alors que les fourmis travaillaient dur, les cigales ne faisaient rien. Elles chantaient et dansaient toute la journée.

Для читателей, которые не понимают французского, у нас есть два огромных улучшения между Google и DeepL: определение пола (на французском и цикады, и муравьи - женские слова, поэтому мы квалифицируем их с помощью elles вместо ils, которое в мужском роде означает elles), и согласование времен, которое заключается в использовании правильной формы спряжения в зависимости от времени наступления события.

Здесь достаточно примеров, но в коротких предложениях из очень небольшого количества слов перевод также намного лучше и хорошо справляется со стоп-словами. Что очень важно для случая использования PowerPoint. Итак, начнем, мы будем использовать DeepL.

Почему Selenium?
Поскольку API DeepL не является бесплатным, нам придется использовать его через веб-интерфейс. Не нужно спорить, Selenium - идеальный инструмент для такого рода задач. Как говорят сами:

Selenium автоматизирует браузеры

Чтобы открыть для себя возможности Selenium, я предлагаю вам прочитать эту статью, в которой подробно описывается библиотека и объясняется, как создать бота для Instagram.

Практика

Инструмент с нуля

Как вы, возможно, догадались, в этом проекте есть две отдельные части, что в основном означает три этапа:

  • Сборка переводчика
  • Взаимодействие с презентацией PowerPoint
  • Собираем все вместе

Давайте углубимся (L) и узнаем, как работает решение!

Сборка переводчика

Чтобы иметь в виду процесс, вот что мы хотим сделать

  • Создайте драйвер селена
  • Откройте веб-страницу DeepL
  • Отправьте текст в область ввода текста веб-страницы
  • Прочтите переведенный текст из области текста перевода
  • Закройте страницу и драйвер селена

Прямолинейно, а?

К сожалению, страница deepL полностью написана на Javascript, и переведенный текст никогда не появляется в содержимом HTML, даже когда отображается на вашем экране. Это первая проблема: невозможно идентифицировать компонент Html div (или какой-либо другой), из которого извлекается текстовое содержимое.

Надеюсь, Selenium - отличный инструмент, а deepL упрощает еще один момент: они предоставляют нам «кнопку копирования в буфер обмена». После его идентификации необходимо выполнить один щелчок, чтобы перевести переведенный текст в буфер обмена (обратите внимание, что библиотека буфера обмена была (установлена ​​и) импортирована строка 3.

Примечание. Между вводом текста и нажатием кнопки копирования вводится время ожидания: time.sleep(3). Это связано с подключением к Интернету и запросами через сеть. Помимо процесса перевода, независимо от длины текста, есть минимальное время ожидания, прежде чем он получит перевод в вашем браузере.

Итак, вот переводчик предложений. Теперь, как перейти от отдельного предложения к полному корпусу? Первое решение - зациклить процесс. Но учитывая, что 3s-translation ждать более длинного корпуса, это будет очень медленно. Представьте себе PowerPoint с 50 слайдами, содержащими заголовок и несколько полей с текстом, на это потребуются часы.

Но еще раз, DeepL облегчает нам задачу. Это позволяет нам переводить разные абзацы за раз. Таким образом, мы можем отправлять несколько предложений одновременно, составляя корпус из предложений. Чтобы понять это, мы создаем более длинный текст, объединяя наши предложения в одну длинную строку. Чтобы быть уверенным, что алгоритм не добавит никакого контекста между нашими предложениями, мы используем объединяющую строку для конкатенации. После перевода строка соединения затем используется как строка-разделитель, так что мы получаем предложение перевода за предложением.

Фантастика ! Значит, если я пришлю свой полный корпус, я получу его перевод в течение нескольких секунд?

Еще нет. При использовании DeepL существует ограничение на количество переводимых символов. Давай узнаем это.

Примечание: вы можете увидеть опцию «Перевести документ». Если вы нажмете на нее, вам будет разрешено загрузить файл PowerPoint. К сожалению, размер файла ограничен, и есть перенаправление на премиум-вариант, который не является бесплатным.

Действительно, как указано в правом нижнем углу, ограничение на перевод составляет 5000 символов. А если кто-то пытается поставить больше, страница становится красной, и перевод работает только с предложениями до 5000-й буквы текста.

Это не настоящая проблема, если это очень разумный предел, и мы можем создавать скорректированные пакеты предложений. Идея заключается в следующем: учитывая огромный корпус, мы создадим пакеты предложений так, чтобы каждый пакет был примерно (чуть меньше) 5000 символов.

Затем для каждого пакета мы запустим предыдущую функцию. Если у нас есть корпус из 200 предложений, в среднем 90 символов (15 слов, 5 букв / слово +1 пробел / слово), всего 18 000 слов, он, скорее всего, создаст 4 пакета: 3 * 5000 + 1 * 3000. Расчет не совсем правильный, так как есть дополнительные символы из-за объединения, но идея вы поняли.

Примечание: при увеличении размера текста увеличивается и время перевода. Он не увеличивается линейно, но для перевода 5000 символов разумно подождать 20 секунд вместо 3 перед извлечением переведенного текста в буфер обмена. Время также зависит от языка перевода. Например, если вы хотите перевести с английского на французский или испанский, это быстро. Перевод на китайский намного длиннее. Я сделал несколько тестов, и в этом случае время ожидания составляет около 45 секунд. Что касается точности перевода, я бы доверился DeepL, но не смог проверить!

Большой ! Теперь все нормально? Могу ли я перевести свою любимую книгу с португальского на голландский?

Еще раз, есть несколько новых задач. Предыдущий сценарий хорошо работает с небольшими объемами текста. Фактически, функция send_keys из селена имитирует нажатие человеком одной за другой клавиш на клавиатуре. Он делает это быстрее, но он это делает. Это означает, что deepL получает около 5000 символов один за другим. И веб-сайт обнаруживает, что это действия бота. Затем подключаемый модуль защиты от ботов заменяет процесс перевода на неустойчивое поведение: изменение страниц на веб-сайте DeepL, открытие всплывающих окон или попытки загрузить переводы на ваш компьютер. ОЧЕНЬ ПЛОХОЙ.

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

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

Предупреждение: похоже, что селеновый способ копирования / вставки зависит от используемой ОС и навигатора. Позвольте мне объяснить: моделируя использование клавиатуры, в MacOS вы реализуете COMMAND + V, а в Windows вы реализуете CONTROL + V.

Я обнаружил, что в MacOS + Chrome он хорошо работает с: element.send_keys(Keys.SHIFTT, Keys.INSERT)

Ладно, мы почти закончили. Это работает нормально, но есть еще одна проблема, которую нужно решить: когда мы добавляем столько текста, поле перевода становится больше: больше, чем размер вашего экрана.

Поначалу кажется, что это ничего не меняет, но используемая нами кнопка «Копировать в буфер обмена» расположена внизу страницы. И теперь это вне экрана. Тогда мы все еще можем обнаружить его в синтаксисе Html, но селен не может имитировать щелчок по нему.

Следующий шаг: прокрутка страницы. У Selenium есть встроенный способ сделать это.

Мы здесь! Наш переводчик теперь работает и готов перевести весь нужный нам текст. Бесплатный и точный перевод. Большой!

Хорошая практика - реализовать очистители селена как классы. Основываясь на том, что мы видели здесь, вы можете найти здесь полный класс seleniumDeepL, который упрощает перевод. Обратите внимание, что он наследует некоторые базовые свойства селена от класса seleniumDefault, доступного здесь в том же репозитории GitHub.

Пример перевода в корпусе из трех предложений

corpus_fr = [
    "Bonjour j’aimerais traduire tous ces documents",
    "Mais je ne suis pas sur d’avoir un niveau d’anglais suffisant",
    "Et surtout ! Je suis Data Scientist, pas traducteur."
]

Объект seleniumDeepL предоставляет интересные дополнительные функции, не обсуждаемые в этой статье, например:

  • Выбор целевого языка перевода. Мы можем использовать все языки, доступные в DeepL. На сегодняшний день доступны: английский ( en ), французский ( fr ), испанский ( sp ), немецкий ( de ), голландский ( nl ), португальский ( pt ), польский ( pl ), китайский ( zh ) и японский ( ja ). Исходный язык автоматически определяется DeepL, и для выбора целевого языка вам необходимо изменить en в URL-адресе www.deepl.com/en/translator на нужный язык.
  • Более быстрая обработка за счет перевода только предложений, которых еще нет в корпусе или в текущем пакете.
  • Импорт и экспорт переводов из / в файл json {предложение1: перевод1, предложение2: перевод2,…}

Подводя итог, мы узнали, как:

  • Загружайте данные в виде списков строк, объединяйте их в пакеты по 5 тыс. Букв, используя объединяющую строку, и преобразуйте эти пакеты в меньший корпус, чтобы быстрее переводить.
  • Переведите каждый пакет, добавив его в буфер обмена и вставив из буфера обмена в поле перевода DeepL. Ждем несколько секунд перевода, находим, прокручиваем и нажимаем кнопку «Копировать в мой буфер обмена». Последний шаг - разделить переведенные данные до их исходного размера с помощью соединительной строки.

Исследование в PowerPoint

Эта часть короче и проще: из файла PowerPoint мы хотим извлечь весь его текст, передать его нашему переводчику и заменить все тексты их переводом.

Извлечение текста

Теперь мы хотим получить все тексты в презентации. И чтобы прочитать все это дальше, необходимо методично просмотреть файл.

Каждая презентация построена одинаково:

  • Презентация содержит слайды
  • Слайд содержит фигуры
  • Фигура может содержать текст

Оказывается, в python-pptx есть соответствующие им встроенные объекты. Что быстро приводит к этой функции:

У нас есть все тексты презентации? Все они? Действительно? Давай проверим.

Чтобы быть уверенным в собираемом тексте, я вместо того, чтобы собирать только тексты, заменял их пустыми строками, а затем сохранял презентацию в ее пустой версии. Открыв его, мы быстро проверим, весь ли текст выделен (и удален), и сделаем выводы, правильно ли работает наш алгоритм.

Сделаем это за 2 шага:

  1. заменить texts.append(paragraph.text) на paragraph.text = ‘’
  2. используйте prs.save(output_file) в конце нашей get_texts_from_file функции

Вот результат на презентации с предыдущей картинки:

Кажется, это почти хорошо, но на третьем слайде вы можете увидеть, что у нас остался один текст.

Фактически, в коде мы проверили все формы, для которых атрибут has_text_frame установлен наTrue.

Но не все формы имеют один и тот же тип. В частности, мы имеем дело с двумя специальными формами:

  • Сгруппированные фигуры: как вы, возможно, знаете, в PowerPoint при редактировании файла с большим количеством информации вы можете выбрать несколько фигур и сгруппировать их. Если вы внимательно посмотрите на первый снимок экрана, вы увидите, что в правой части есть два прямоугольника (один для изображения и один для текста), а в левой части только один. Это потому, что логотип Selenium и тексты Selenium сгруппированы вместе. В python-pptx эти элементы называются GroupShapes, и на самом деле GroupShapes не имеют атрибутов text_frames, поэтому для свойства has_text_frame по умолчанию установлено значение False. Вот почему наш алгоритм не подавил этот текст. Надеюсь, у GroupShapes есть атрибут Shapes, который содержит отдельные фигуры сгруппированной фигуры.
  • Таблицы: в приведенном выше примере таблицы нет, но проблема та же. Некоторые фигуры, помимо has_text_frame, имеют атрибут has_table. А когда has_table is True мы можем получить доступ к объектам Таблица. В таблице нет текстовых значений, но Table содержит cell, а ячейки имеют text_frame объект. Задача решена.

Если принять во внимание оба этих типа форм, результаты будут гораздо более удовлетворительными.

Примечание: есть и другие формы, но в основном они графические, не подразумевающие текст, поэтому нам не нужно с ними возиться. Но если вам нужно иметь дело с файлами PowerPoint, вам определенно следует поближе познакомиться с хорошо написанной документацией по python-pptx;)!

Теперь мы уверены, что прочитали все тексты презентаций, перейдем к следующему шагу.

Перевод

У нас есть список предложений, он выглядит как форматированный корпус для нашего переводчика. Этот преобразует его в пакетный корпус, выполняет некоторую итерацию на сайте deepL и возвращает словарь.

Мы можем снова перебрать наш PowerPoint и заменить текст, используя словарь перевода. Ключи - это оригинальные предложения, а значения - это переводы.

Вставка текста

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

Примечание: чтобы упростить код, мы повторяем all_presentation_text_frames на l.15. Это сделано для иллюстрации: реальный процесс работы с таблицами и сгруппированными фигурами не так прост. Полный код для манипуляции ppt доступен здесь.

Необходимо последнее обновление. Здесь мы заменили значение text_frame.paragraph.text. Фактически, он инкапсулирует больше информации, чем только текст. Чтобы понять это, вы должны знать, что каждая фигура имеет свои собственные параметры (цвет, размер, положение, формат и шрифт). Это значения по умолчанию с учетом формы и шаблона PowerPoint. Но иногда мы можем вручную изменить эту информацию. Например, если текст слишком длинный, люди могут решить изменить размер по умолчанию с 16 на 14, чтобы он правильно вписался в форму. И в этом конкретном случае информация хранится в text_frame.paragraph.text.runs. Так что мы не сможем легко перезаписать текст.

К сожалению, это важный момент: мы должны сохранить ту же структуру, что и входной файл!

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

Я бы сказал, что несмотря на то, что это была главная проблема проекта, ее было труднее всего преодолеть. Он должен понимать концепцию runs и внимательно читать документацию по python-pptx. Поскольку это становится очень техническим, я помещаю функцию прямо здесь, на случай, если она вам интересна, но если вы не понимаете, как она работает, не беспокойтесь об этом.

Итак, мы здесь! Почти конец нашего долгого пути! И последнее, что нужно сделать: запустить все это с нуля!

Собираем все вместе

Мы достигли последнего шага: с помощью переводчика, который мы создали, для преобразования PowerPoint. Я не буду задерживаться на этом, поскольку это всего лишь комбинация всего, что мы видели до сих пор, с некоторым рефакторингом.

Заключение

Мы узнали, как создать отличный инструмент для автоматизации перевода файлов PowerPoint без изменения их внешнего вида и с большой степенью уверенности. Тем не менее, имейте в виду, что нет ничего идеального. Таким образом, это не препятствует повторному воспроизведению вывода для обнаружения возможных ошибок. Действительно, DeepL - очень мощный инструмент, но иногда, если мы не даем ему достаточно контекстной информации, это может привести к приблизительным переводам.

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

Это также заставило меня открыть для себя библиотеку python-pptx, которая является интересным и отличным инструментом для версии PowerPoint.

В качестве следующего шага мы могли бы представить себе создание базового веб-интерфейса с зоной загрузки, раскрывающимся списком целевого языка и кнопкой перевести и загрузить. Такой фреймворк, как Flask или Dash, подойдет.

Наконец, я надеюсь, что вам понравилось читать этот рассказ / руководство так же, как мне понравился этот проект. Осознать это было намного (намного) веселее, чем целыми днями переводить слайды. Обратите внимание, что весь код доступен в этом репозитории на моем Github. Если вы хотите его использовать, не стесняйтесь и не стесняйтесь давать звезду в проекте. Конечно, приветствуются любые замечания и предложения :)!

Я хотел бы поблагодарить моего коллегу и друга Исмаила Мебсаута, который только что опубликовал кучу статей о Основах глубокого обучения и побудил меня написать этот первый пост!