Не сохраняется word в pdf в питон модулем comtypes

Обновлено: 07.07.2024

В данной работе мы поработаем с PDF файлами используя Python, а именно: мы рассмотрим, как извлекать текст, изображения, разделять на страницы, найти все страницы файла, где имеется нужный нам текст, как вставлять изображения в этот файл, удалять страницы, разделять страницы на четные и нечетные. Давайте же начнем!

Извлечение текста с помощью PyPDF2 и PyMuPDF

Сначала сделаем извлечение текста двумя методами. Первый – используя библиотеку PyPDF2, а второй – PyMuPDF. Что это вообще за библиотеки? PyPDF2 – это библиотека для извлечения информации и содержимого документов, постраничного разделения документов, объединения документов, обрезки страниц и добавления водяных знаков. А PyMuPDF (известный как fitz) - привязка Python для MuPDF, который является облегченным средством просмотра PDF и XPS. Именно поэтому, первым делом мы устанавливаем эти библиотеки: pip3 install pypdf2, pip3 install pymupdf. Далее, в папке с проектом мы создаем еще три дополнительные папки: images, source и dist. Папки images и dist будем использовать для записи результатов работы своих программ, а в папке source храним исходные PDF файлы (которые надо будет заранее туда положить), сами скрипты будем хранить в корне. После всех этих действий, приступаем к извлечению текста с помощью PyPDF2:

В данном коде мы импортируем PdfFileReader, помня о том, что пакет уже установлен. Задаём имя файла из папки source, открывает документ и получаем информацию о документе, используя метод getDocumentInfo() и общее количество страниц getNumPages(). Далее в цикле for читаем каждую страницу, получаем содержимое page.extractText() и печатаем в stdout. Обратите внимание, что PyPDF2 начинает считать страницы с 0, и поэтому вызов pdf.getPage(i) при i = 0 извлекает первую страницу документа. Результат:

Если использовать библиотеку PyMuPDF, то код выполняется аналогично предыдущему методу, единственный момент заключается в том, что импортируемый модуль имеет имя fitz, что соответствует имени PyMuPDF в ранних версиях:

Приятной особенностью PyMuPDF является то, что он сохраняет исходную структуру документа без изменений — целые абзацы с разрывами строк сохраняются такими же, как в PDF документе. Результат:

Извлечение изображений из PDF с помощью PyMuPDF

Переходим к изображениям. PyMuPDF упрощает извлечение изображений из документов PDF с использованием метода getPageImageList(). Скрипт, приведённый ниже, основан на примере из вики-страницы PyMuPDF и извлекает и постранично сохраняет все изображения из PDF в формате PNG. Если изображение имеет цветовое пространство CMYK, оно будет сначала преобразовано в RGB. При этом, все извлеченные изображения будут сохраняться у нас в папку images. Сам код:


В моем случае, код извлек из PDF файла 244 изображения. И все это произошло меньше чем за минуту! Результат:

Разделение PDF файлов на страницы с помощью PyPDF2

Для этого примера, в первую очередь необходимо импортировать классы PdfFileReader и PdfFileWriter. Затем мы открываем файл PDF, создаем объект для чтения и перебираем все страницы, используя метод объекта для чтения getNumPages. Внутри цикла for мы создаем новый экземпляр PdfFileWriter, который еще не содержит страниц. Затем мы добавляем текущую страницу к нашему объекту записи, используя метод pdfWriter.addPage(). Этот метод принимает объект страницы, который мы получаем, используя метод PdfFileReader.getPage(). Следующим шагом является создание уникального имени файла, что мы делаем, используя исходное имя файла плюс слово «page» плюс номер страницы. Мы добавляем 1 к текущему номеру страницы, потому что PyPDF2 считает номера страниц, начиная с нуля. Наконец, мы открываем новое имя файла в режиме (режиме wb) записи двоичного файла и используем метод write() класса pdfWriter для сохранения извлеченной страницы на диск. Все извлеченные страницы запишутся в папку dist. Сам код:


Результат:

Найти все страницы, где есть заданный текст


Результат:

Добавление водяного знака с помощью PyPDF2

В пакете PyPDF2 есть метод mergepage(), который использует другой PDF в качестве водяного знака или штампа. Сам PDF файл, который мы хотим, чтобы программа использовала в качестве водяного знака кладем в папку source (в моем случае это mshe-logo-512x512.pdf). Начнем с чтения первой страницы исходного PDF документа и водяного знака. Для чтения файла мы используем класс PdfFileReader(). На втором шаге эти две страницы объединяются с помощью метода mergepage(), после чего результат записывается в выходной файл. Эти три этапа — создание объекта на основе класса PdfFileWriter(), добавление объединенной страницы к этому объекту с помощью метода addPage() и запись нового контента на выходную страницу с помощью метода write(). При этом, получившийся новый PDF файл с водяным знаком появится в папке dist. Сам код:


Результат:

Добавление изображения с помощью PyMuPDF

В данном коде, я добавил в мой PDF файл изображение, которое предварительно положил в папку source (в моем случае это image.jpg). Сам код:


Положение изображения определяется как rectangle (прямоугольник) методом fitz.Rect(), который требует двух пар координат — левый верхний угол (x1,y1) и правый нижний угол (x2,y2) изображения. В PyMuPDF левому верхнему углу страницы соответствуют координаты (0,0). После открытия входного файла и извлечения из него первой страницы с помощью метода insertImage() добавляется наше изображение. Этот метод требует двух параметров — позиционирование с использованием imageRectangle и имя файла изображения для вставки. С помощью метода save() измененный PDF файл сохраняется на диске. Результат:

Добавление штампов с pdfrw

pdfrw — это библиотека Python и утилита, которая читает и записывает PDF файлы. И перед тем как выполнять данное задание, эту библиотеку необходимо будет установить. После этого, мы из данного пакета импортируем три класса — PdfReader PdfWriter и PageMerge. Устанавливаем соответственно объекты чтения/записи, для доступа как к содержимому PDF, так и к нашему изображению. Для каждой страницы в исходном документе вы продолжаем создавать объекты PageMerge, к которому добавляем водяной знак и который отображается всё это с помощью метода render(). Сам код:


Результат:

Удаление страниц с помощью PyMuPDF

Библиотека PyMuPDF включает в себя довольно много сложных методов, которые упрощают удаление страниц из файла PDF. Он позволяет вам указать либо одну страницу (метод deletePage()), либо диапазон номеров страниц (метод deletePageRange()), либо список с номерами страниц (метод select()). В следующем примере будет показано, как использовать список для выбора страниц, которые следует сохранить из исходного документа. Имейте в виду, что страницы, которые не указаны, не будут частью выходного документа. В нашем случае выходной документ содержит только первую, вторую и четвертую страницы:


Результат:

I'am tasked with converting tons of .doc files to .pdf. And the only way my supervisor wants me to do this is through MSWord 2010. I know I should be able to automate this with python COM automation. Only problem is I dont know how and where to start. I tried searching for some tutorials but was not able to find any (May be I might have, but I don't know what I'm looking for).

Right now I'm reading through this. Dont know how useful this is going to be.


37.4k 63 63 gold badges 180 180 silver badges 282 282 bronze badges 7,497 11 11 gold badges 34 34 silver badges 41 41 bronze badges

13 Answers 13

A simple example using comtypes, converting a single file, input and output filenames given as commandline arguments:

You could also use pywin32, which would be the same except for:

25.8k 5 5 gold badges 57 57 silver badges 49 49 bronze badges For many files, consider setting: word.Visible = False to save time and processing of the word files (MS word will not display this way, code will run in background essentially) I am using a linux server and these libraries dont work in linux.. is there any other way to make it work in linux

You can use the docx2pdf python package to bulk convert docx to pdf. It can be used as both a CLI and a python library. It requires Microsoft Office to be installed and uses COM on Windows and AppleScript (JXA) on macOS.

Thanks @Todd! Give the repo a star when you get a chance. @Abdelhedihlel Unfortunately, it requires Microsoft Office to be installed and thus only works on Windows and macOS. is there a method to convert word file object to pdf in your module?

(1). The first time when I created the 'Word.Application' object, I should make it (the word app) visible before open any documents. (Actually, even I myself cannot explain why this works. If I do not do this on my computer, the program will crash when I try to open a document in the invisible model, then the 'Word.Application' object will be deleted by OS. )

(2). After doing (1), the program will work well sometimes but may fail often. The crash error "COMError: (-2147418111, 'Call was rejected by callee.', (None, None, None, 0, None))" means that the COM Server may not be able to response so quickly. So I add a delay before I tried to open a document.

After doing these two steps, the program will work perfectly with no failure anymore. The demo code is as below. If you have encountered the same problems, try to follow these two steps. Hope it helps.

Делаю проект на Django, если вкратце - по заполненной пользователем форме формируется файл .docx. Но мне необходимо его переконвертировать в pdf для более удобной работы. Наиболее популярный вариант - с использованием comtypes.

Но вся загвоздка в объявлении переменной(создание объекта) "word = comtypes.client.CreateObject('Word.Application')". При запуске сервера, она создаётся. Но все последующие запросы он обращает в ошибку. "[WinError -2147221008] Не был произведен вызов CoInitialize".
На некоторых форумах писали, что помогает объявление pythoncom.CoInitialize(), но это очень старые записи. Да и сам модуль pythoncom отсутствует в библиотеках.

Буду благодарен за помощь.
Либо какой-то ещё способ преобразования docx - pdf

__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь

Не был произведен вызов CoInitialize при использовании CppWebBrowser
В программе 2 формы: 1 - основная программа 2 - заставка, пока проводится подготовка к работе.

Небыл произведён вызов CoInitialize
При оброщение к функции внешней DLL, каторая открывает окно, получаю ошибку: Небыл произведён вызов.

Конвертация Docx в PDF
День добрый, Суть такая, что с помощью формы я создаю docx документ, с колонтитулами, картинками.

Как получить адрес сервера, откуда был произведен вызов?
кто знает, подскажите, как получить адрес сервера, откуда был произведен вызов. комбинация redirect.

А сразу генерить pdf можно? Это куда проще.

Ну если сервак у вас на никсах - то неудивительно.

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

Добавлено через 2 минуты
А, посмотрел на картинку, видно, что на винде крутится.

Тогда для образца советую найти книжку, что-то типа "Python programming for Win32", она есть в сети, там рабоота с com\ole, разумеется, освещается.

Мне поручено конвертировать тонны файлов .doc в .pdf. И единственный способ, которым мой супервайзер хочет, чтобы я делал это, - через MSWord 2010. Я знаю, что должен быть в состоянии автоматизировать это с помощью автоматизации Python COM. Единственная проблема в том, что я не знаю, как и с чего начать. Я пытался найти некоторые учебные пособия, но не смог их найти (может быть, у меня есть, но я не знаю, что я ищу).

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

Простой пример, использующий comtypes, конвертирующий один файл, входные и выходные имена файлов, заданные в качестве аргументов командной строки:

Вы также можете использовать pywin32, который будет таким же, за исключением:

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

( 1 ) . В первый раз, когда я создал объект «Word.Application», я должен сделать его (приложение Word) видимым, прежде чем открывать какие-либо документы. (На самом деле, даже я сам не могу объяснить, почему это работает. Если я не сделаю этого на моем компьютере, программа произойдет сбой при попытке открыть документ в невидимой модели, тогда объект «Word.Application» будет удален ОПЕРАЦИОННЫЕ СИСТЕМЫ. )

( 2 ) . После выполнения (1) программа иногда будет работать хорошо, но часто может давать сбои. Ошибка сбоя "COMError: (-2147418111, 'Call was rejected by callee.', (None, None, None, 0, None))" означает, что COM-сервер не может отвечать так быстро. Поэтому я добавляю задержку, прежде чем пытаться открыть документ.

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

В качестве альтернативы функции SaveAs вы также можете использовать ExportAsFixedFormat, который дает вам доступ к диалоговому окну параметров PDF, который вы обычно видите в Word. При этом вы можете указать закладки и другие свойства документа.

Полный список аргументов функции: «OutputFileName», «ExportFormat», «OpenAfterExport», «OptimizeFor», «Range», «From», «To», «Item», «IncludeDocProps», «KeepIRM», «CreateBookmarks» ',' DocStructureTags ',' BitmapMissingFonts ',' UseISO19005_1 ',' FixedFormatExtClassPtr '

Вам следует начать с исследования так называемых виртуальных драйверов печати PDF. Как только вы найдете такой файл, вы сможете написать командный файл, который печатает ваши DOC-файлы в PDF-файлы. Вы, вероятно, можете сделать это и в Python (настройте вывод драйвера принтера и введите команду document / print в MSWord, позже это можно сделать с помощью командной строки AFAIR).

Если вы не возражаете против использования PowerShell, взгляните на этот Эй, сценарист! статья. Представленный код может быть принят для использования значения перечисления wdFormatPDF WdSaveFormat (см. здесь ). В этой статье блога представлена другая реализация та же идея

Я попробовал принятый ответ, но не особо заинтересовался раздутыми PDF-файлами, которые выпускал Word, которые обычно были на порядок больше, чем ожидалось. Посмотрев, как отключить диалоговое окно при использовании виртуального PDF-принтера, я наткнулся на Bullzip PDF Printer, и меня довольно впечатлили его возможности. Теперь он заменяет другие виртуальные принтеры, которые я использовал ранее. Вы найдете "бесплатную версию сообщества" на их странице загрузки.

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

Я работал с этим решением, но мне нужно было найти все .docx, .dotm, .docm, .odt, .doc или .rtf и затем включить их все в .pdf (python 3.7.5). Надеюсь, что это работает.

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

Я бы посоветовал игнорировать вашего супервизора и использовать OpenOffice с API-интерфейсом Python. OpenOffice имеет встроенную поддержку Python, и кто-то создал библиотеку, специально предназначенную для этой цели (PyODConverter).

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

Стоит отметить, что ответ Стивенса работает, но убедитесь, что при использовании цикла for для экспорта нескольких файлов для размещения операторов ClientObject или Dispatch перед циклом - его нужно создать только один раз - смотрите мою проблему: Python win32com.client.Dispatch зацикливание документов Word и экспорт в PDF; не удается, когда происходит следующий цикл

Вы можете использовать пакет docx2pdf python для массового преобразования docx в pdf. Его можно использовать как CLI, так и библиотеку Python. Для этого требуется установить Microsoft Office и использовать COM в Windows и AppleScript (JXA) в macOS.

Прекрасно работает для doc, docx, ppt, pptx, xls, xlsx. Очень полезно, если вам нужно конвертировать документы или сохранять / конвертировать в определенные форматы на сервере


Обработка PDF документов

Инструменты и библиотеки

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

В своём исследовании мы учитывали мнения Github-сообщества, а именно:

Читать это руководство, не прорабатывая приведённые в нём примеры, бессмысленно. Поэтому, вооружимся IDLE Python и воспользуемся менеджером пакетов pip или pip3 для установки PyPDF2 и PyMuPDF. Наберём в командной строке (Windows):

Извлечение текста с помощью PyPDF2

Сначала импортируем PdfFileReader , помня о том, что пакет уже установлен. Задаём имя файла из папки source (можете загрузить туда свой файл и поменять Computer-Vision-Resources.pdf в скрипте на имя загруженного файла), открывает документ и получаем информацию о документе, используя метод getDocumentInfo() и общее количество страниц getNumPages() . Далее в цикле for читаем каждую страницу, получаем содержимое page.extractText() и печатаем в stdout .

Обратите внимание, что PyPDF2 начинает считать страницы с 0, и поэтому вызов pdf.getPage(i) при i = 0 извлекает первую страницу документа.

Извлечение текста с помощью PyPDF2

Извлечение текста с помощью PyPDF2

Извлечение текста с помощью PyMuPDF

Перейдём к PyMuPDF.

Отображение информации о документе, печать количества страниц и извлечение текста из документа PDF выполняется аналогично PyPDF2 (см. скрипт ниже). Импортируемый модуль имеет имя fitz , что соответствует имени PyMuPDF в ранних версиях.

Извлечение текста с помощью PyMuPDF

Извлечение текста с помощью PyMuPDF

Извлечение изображений из PDF с помощью PyMuPDF

Переходим к изображениям. PyMuPDF упрощает извлечение изображений из документов PDF с использованием метода getPageImageList() . Скрипт, приведённый ниже, основан на примере из вики-страницы PyMuPDF и извлекает и постранично сохраняет все изображения из PDF в формате PNG. Если изображение имеет цветовое пространство CMYK, оно будет сначала преобразовано в RGB.

Извлечение изображений

Извлечение изображений

Этот скрипт Python извлёк 773 изображения на 400-страничном PDF, размером полгигабайта менее чем за 3 минуты, что удивительно. Отдельные изображения хранятся в формате PNG. Чтобы сохранить исходный формат и размер изображения вместо преобразования в PNG, взгляните на расширенные версии сценариев в вики PyMuPDF .

Для этого примера, в первую очередь необходимо импортировать классы PdfFileReader и PdfFileWriter . Затем мы открываем файл PDF, создаем объект для чтения и перебираем все страницы, используя метод объекта для чтения getNumPages .

Внутри цикла for мы создаем новый экземпляр PdfFileWriter , который еще не содержит страниц. Затем мы добавляем текущую страницу к нашему объекту записи, используя метод pdfWriter.addPage() . Этот метод принимает объект страницы, который мы получаем, используя метод PdfFileReader.getPage() .

Следующим шагом является создание уникального имени файла, что мы делаем, используя исходное имя файла плюс слово «page» плюс номер страницы. Мы добавляем 1 к текущему номеру страницы, потому что PyPDF2 считает номера страниц, начиная с нуля.

Наконец, мы открываем новое имя файла в режиме (режиме wb ) записи двоичного файла и используем метод write() класса pdfWriter для сохранения извлеченной страницы на диск.

Листинг 4: Разделение PDF на отдельные страницы.

Разделили исходный файл на страницы

Разделили исходный файл на страницы

Найти все страницы, где есть заданный текст

Результаты поиска COMPUTER VISION

Результаты поиска COMPUTER VISION

Методы, показанные здесь, довольно мощные. Сравнительно небольшое количество строк кода позволяет легко получить результат. Другие варианты применения рассматриваются во второй части, посвященной добавлению водяного знака и картинок в PDF.

Читайте также: