Архив метки: pdf

PyPDF2: новый форк pyPdf (Перевод)

Сегодня узнал, проект pyPDF НЕ умер, как я думал раньше. На самом деле он перешёл в PyPDF2 (видите небольшую разницу в написании?). Есть так же вероятность того, что кто-то занимается и оригинальной версией проекта. При желании, за судьбой PyPDF2 можно следить на reddit. Тем временем я решил посмотреть, чем же PyPDF2 отличается от оригинала. Так что если у Вас есть пара свободных минут — милости просим.

Введение в PyPDF2

Два года назад я уже  писал про pyPDF, а совсем недавно мне как раз пришлось погрузиться в различные библиотеки для работы с PDF на Python, так что появление нового форка пришлось кстати. Мы возьмём несколько моих старых примеров, запустим их в PyPDF2 и посмотрим, как они сработают.
# Соединяем два PDF
from PyPDF2 import PdfFileReader, PdfFileWriter
 
output = PdfFileWriter
()
pdfOne = PdfFileReader
(open( "somepathtoaPDf", "rb"))
pdfTwo = PdfFileReader
(open("someotherpathtoaPDf", "rb"))
 
output.
addPage(pdfOne.getPage(0))
output.
addPage(pdfTwo.getPage(0))
 
outputStream =
open(r"output.pdf", "wb")
output.
write(outputStream)
outputStream.
close()
На моём Windows 7 это сработало без проблем. Как Вы можете предположить, всё, что этот код делает — создаёт два объекта PdfFileReader и прочитывает в каждом первую страницу. После этого, он добавляет эти две страницы в наш PdfFileWriter. И, наконец, мы открываем новый файл и записываем в него PDF. Вот и всё! Мы только что создали новый документ из двух разных PDF!
Теперь давайте попробуем скрипт для поворота страницы из другой моей страницы:
from PyPDF2 import PdfFileWriter, PdfFileReader
 
output = PdfFileWriter()
input1 = PdfFileReader(file("document1.pdf", "rb"))
output.addPage(input1.getPage(1).rotateClockwise(90))
# output.addPage(input1.getPage(2).rotateCounterClockwise(90))
 
outputStream = file("output.pdf", "wb")
output.write(outputStream)
outputStream.close()
Этот скрипт так же сработал на моей машине. Очень даже хорошо. Мой последний тест на соответствие должен проверить, можем ли мы вытаскивать данные так же, как мог оригинальный pyPdf. Давайте попробуем прочитать метаданные:
>>> from PyPDF2 import PdfFileReader
 
>>> p = r'C:UsersmdriscollDocumentsreportlab-userguide.pdf'
 
>>> pdf = PdfFileReader(open(p, 'rb'))
 
>>> pdf.documentInfo
 
{'/ModDate': u'D:20120629155504', '/CreationDate': u'D:20120629155504', '/Producer': u'GPL Ghostscript 8.15', '/Title': u'reportlab-userguide.pdf', '/Creator': u'Adobe Acrobat 10.1.3', '/Author': u'mdriscoll'}
>>> pdf.getNumPages()
 
120
>>> info = pdf.getDocumentInfo()
 
>>> info.author
 
u'mdriscoll'
>>> info.creator
 
u'Adobe Acrobat 10.1.3'
>>> info.producer
 
u'GPL Ghostscript 8.15'
>>> info.title
 
u'reportlab-userguide.pdf'
Тоже очень хорошо, кроме поля автора. Я определённо не автор этого документа и я не знаю, почему PyPDF2  решил, что я им являюсь. Всё остальное сработало верно. Теперь давайте посмотрим, что тут нового.

Что нового в PyPDF2

Одна из вещей, которую я сразу заметил как только взглянул на исходники PyPDF2, это то, что он добавляет несколько новых методов в PdfFileReader и PdfFileWriter. Кроме того, я заметил, что появился совершенно новый модуль merger.py, который содержит класс PdfFileMerger. Поскольку никакой нормальной документации нет — придётся лезть «под капот». Единственный новый метод, который был добавлен в reader — это getOutlines, который позволяет получить эскизы документа (outlines), если они есть. В writer появилась возможность добавить bookmarks и named destinations. Не так уж и много, но дарёному коню в зубы не смотрят. Но больше всего меня вдохновил новый класс PdfFileMerger, который мне напомнил почти погибший проект Stapler. PdfFileMerger позволяет нам объединить несколько PDF в один, используя соединение, вставку и вырезку и их комбинации.
Давайте попробуем?
import PyPDF2
 
path = open('path/to/hello.pdf', 'rb')
path2 = open('path/to/another.pdf', 'rb')
 
merger = PyPDF2.PdfFileMerger()
 
merger.merge(position=0, fileobj=path2)
merger.merge(position=2, fileobj=path)
merger.write(open("test_out.pdf", 'wb'))
Тут мы соединяем два файла вместе. В первый файл вместо третьей страницы будет добавлен второй файл, а как только содержание второго файла закончится будет продолжен первый файл. Это проще, чем проходиться по страницам двух документов и соединять их. Команда merge имеет следующую сигнатуру и строку документации, которая хорошо всё это описывает:
>>> merge(position, file, bookmark=None, pages=None, import_bookmarks=True)
 
Сливает страницы из исходного документа, определённого в
"file" в файл вывода на место, определённое в "position".
 
Опционально Вы можете определить закладку, которая будет установлена на начало этого файла. Для этого надо передать текст закладки в параметре
"bookmark".
 
Вы можете запретить импорт закладок из исходного документа если передадите значение False параметру
"import_bookmarks".
 
Вы можете так же использовать параметр "pages" для того, чтобы добавить только некоторые страницы исходного файла. Для этого надо задать их диапазон.
Есть так же метод append, который аналогичен команде merge, но вместо того, чтобы сливать файлы, он добавляет их в конец исходного файла. Вот скрипт для примера:
import PyPDF2
 
path = open('path/to/hello.pdf', 'rb')
path2 = open('path/to/another.pdf', 'rb')
 
merger = PyPDF2.PdfFileMerger()
 
merger.append(fileobj=path2)
merger.append(fileobj=path)
merger.write(open("test_out2.pdf", 'wb'))
И совсем не больно!

Подводим итоги

Мне кажется, это хорошая альтернатива для работы с PDF. Я могу комбинировать и разделять PDF при помощи PyPDF2 даже проще, чем с оригинальным pyPdf. Кроме того, я надеюсь, что PyPDF не умрёт, так как у него есть спонсоры, оплачивающие его разработку. Согласно потокам reddit есть даже шанс, что оригинальный pyPdf будет переработан и в конце концов оба эти проекта сольются в дружеском экстазе. Но, вне зависимости от того, чем всё закончится, я рад, что разработка его возобновилась и надеюсь, что она не скоро прекратится.

Домашнее чтение

Автор: Ishayahu Lastov

Как вставить документ PDF (пдф) в страницу сайта

Возможностей несколько, но, к сожалению, не все имеют кроссбраузерную поддержку — одни требуют установки плагина, другие вовсе не отражаются. Лучший способ — это вставка кода с использованием скрипта Google Docs Viewer plugin for jQuery. Читать →

Как обрезать поля в pdf файле

Для обрезки полей в Linux есть утилита pdfcrop. Эта утилита является частью пакета texlive-extra-utils:

# apt-get install texlive-extra-utils
$ pdfcrop --clip --margin 5 исходный_файл.pdf целевой_файл.pdf

Автор: Roman Brovko

pisa / xhtml2pdf, конвертер, написанный на Python (Перевод)

Какое-то время назад я познакомился с pisa, которая теперь называется xhtml2pdf. Она написана на Python и может быть использована для конвертации HTML/CSS в PDF.

Вот список некоторых возможностей xhtml2pdf:

  • Переводит HTML и CSS в PDF файлы
  • Написан только на Python и потому платформо-независим
  • Поддерживает колонки, заголовки, колонтитулы, номера страниц, пользовательские шрифты Postscript иTrueType и многое другое
  • Поддерживает фреймворки типа Django, Turbogears, CherryPy, Pylons, WSGI
  • Простая интеграция в программы на Python
  • Может быть использована как утилита командной строки для Windows, MacOS X and Linux (бинарники отсутствуют)

Выглядит, в общем, полезной штукой.

xhtml2pdf: конвертер HTML/CSS в PDF на Python

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

Источник

Автор: Ishayahu Lastov

PyBooklet: создание PDF с двумя страницами на листе для печати (Перевод)

Интересная идея.
PyBooklet может быть полезным дополнением к моей утилите PDFBook (части xtopdf), которое может создавать книжки в PDF из набора текстовых файлов, используя при этом меньшее количество бумаги, что хорошо отразится на окружающей среде.

Автор: Ishayahu Lastov

Введение в pyfpdf – Простая библиотека для создания PDF на Python (Перевод)

Сегодня мы посмотрим на простую библиотеку для создания PDF, которая называется pyfpdf и является портом библиотеки FPDF для PHP. Она не может заменить Reportlab, но даёт Вам более чем простую возможность создавать PDF файлы. Давайте на неё посмотрим.

Установка pyfpdf

К сожалению, у этого пакета не setup.py или eggs, что облегчило бы нам его установку. Вместо этого Вам придётся скачать его, разархивировать и скопировать получившуюся папку в папку site-packages. Последняя версия создаёт папку pyfpdf-1.54b, так что Вам придётся переименовать её в pyfpdf, если Вы хотите использовать примеры из их руководства или из этой статьи. Кроме того, Вы можете просто скопировать его в virtualenv.

Тест-драйв pyfpdf

Как и при знакомстве с любой новой библиотекой, для того, чтобы понять, как она работает, Вам надо написать несколько примеров. Вот простейший код, с помощью которого Вы можете создать PDF:

import pyfpdf
 
pdf = pyfpdf.FPDF(format='letter')
pdf.add_page()
pdf.set_font("Arial", size=12)
pdf.cell(200, 10, txt="Welcome to Python!", align="C")
pdf.output("tutorial.pdf")
Обратите внимание, что когда Вы инициализируете ваш FPDF объект, Вы должны сообщить ему, что хотите, чтобы результат был с размером «letter». По умолчанию его значение «A4». Далее мы должны добавить страницу, задать шрифт и поместить туда какой-нибудь текст. Вызов pdf.cell немного не очевиден. Первые два аргумента — ширина и высота и определяет место, где будет располагаться ваш текст. Параметр align принимает в качестве значения один символ. В нашем случае мы центрируем текст, передавая символ «С». Последняя строка принимает два параметра — имя файла и путь. Если путь не задан, то файл будет располагаться в рабочей папке скрипта.
А что, если мы хотим добавить ещё одну строку? Это можно сделать, добавляя текст в конец файла, добавив ещё одну «ячейку». Если Вам нужен разрыв строки — можно использовать такой код:
import pyfpdf
 
pdf = pyfpdf.FPDF(format='letter')
pdf.add_page()
pdf.set_font("Arial", size=12)
pdf.cell(200, 10, txt="Welcome to Python!", ln=1, align="C")
pdf.cell(200,10,'Powered by FPDF',0,1,'C')
pdf.output("tutorial.pdf")

Добавляем Цацки: заголовки, нижние колонтитулы и разрывы страниц

В руководстве показано, как можно добавить заголовок, нижний колонтитул и разрыв страниц. Но этот способ не работает, так как надо изменить имя метода и код надо переписать, используя this вместо self (не знаю о чём он — прим. пер.). Вот что должно быть в идеале:

import pyfpdf
 
########################################################################
class MyPDF(pyfpdf.FPDF):
""""""
 
#----------------------------------------------------------------------
def header(self):
"""
Заголовок на каждой странице
"
""
# добавляем логотип
self.image("logo.png", x=10, y=8, w=23)
# располагаем логотип справа
self.cell(w=80)
 
# устанавливаем шрифт для заголовка, B=Bold
self.set_font("Arial", style="B", size=15)
# заголовок страницы
self.cell(40,10, "Python Rules!", border=1, ln=0, align="C")
# вставляем разрыв строки в 20 pixels
self.ln(20)
 
#----------------------------------------------------------------------
def footer(self):
"""
Нижний колонтитул на каждой странице
"
""
# располагаем footer в 15mm от конца страницы
self.set_y(-15)
 
# устанавливаем шрифт, I=italic
self.set_font("Arial", style="I", size=8)
 
# отображаем номер страницы по центру
pageNum =
"Page %s/{nb}" % self.page_no()
self.cell(0, 10, pageNum, align="C")
 
#----------------------------------------------------------------------
if __name__ == "__main__":
pdf = MyPDF
()
pdf.
alias_nb_pages()
pdf.
add_page()
pdf.
set_font("Times", size=12)
 
# добавляем несколько строк на страницу
for i in range(1, 50):
pdf.
cell(0, 10, "Line number %s" % i, border=0, ln=1)
pdf.
output("tutorial2.pdf")
Итак, мы создали подкласс FPDF, переопределили его методы header и footer, так как в оригинальном классе они всего лишь заглушки. В нашем заголовке мы создаём объект изображения и задаём его координаты х/у и его ширину w. Кроме того, вы можете передать и его высоту, если Вас беспокоит соотношение сторон. После этого мы его позиционируем и добавляем строку текста для заголовка. Наконец, мы добавляем разрыв строки.
Footer мы помещаем на 15 мм выше конца страницы. Его шрифт — 8pt Arial Italic. Ошибка в официальном руководстве была в том, что он вызывал self.PageNo(), который не существует. Зато есть метод page_no, который, видимо, его заменяет, так что я его и испо
льзовал. Наконец, в конце скрипта мы создаём наш PDF объект и записываем в него несколько строк. Если Вы запустите этот скрипт, Вы получите 3-х страничный документ.

Подведение итогов

В руководстве говорится так же об использовании цветов, но это я оставлю Вам в качестве домашнего задания. Ничего по поводу рисования, вставки таблиц или графиков, встраивания собственных шрифтов и многих других вещей, доступных в Reportlab, я не нашёл, но, опять же, это и предполагалось в качестве простой библиотеки для создания PDF. Если Вам нужны более продвинутые инструменты — смотрите в сторону Reportlab или проектов, созданных на его основе (rst2pds или xhtml2pdf).

Домашнее чтение

Автор: Ishayahu Lastov