## Espaço de Tecnologias e Artes - Sesc Avenida Paulista ### `hackmd.io/@sesc-av-paulista/estudos-em-python-14-maio` # Grupo de estudos em Python ## 14/5 Manipulando arquivos PDF ### O que eu preciso para começar? - Vamos usar o **Thonny IDE**, que é livre já com um interpretador Python, você pode baixar em https://thonny.org - Como instalar bibliotecas no Thonny? - **Usando a interface gráfica** menu *Tools/Ferramentas > Manage Packages/Gerenciar Pacotes* - **Usando o shell aberto pelo Thonny** em *Tools > Open System Shell* - Como se faz em geral no Python: `pip install <nome da lib>`, mas idealmente você deve usar um "virtual environment" antes, só que no caso do Thonny provê já esse env ### Algumas bibliotecas - **pdfrw2** - https://github.com/sarnold/pdfrw - **PyMuPDF** (the "fitz" engine) - https://github.com/pymupdf/PyMuPDF - https://pymupdf.readthedocs.io/en/latest/ - Fontes tipograficas extra: https://pypi.org/project/pymupdf-fonts/ ### Script para concatenar (juntar) vários PDFs - Roda no **Thonny**, precisa ter a lib **pdfrw2** instalada! ```python! from pathlib import Path # requer pdfrw2 - https://pypi.org/project/pdfrw2/ from pdfrw import PdfReader, PdfWriter # TROQUE O STRING DE pasta_entrada PELO CAMINHO DA SUA PASTA! pasta_entrada = '/home/villares/Desktop/meus-pdfs' # garante pasta entrada que é um objeto pathlib.Path pasta_entrada = Path(pasta_entrada) # prepara path do arquivo_saida, nome da pasta_entrada + extensao arquivo_saida = pasta_entrada.parent / (pasta_entrada.name + '.pdf') try: writer = PdfWriter(arquivo_saida) # cria gerador do novo PDF # percorre a pasta_entrada for arquivo in sorted(pasta_entrada.iterdir()): if arquivo.suffix.lower() == '.pdf': # convere se é PDF for pagina in PdfReader(arquivo).pages: # pega paginas writer.addpage(pagina) # escreve no arquivo novo writer.write() # salva o arquivo novo de saida print(f'Fusão de PDFs em {arquivo_saida} concluída') except Exception as erro: print(erro) ``` ### Script de fazer zines - Requer a lib **PyMuPDF** - [Código que reordena páginas de um PDF](https://gist.github.com/villares/0402a1c9033e6f4baf55554c16d25f4e) - Confira como executar o script com argumentos na linha de comando a partir do Thonny em https://hackmd.io/@sesc-av-paulista/programazine#Script-que-faz-a-re-ordena%C3%A7%C3%A3o-das-p%C3%A1ginas-de-um-PDF ### Script para sobrepor um PDF em todas as páginas de outro - [Overlay: usando um PDF sobreposto em várias páginas de outro](https://gist.github.com/villares/f99229fd8a3c7b8c51d8b480c93f19ad#file-multiple_page_pdf_py5_module_mode-py) ### Juntando páginas de dois PDFs lado a lado - Este script encolhe fazendo caber quatro páginas por página, duas de cada arquivo original, em colunas paralelas - Precisa da lib `pdfrw2` - Feito para a linha de comando (rola no Thonny) ```python! #! python import sys # Requires pdfrw2 - https://pypi.org/project/pdfrw2/ from pdfrw import PdfReader, PdfWriter, PdfDict, PdfName, PageMerge def write_side_by_side(input_a, input_b, output_file): """ Write to the output file a PDF with the combined contents of 2 input files. Each page gets 2 pages from each of the input files, scaled down by a factor of 0.5, side by side in a 4 pages up layout. """ # Retrieves pagas from both source PDF files left_pages = PdfReader(input_a).pages right_pages = PdfReader(input_b).pages # Fill with blank pages if one source is shorter # and make sure there is an even number of pages while (len(left_pages) % 2 != 0 or len(right_pages) > len(left_pages)): left_pages.append(blank_page(left_pages[0])) while len(right_pages) < len(left_pages): right_pages.append(blank_page(right_pages[0])) # Creates final PDF writer object writer = PdfWriter(output_file) # Loops over the number of pages index, stepping every 2 for index in range(0, len(left_pages), 2): left_slice = left_pages[index:index + 2] # 2 from L right_slice = right_pages[index:index + 2] # 2 from R new_page = render4(left_slice, right_slice) # merge 4 writer.addpage(new_page) # add merged page to result writer.write() def blank_page(template): """Create a blank page from example (to get size)""" p = PdfDict() p.Type = PdfName.Page p.Contents = PdfDict(stream="") p.MediaBox = template.inheritable.MediaBox return p def render4(srcleft, srcright): """ Create a page with 4 scaled down pages, 2 from "left" and to from "right" """ scale = 0.5 srcpages = PageMerge() + srcleft + srcright x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:]) for i, page in enumerate(srcpages): page.scale(scale) page.x = x_increment if i > 1 else 0 page.y = 0 if i % 2 else y_increment return srcpages.render() if __name__ == '__main__': # Command Line Interface try: args = sys.argv input_a, input_b = args[1:3] if len(args) == 4: output = args[3] else: output = 'output.pdf' except: print('Needs 2 PDF files as input arguments. Output name optional.') exit() write_side_by_side(input_a, input_b, output) ``` - Se quiser rodar com os paths dos arquivos no código direto, mudar a parte final do `if __name__ == '__main__':`: ```python! if __name__ == '__main__': input_a = 'arquivo_a.pdf' input_b = 'arquivo_b.pdf' output = 'resultado.pdf' write_side_by_side(input_a, input_b, output) ```