Files
INTUIA/Testes/lerpdf.ipynb
T
2026-03-15 13:27:50 +00:00

1096 lines
48 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"#!pip install tabula-py\n",
"#https://ghostscript.com/releases/gsdnld.html\n",
"#pip install PyPDF2\n",
"#!pip install pymupdf\n",
"#!pip install pillow\n",
"\n",
"from reportlab.lib.pagesizes import A4\n",
"from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Image\n",
"from reportlab.lib import colors\n",
"from PIL import Image, ImageOps\n",
"from tkinter import filedialog\n",
"import pandas as pd\n",
"import numpy as np\n",
"import tabula\n",
"import PyPDF2\n",
"import pdfplumber\n",
"from datetime import datetime\n",
"import fitz\n",
"import re\n",
"import os"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div style=\"text-align: center;\">\n",
" <img src=\"https://dl.dropboxusercontent.com/scl/fi/twryk5ou45odi3hdzagsf/TMprocess.png?rlkey=bqixtmkn4qmge1djbfu4ufx6r&st=etgfoobo&dl=0\" alt=\"Texto Alternativo\" />\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a id=\"secao3\"></a>\n",
"Vamos começar por dar um documento PDF para trabalharmos, este vai ser o documento que iremos trabalhar para fazer a extração dos dados.\n",
"\n",
"Para o nosso programa de transcição de inquéritos da PJ/PJM nós precisamos de um documento de identificação que possa identificar neste caso o intervistado.\n",
"\n",
"Esta informação era fácilmente obtida caso tivessemos acesso tanto a Base de dados do Exército (SIG e BDUPE) o que não aconteçe, assim sendo e para contronar esse problema teremos que nos limitar a fornecer a folha de matricula (no caso dos militares) ou a folha do cartão de cidadão no caso dos civis. E apartir daqui extrair a informação de uma forma mais fácil e confiável, para retirarmos as informações necessárias para o programa.\n",
"\n",
"A informação que deve ser retirada para a elaboração do relatório é:\n",
"<a id=\"secao0\"></a>\n",
"- Nome\n",
"- NIF\n",
"- Data de Nascimento\n",
"- Morada\n",
"- Numero do cartão de cidadão\n",
"- Data de Validade do cartão de cidadão\n",
"- NIM (caso seja Militar)\n",
"- Posto (Caso seja Militar)\n",
"- Filiação (Pai e Mãe)\n",
"- Fotografia\n",
"\n",
"No que concerne á Folha de Matricula de um militar a informação que consta na mesma é oriunda de dois sistemas de base de dados o SIG e o BDUPE e têm a seguinte informação:\n",
"\n",
"![Texto Alternativo](https://dl.dropboxusercontent.com/scl/fi/b8y9eqy5ugypil5rnp8pa/FM-Militar.png?rlkey=m2h244ujmd96sgtmmqkr54dgl&st=rroypa23&dl=0)\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
"pdf_path =\"C:\\\\Users\\\\garci\\\\OneDrive\\\\Área de Trabalho\\\\Programa PJM\\\\Programa final\\\\Scripts\\\\FM_dos_militares_\\\\FM_2Sarg_GabrielaSantos.pdf\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Numa fase inicial do trabalho usamos o modulo [`tabula.io`](https://tabula-py.readthedocs.io/en/latest/tabula.html), para transformar a informação do pdf para um dataframe. Contudo os dados tabulares, ou estruturados, estavam dispostos de forma não organizada, e a cada pdf introduzido a informação variava de posição, isto é por exemplo o cc que estaria no valor da matriz [1,1] num pdf novo poderia estar no valor da matriz [0,3]. Assim este módulo não nos servia pois para cada pdf novo o valor da matriz mudaria.\n",
"\n",
"Então optamos pela função abaixo, e neste caso especifico esta função vai buscar a informação da Folha de matricula de um Militar, nomeadamente a imagem (foto) do documento.\n",
"\n",
"Como a imagem do militar é a segunda imagem da folha de matricula, nós extraímos essa imagem, com uma sequela de if e se a imagem não é encontrada, nós extraímos a primeira imagem da folha de matricula. isto para evitar que o programa vá buscar a imagem que se encontra no topo da folha de matricula referente a Republica Portuguesa.\n",
"\n",
"Para isso tivemos que normalizar o path do pdf para evitar problemas com caracteres especiai, para isso usamos o comando [`os.path`](https://docs.python.org/3/library/os.path.html).\n",
"\n",
"Um dos problemas que nos deparamos inicialmente foi que quando extraiamos a informação da imagem, e o programa não identificava a segunda imagem ou seja fazia o nosso ciclo if, a imagem era apresentada em modulo monocromático, assim foi necessário introduzir um bloco de comandos que permitisse que o programa aceite imagens em RGB. [`ImageOps Module`](https://pillow.readthedocs.io/en/stable/reference/ImageOps.html)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def extrairimagemdopdfFM(pdf_path, page_number=0):\n",
" pdf_path = os.path.normpath(pdf_path).replace(\"\\\\\", \"\\\\\\\\\")\n",
" doc = fitz.open(pdf_path)\n",
" pagina = doc[page_number]\n",
" imagem_extraida = False\n",
" for img_index, img in enumerate(pagina.get_images(full=True)):\n",
" if img_index == 1:\n",
" xref = img[0]\n",
" base_image = doc.extract_image(xref)\n",
" image_bytes = base_image[\"image\"]\n",
" image_ext = base_image[\"ext\"]\n",
" image_filename = \"imagem_extraida.jpeg\"\n",
" if not imagem_extraida:\n",
" for img_index, img in enumerate(pagina.get_images(full=True)):\n",
" if img_index == 0:\n",
" xref = img[0]\n",
" base_image = doc.extract_image(xref)\n",
" image_bytes = base_image[\"image\"]\n",
" image_ext = base_image[\"ext\"]\n",
" image_filename = \"imagem_extraida.jpeg\"\n",
" with open(image_filename, \"wb\") as img_file:\n",
" img_file.write(image_bytes)\n",
" imagem = Image.open(image_filename)\n",
" imagem_corrigida = ImageOps.invert(imagem.convert(\"RGB\"))\n",
" imagem_corrigida.save(\"imagem_extraida.jpeg\")\n",
" break \n",
" doc.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Tendo a imagem ou fotografia do militar extraída, podemos extrair a informação necessária para o relatório que [identificamos](#secao0), para isso precisamos de uma função que receba o nosso pdf e procure dentro do mesmo uma palavra que designamos de keyword para isso usamos as funcionalidades existentes na library do [`pdfplumber`](https://azhar-sayyad.medium.com/a-step-by-step-guide-to-parsing-pdfs-using-the-pdfplumber-library-in-python-c12d94ae9f07), sendo que um dos primeiros problemas que tivemos foi com a extração da informação relativamente ao posto, isto porque ao usarmos a função [`extract_text()`](https://pypdf2.readthedocs.io/en/3.x/user/extract-text.html), tal como configuramos, ele extrai o texto da linha que encontra a keyword.\n",
"\n",
"![Texto Alternativo](https://dl.dropboxusercontent.com/scl/fi/g9255755wm17m8mg50wsa/FM-Militar2.png?rlkey=69ow5ocdl3v40e5k6xuiz0uih&st=n7z8vu6o&dl=0)\n",
"\n",
"Assim e de forma a garantir que o output é somente o posto colocou-se um cilco para garantir que a palavra \"AUTENTICAÇÃO\" não aparecia. \n",
"\n",
"A função em baixo procura e devolve apenas o primeiro valor encontrado na página do pdf."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"def extrairinfo(pdf_path, keyword):\n",
" with pdfplumber.open(pdf_path) as pdf:\n",
" for page in pdf.pages:\n",
" text = page.extract_text()\n",
" for line in text.split('\\n'):\n",
" if keyword in line:\n",
" extracted_text = line.split(keyword, 1)[1].strip()\n",
" if \"AUTENTICAÇÃO\" in extracted_text:\n",
" extracted_text = extracted_text.split(\"AUTENTICAÇÃO\", 1)[0].strip()\n",
" return extracted_text\n",
" return None "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A função seguinte faz exatamente o mesmo que a anterior, contudo retorna uma lista com todos os valores encontrados na página do pdf, e não só um."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def extrairinfomaisdificil(pdf_path, keyword):\n",
" resultados = [] \n",
" with pdfplumber.open(pdf_path) as pdf:\n",
" for page in pdf.pages:\n",
" text = page.extract_text()\n",
" for line in text.split('\\n'):\n",
" if keyword in line:\n",
" extracted_text = line.split(keyword, 1)[1].strip()\n",
" if \"AUTENTICAÇÃO\" in extracted_text:\n",
" extracted_text = extracted_text.split(\"AUTENTICAÇÃO\", 1)[0].strip()\n",
" resultados.append(extracted_text)\n",
" \n",
" return resultados"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"O conjunto de operações seguintes retira da folha de matricula do militar, as informações necessárias para o relatório que [identificamos](#secao0) no incio do notebook.\n",
"\n",
"Aproveitamos para retirar mais informação relativamente ao intervistado que vamos necessitar para mais para a frente (colocar ancora)\n",
"\n",
"Aqui houve necessidade de alguns comandos extra para retirar mais informação relativamente por exemplo as datas, onde usamos :\n",
"\n",
"- [Regex](https://pypi.org/project/regex/) para procurar por datas com a formatação de *dd-mm-aaaa*.\n",
"- [Regex](https://pypi.org/project/regex/) para dividir a string para separar texto por exemplo o distrito do concelho.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Portugal'"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"Nacionalidade = extrairinfo(pdf_path, \"País:\")\n",
"Nacionalidade = re.sub(r\"Posto Consular:\\S*.+\",\"\",Nacionalidade).strip()\n",
"Nacionalidade =\" \".join(Nacionalidade.split()[:-2])\n",
"Nacionalidade\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"pai = extrairinfo(pdf_path, \"Pai:\")\n",
"mae = extrairinfo(pdf_path, \"Mãe:\")\n",
"posto = extrairinfo(pdf_path, \"Posto:\")\n",
"nim = extrairinfo(pdf_path, \"NIM:\")\n",
"Nome = extrairinfo(pdf_path, \"Nome:\")\n",
"valor5 = extrairinfo(pdf_path, \"Data de Nascimento:\")\n",
"DTnasc = re.search(r\"\\d{2}-\\d{2}-\\d{4}\", valor5).group()\n",
"Freg = extrairinfo(pdf_path, \"Freguesia:\")\n",
"valor7 = extrairinfo(pdf_path, \"Concelho:\")\n",
"valor7= re.split(r\"\\s+Distrito\", valor7)[0].strip()\n",
"valor8 = extrairinfo(pdf_path, \"Distrito:\")\n",
"valor9 = extrairinfo(pdf_path, \"País:\")\n",
"valor9= re.split(r\"\\s+Posto\", valor9)[0].strip()\n",
"valor10 = extrairinfo(pdf_path, \"Endereço:\")\n",
"valor11 = extrairinfo(pdf_path, \"Código Postal:\")\n",
"valor12 = re.split(r\"\\s+Localidade:\", valor11)[1].strip()\n",
"valor11 = re.split(r\"\\s+Localidade:\", valor11)[0].strip()\n",
"valor13 = extrairinfo(pdf_path, \"Cartão do Cidadão\")\n",
"ccval = re.search(r\"\\d{2}-\\d{2}-\\d{4}\", valor13).group()\n",
"cc = valor13.replace(ccval, \"\").strip()\n",
"nif = extrairinfo(pdf_path, \"Número de Identificação Fiscal\")\n",
"valor16 = extrairinfo(pdf_path, \"Cartão da Segurança Social\")\n",
"valor17 = extrairinfo(pdf_path, \"Telemóvel:\")\n",
"valor17 = re.split(r\"\\s+email:\", valor17)[0].strip()\n",
"valor18 = extrairinfo(pdf_path, \"email:\")\n",
"valor19 = extrairinfomaisdificil(pdf_path, \"Freguesia:\")[1]\n",
"valor20 = extrairinfomaisdificil(pdf_path, \"Concelho:\")[1]\n",
"valor21 = extrairinfomaisdificil(pdf_path, \"Distrito:\")[1]\n",
"valor22 = extrairinfomaisdificil(pdf_path, \"País:\")[1]\n",
"valor22 = re.split(r\"\\s+Posto\", valor22)[0].strip()\n",
"Morada = valor10 +\",\"+ \" \"+ valor11 +\",\"+ \" \"+ valor12+\",\"+ \" \"+ valor19 +\",\"+ \" \"+ valor20\n",
"extrairimagemdopdfFM(pdf_path, page_number=0)\n",
"imagem= \"C:\\\\Users\\\\garci\\\\OneDrive\\\\Área de Trabalho\\\\Programa PJM\\\\Programa final\\\\Scripts\\\\imagem_extraida.jpeg\"\n",
"\n",
"Nacionalidade = extrairinfo(pdf_path, \"Concelho:\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Com o codigo anterior ficamos com a seguinte informação:\n",
"- Nome\n",
"- NIF\n",
"- Data de Nascimento\n",
"- Morada (Endereço + Código Postal + Localidade (valor12) + Freguesia + Concelho)\n",
"- Numero do cartão de cidadão\n",
"- Data de Validade do cartão de cidadão\n",
"- NIM (aqui não se considera se é civil ou não porque a folha de matricula é esclusiva de militares)\n",
"- Posto (aqui não se considera se é civil ou não porque a folha de matricula é esclusiva de militares)\n",
"- Filiação (Pai e Mãe)\n",
"- Fotografia\n",
"\n",
"Os valores como:\n",
"- email\n",
"- Telemóvel\n",
"- Cartão da Segurança Social\n",
"- Local de naschimento (Freguesia. Disctrito, concelho e pais)\n",
"\n",
"Irão ser usados para utilidades mais a frente (colocar ancora)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>Nome</th>\n",
" <td>Wilkerson Amador de Sá</td>\n",
" </tr>\n",
" <tr>\n",
" <th>NIM</th>\n",
" <td>18111822 RC</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Posto</th>\n",
" <td>FUR</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Data de Nascimento</th>\n",
" <td>13-01-2002</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Cartão de Cidadão</th>\n",
" <td>32847447</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Validade do Cartão de Cidadão</th>\n",
" <td>01-10-2026</td>\n",
" </tr>\n",
" <tr>\n",
" <th>NIF</th>\n",
" <td>288272846</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Pai</th>\n",
" <td>WASHINGTON AMADOR</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Mãe</th>\n",
" <td>DIRCE MARIA DE SÁ</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Morada</th>\n",
" <td>RUA NUNO DE BRAGANÇA Nº11 2º B - PORTO SALVO, ...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Imagem</th>\n",
" <td>C:\\Users\\garci\\OneDrive\\Área de Trabalho\\Progr...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" 0\n",
"Nome Wilkerson Amador de Sá\n",
"NIM 18111822 RC\n",
"Posto FUR\n",
"Data de Nascimento 13-01-2002\n",
"Cartão de Cidadão 32847447\n",
"Validade do Cartão de Cidadão 01-10-2026\n",
"NIF 288272846\n",
"Pai WASHINGTON AMADOR\n",
"Mãe DIRCE MARIA DE SÁ\n",
"Morada RUA NUNO DE BRAGANÇA Nº11 2º B - PORTO SALVO, ...\n",
"Imagem C:\\Users\\garci\\OneDrive\\Área de Trabalho\\Progr..."
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dffm=pd.DataFrame({\"Nome\": [Nome], \"NIM\": [nim], \"Posto\": [posto], \"Data de Nascimento\": [DTnasc],\"Cartão de Cidadão\": [cc],\"Validade do Cartão de Cidadão\": [ccval],\"NIF\": [nif], \"Pai\": [pai], \"Mãe\": [mae], \"Morada\": [Morada], \"Imagem\": [imagem]})\n",
"dffm.T"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a id=\"secao2\"></a>\n",
"Tendo o problema da Folha de Matricula resolvido, vamos nos agora fucar na Folha do Cartão de ciadadão.\n",
"\n",
"Por sua vez vamos carregar uma folha do Cartão de Cidadão e realizar a extração dos dados necessários para o relatório.\n",
"\n",
"A estrutura da folha do Cartão de Cidadão é em tudo diferente do que a da folha de matricula do militar. Se a Folha de Matricula aparentava ter uma estrutrua tabelar e dai termos começado com [ctabula.io`](https://tabula-py.readthedocs.io/en/latest/tabula.html) como uma possibilidade, na folha referente ao cartão de cidadão já nem sequer tentamos e continuamos com a mesma lógica da que usamos até aqui.\n",
"\n",
"Esta folha do Cartão de Cidadão possui muito menos informação do que a da folha de matricula do militar. \n",
"\n",
"![Texto Alternativo](https://dl.dropboxusercontent.com/scl/fi/qnaz0ffgaeagygpsa2jmq/cc.png?rlkey=5qi8bfvu4vn8dkgb1bn2dsy1m&st=h6g5ttgb&dl=0)\n",
"\n",
"Neste caso vamos ter que extrair os seguintes dados:\n",
"- Nome\n",
"- NIF\n",
"- Data de Nascimento\n",
"- Morada\n",
"- Numero do cartão de cidadão\n",
"- Data de Validade do cartão de cidadão\n",
"- Filiação (Pai e Mãe)\n",
"- Fotografia"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [],
"source": [
"pdf_path =\"C:\\\\Users\\\\garci\\\\OneDrive\\\\Área de Trabalho\\\\Programa PJM\\\\Programa final\\\\Scripts\\\\Cartão Cidadão\\\\Cartão_de_Cidadão_13182269.pdf\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Á semelhança da folha de matricula, vamos começar por defenir uma função para extrair a fotografia que consta no PDF.\n",
"\n",
"Existem uma particularidade com o pdf do cartão de cidaddão que não existia com o pdf da folha de matricula do militar, que se prende com esta primeira ter muito mais fotografias do que a segunda, assim como tem a assinatura digital que a biblioteca considera como imagem.\n",
"\n",
"Assim como output desta função vão ocorrer várias imagens extraídas e salvas contudo e como vamos ver mais a [frente](#secao1) apenas vamos usar a segunda imagem extraida, mantemos as outras pois poderá ser util para alguma funcionalidade."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"def extrair_imagem_do_pdf(pdf_path):\n",
" doc = fitz.open(pdf_path)\n",
" for page_num in range(len(doc)):\n",
" pagina = doc[page_num]\n",
" for img_index, img in enumerate(pagina.get_images(full=True)):\n",
" xref = img[0]\n",
" base_image = doc.extract_image(xref)\n",
" image_bytes = base_image[\"image\"]\n",
" image_ext = base_image[\"ext\"]\n",
" image_filename = f\"imagem_extraida_{page_num + 1}_{img_index + 1}.{image_ext}\"\n",
" with open(image_filename, \"wb\") as img_file:\n",
" img_file.write(image_bytes)\n",
" print(f\"Imagem extraída e salva como: {image_filename}\")\n",
" doc.close()\n",
" return None"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"No que diz respeito a restante informação necessária o pdf do cartão do cidadão têm uma estrutura diferente quando comparado com a folha de matricula do militar e a informação que procuramos está por sua vez em formato coluna, isto é, se para a folha de matricula a lógica seria procurar a palavra e retirar a informação que se encontrava nas linhas, já para o cartão de cidadão a ideia será procurar a palavra e retirar a informação que se encontrava nas colunas."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"def extrairinfoabaixo(pdf_path, keyword):\n",
" resultados = [] \n",
" with pdfplumber.open(pdf_path) as pdf:\n",
" for page in pdf.pages:\n",
" text = page.extract_text()\n",
" lines = text.split('\\n')\n",
" for i, line in enumerate(lines):\n",
" if keyword in line:\n",
" if i + 1 < len(lines):\n",
" extracted_text = lines[i + 1].strip()\n",
" resultados.append(extracted_text)\n",
" \n",
" return resultados"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Contudo e a parte da filiação não foi possivel fazer com a função anterior, assim foi necessário fazer uma função que fosse buscar a 2a e 3a linha da procura."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"def extrairinfoabaixo3(pdf_path, keyword):\n",
" resultados = [] \n",
" with pdfplumber.open(pdf_path) as pdf:\n",
" for page in pdf.pages:\n",
" text = page.extract_text()\n",
" lines = text.split('\\n')\n",
" for i, line in enumerate(lines):\n",
" if keyword in line:\n",
" for j in range(1, 4):\n",
" if i + j < len(lines):\n",
" extracted_text = lines[i + j].strip()\n",
" resultados.append(extracted_text)\n",
" \n",
" return resultados"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"De frorma homolga a extração da informação da folha do cartão de cidadão foi feita á semelhança do que terá sido feito para a extração da informação constante na folha de matricula do militar.\n",
"Com a ressalva de que a informação como nim e posto no caso da informação extraida pela folha do cartão de cidadão não é possivel ser feita.\n",
"\n",
"Como queremos usar no programa uma funcção (como vamos ver mais a frente(colocar ancora)) que independnetemente da folha carregada ela extraia a informação [solicitada](#secao0), temos que dar as variaveis nim e posto um valor de vazio (\"\")\n",
"\n",
"O conjunto de operações seguintes retira da folha do cartão de cidadão, as informações.\n",
"\n",
"Aqui houve necessidade de alguns comandos extra para retirar mais informação, para alem das já referidas anteriormente, relativamente a separar texto de numeros, isto é isolar apenas parte do vetor que contem texto: :\n",
"\n",
"- [Regex](https://pypi.org/project/regex/) Optamos por este comando [`re.findall(r\"[A-Za-zçÇáÁéÉíÍóÓúÚâÂêÊîÎôÔûÛãÃõÕàÀèÈìÌòÒùÙäÄëËïÏöÖüÜñÑ]+\", valor11)`] garantindo assim que todas as letras assim como todas as letras com acentuação disponiveis no teclado são contempladas, isto porque nada nos garante que os nomes dos individuos não possuam estes caracteres especiais ou espaço em branco e que parem o nosso regex.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['13182269 1ZX3 11-10-2030']"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"valor5 = extrairinfoabaixo(pdf_path, \"Nº cartão\") or \"\"\n",
"valor5"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [
{
"ename": "TypeError",
"evalue": "expected string or bytes-like object, got 'list'",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[1;32mIn[48], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m valor6 \u001b[38;5;241m=\u001b[39m \u001b[43mre\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msearch\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43mr\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m\\\u001b[39;49m\u001b[38;5;124;43md\u001b[39;49m\u001b[38;5;132;43;01m{2}\u001b[39;49;00m\u001b[38;5;124;43m-\u001b[39;49m\u001b[38;5;124;43m\\\u001b[39;49m\u001b[38;5;124;43md\u001b[39;49m\u001b[38;5;132;43;01m{2}\u001b[39;49;00m\u001b[38;5;124;43m-\u001b[39;49m\u001b[38;5;124;43m\\\u001b[39;49m\u001b[38;5;124;43md\u001b[39;49m\u001b[38;5;132;43;01m{4}\u001b[39;49;00m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mvalor5\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mgroup()\n\u001b[0;32m 2\u001b[0m valor6\n",
"File \u001b[1;32mc:\\Users\\garci\\anaconda32\\Lib\\re\\__init__.py:177\u001b[0m, in \u001b[0;36msearch\u001b[1;34m(pattern, string, flags)\u001b[0m\n\u001b[0;32m 174\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21msearch\u001b[39m(pattern, string, flags\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m0\u001b[39m):\n\u001b[0;32m 175\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Scan through string looking for a match to the pattern, returning\u001b[39;00m\n\u001b[0;32m 176\u001b[0m \u001b[38;5;124;03m a Match object, or None if no match was found.\"\"\"\u001b[39;00m\n\u001b[1;32m--> 177\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_compile\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpattern\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mflags\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msearch\u001b[49m\u001b[43m(\u001b[49m\u001b[43mstring\u001b[49m\u001b[43m)\u001b[49m\n",
"\u001b[1;31mTypeError\u001b[0m: expected string or bytes-like object, got 'list'"
]
}
],
"source": [
"valor6 = re.search(r\"\\d{2}-\\d{2}-\\d{4}\", valor5).group()\n",
"valor6"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Imagem extraída e salva como: imagem_extraida_1_1.jpeg\n",
"Imagem extraída e salva como: imagem_extraida_1_2.jpeg\n",
"Imagem extraída e salva como: imagem_extraida_1_3.png\n",
"Imagem extraída e salva como: imagem_extraida_1_4.png\n"
]
}
],
"source": [
"valor1 = extrairinfoabaixo(pdf_path, \"Apelido(s)\")\n",
"valor2 = extrairinfoabaixo(pdf_path, \"Nome(s)\")\n",
"valor3 = valor2+valor1\n",
"valor3 = \" \".join(valor3)\n",
"Nome=valor3\n",
"nim=\"\"\n",
"posto=\"\"\n",
"valor4 = extrairinfoabaixo(pdf_path, \"Nascimento\")\n",
"valor4 = \"\".join(valor4)\n",
"valor4 = re.search(r\"\\d{2}-\\d{2}-\\d{4}\", valor4).group()\n",
"DTnasc =valor4\n",
"valor5 = extrairinfoabaixo(pdf_path, \"Nº cartão\")\n",
"valor5 = \"\".join(valor5)\n",
"valor6 = re.search(r\"\\d{2}-\\d{2}-\\d{4}\", valor5).group()\n",
"valor7 = valor5.replace(valor6, \"\").strip()\n",
"valor8 = extrairinfoabaixo3(pdf_path, \"Morada\")[:2]\n",
"Morada = \"\".join(valor8)\n",
"valor10 = extrairinfoabaixo3(pdf_path, \"Filiação\")[2]\n",
"mae=valor10\n",
"valor11 = extrairinfoabaixo3(pdf_path, \"Filiação\")[1]\n",
"valor12 = re.findall(r\"\\d+\", valor11)\n",
"valor13 = valor12[0]\n",
"cc=valor7\n",
"ccval=valor6\n",
"nif=valor13\n",
"valor14 = valor12[1]\n",
"valor15 = valor12[2]\n",
"valor11 =re.findall(r\"[A-Za-zçÇáÁéÉíÍóÓúÚâÂêÊîÎôÔûÛãÃõÕàÀèÈìÌòÒùÙäÄëËïÏöÖüÜñÑ]+\", valor11)\n",
"valor11 = \" \".join(valor11)\n",
"pai=valor11\n",
"extrair_imagem_do_pdf(pdf_path)\n",
"imagem = \"C:\\\\Users\\\\garci\\\\OneDrive\\\\Área de Trabalho\\\\Programa PJM\\\\Programa final\\\\Scripts\\\\imagem_extraida_1_2.jpeg\"\n"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'PT'"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Nacionalidade = extrairinfoabaixo(pdf_path, \"Nascimento\")\n",
"Nacionalidade = \"\".join(Nacionalidade)\n",
"Nacionalidade = Nacionalidade.split()[2]\n",
"Nacionalidade"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Com o codigo anterior ficamos com a seguinte informação:\n",
"- Nome\n",
"- NIF \n",
"- Data de Nascimento\n",
"- Morada \n",
"- Numero do cartão de cidadão\n",
"- Data de Validade do cartão de cidadão\n",
"- NIM (relembrar que o valor vai ser vazio)\n",
"- Posto (relembrar que o valor vai ser vazio)\n",
"- Filiação (Pai e Mãe)\n",
"- Fotografia"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>Nome</th>\n",
" <td>José Antónioda Silva Pinto Garcia</td>\n",
" </tr>\n",
" <tr>\n",
" <th>NIM</th>\n",
" <td></td>\n",
" </tr>\n",
" <tr>\n",
" <th>Posto</th>\n",
" <td></td>\n",
" </tr>\n",
" <tr>\n",
" <th>Data de Nascimento</th>\n",
" <td>18-08-1988</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Cartão de Cidadão</th>\n",
" <td>13182269 1ZX3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Validade do Cartão de Cidadão</th>\n",
" <td>11-10-2030</td>\n",
" </tr>\n",
" <tr>\n",
" <th>NIF</th>\n",
" <td>221417877</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Pai</th>\n",
" <td>José António dos Santos Pinto</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Mãe</th>\n",
" <td>Maria Fernanda da Silva Leitão Pinto</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Morada</th>\n",
" <td>Est Reg 247, 24, moradia 5 Baleia2655-132 CARV...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>Imagem</th>\n",
" <td>C:\\Users\\garci\\OneDrive\\Área de Trabalho\\Progr...</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" 0\n",
"Nome José Antónioda Silva Pinto Garcia\n",
"NIM \n",
"Posto \n",
"Data de Nascimento 18-08-1988\n",
"Cartão de Cidadão 13182269 1ZX3\n",
"Validade do Cartão de Cidadão 11-10-2030\n",
"NIF 221417877\n",
"Pai José António dos Santos Pinto\n",
"Mãe Maria Fernanda da Silva Leitão Pinto\n",
"Morada Est Reg 247, 24, moradia 5 Baleia2655-132 CARV...\n",
"Imagem C:\\Users\\garci\\OneDrive\\Área de Trabalho\\Progr..."
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dfcc=pd.DataFrame({\"Nome\": [Nome], \"NIM\": [nim], \"Posto\": [posto], \"Data de Nascimento\": [DTnasc],\"Cartão de Cidadão\": [cc],\"Validade do Cartão de Cidadão\": [ccval],\"NIF\": [nif], \"Pai\": [pai], \"Mãe\": [mae], \"Morada\": [Morada], \"Imagem\": [imagem]})\n",
"dfcc.T"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a id=\"secao1\"></a>\n",
"Agora o interessante e o desafio está em idenpendentemente do que seja introduzido no programa ele consiga retirar informações [necessárias](#secao0), para isso é necessário identificarmos uma caractaristica única do documento para que o programa possa decidir como vair retirar a informação, com as duas divisões que fizemos até aqui, [Folha de Matricula do Militar](#secao3) ou [Folha do Cartão de Cidadão](#secao2).\n",
"\n",
"Esta caracteristica unica no nosso caso foi procurar se no pdf selecionado continha \"MINISTÉRIO DA DEFESA NACIONAL\". Em caso positivo executa a função necessária para retirar as informações da [Folha de Matricula do Militar](#secao3) caso contrário execita todos os comandos necessários para [Folha do Cartão de Cidadão](#secao2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def retirarinfodafolha(pdf_path):\n",
" valor100=extrairinfo(pdf_path, \"MINISTÉRIO DA DEFESA NACIONAL\")\n",
" if valor100 is not None:\n",
" pai = extrairinfo(pdf_path, \"Pai:\")\n",
" mae = extrairinfo(pdf_path, \"Mãe:\")\n",
" posto = extrairinfo(pdf_path, \"Posto:\")\n",
" nim = extrairinfo(pdf_path, \"NIM:\")\n",
" Nome = extrairinfo(pdf_path, \"Nome:\")\n",
" valor5 = extrairinfo(pdf_path, \"Data de Nascimento:\")\n",
" DTnasc = re.search(r\"\\d{2}-\\d{2}-\\d{4}\", valor5).group()\n",
" Freg = extrairinfo(pdf_path, \"Freguesia:\")\n",
" valor7 = extrairinfo(pdf_path, \"Concelho:\")\n",
" valor7= re.split(r\"\\s+Distrito\", valor7)[0].strip()\n",
" valor8 = extrairinfo(pdf_path, \"Distrito:\")\n",
" valor9 = extrairinfo(pdf_path, \"País:\")\n",
" valor9= re.split(r\"\\s+Posto\", valor9)[0].strip()\n",
" valor10 = extrairinfo(pdf_path, \"Endereço:\")\n",
" valor11 = extrairinfo(pdf_path, \"Código Postal:\")\n",
" valor12 = re.split(r\"\\s+Localidade:\", valor11)[1].strip()\n",
" valor11 = re.split(r\"\\s+Localidade:\", valor11)[0].strip()\n",
" valor13 = extrairinfo(pdf_path, \"Cartão do Cidadão\")\n",
" ccval = re.search(r\"\\d{2}-\\d{2}-\\d{4}\", valor13).group()\n",
" cc = valor13.replace(ccval, \"\").strip()\n",
" nif = extrairinfo(pdf_path, \"Número de Identificação Fiscal\")\n",
" valor16 = extrairinfo(pdf_path, \"Cartão da Segurança Social\")\n",
" valor17 = extrairinfo(pdf_path, \"Telemóvel:\")\n",
" valor17 = re.split(r\"\\s+email:\", valor17)[0].strip()\n",
" valor18 = extrairinfo(pdf_path, \"email:\")\n",
" valor19 = extrairinfomaisdificil(pdf_path, \"Freguesia:\")[1]\n",
" valor20 = extrairinfomaisdificil(pdf_path, \"Concelho:\")[1]\n",
" valor21 = extrairinfomaisdificil(pdf_path, \"Distrito:\")[1]\n",
" valor22 = extrairinfomaisdificil(pdf_path, \"País:\")[1]\n",
" valor22 = re.split(r\"\\s+Posto\", valor22)[0].strip()\n",
" Morada = valor10 +\",\"+ \" \"+ valor11 +\",\"+ \" \"+ valor12+\",\"+ \" \"+ valor19 +\",\"+ \" \"+ valor20\n",
" extrairimagemdopdfFM(pdf_path, page_number=0)\n",
" imagem= \"C:\\\\Users\\\\garci\\\\OneDrive\\\\Área de Trabalho\\\\Programa PJM\\\\Programa final\\\\Scripts\\\\imagem_extraida.jpeg\"\n",
" else:\n",
" valor1 = extrairinfoabaixo(pdf_path, \"Apelido(s)\")\n",
" valor2 = extrairinfoabaixo(pdf_path, \"Nome(s)\")\n",
" valor3 = valor2+valor1\n",
" valor3 = \"\".join(valor3)\n",
" Nome=valor3\n",
" nim=\"\"\n",
" posto=\"\"\n",
" valor4 = extrairinfoabaixo(pdf_path, \"Nascimento\")\n",
" valor4 = \"\".join(valor4)\n",
" valor4 = re.search(r\"\\d{2}-\\d{2}-\\d{4}\", valor4).group()\n",
" DTnasc =valor4\n",
" valor5 = extrairinfoabaixo(pdf_path, \"Nº cartão\")\n",
" valor5 = \"\".join(valor5)\n",
" valor6 = re.search(r\"\\d{2}-\\d{2}-\\d{4}\", valor5).group()\n",
" valor7 = valor5.replace(valor6, \"\").strip()\n",
" valor8 = extrairinfoabaixo3(pdf_path, \"Morada\")[:2]\n",
" Morada = \"\".join(valor8)\n",
" valor10 = extrairinfoabaixo3(pdf_path, \"Filiação\")[2]\n",
" mae=valor10\n",
" valor11 = extrairinfoabaixo3(pdf_path, \"Filiação\")[1]\n",
" valor12 = re.findall(r\"\\d+\", valor11)\n",
" valor13 = valor12[0]\n",
" cc=valor7\n",
" ccval=valor6\n",
" nif=valor13\n",
" valor14 = valor12[1]\n",
" valor15 = valor12[2]\n",
" valor11 =re.findall(r\"[A-Za-zçÇáÁéÉíÍóÓúÚâÂêÊîÎôÔûÛãÃõÕàÀèÈìÌòÒùÙäÄëËïÏöÖüÜñÑ]+\", valor11)\n",
" valor11 = \" \".join(valor11)\n",
" pai=valor11\n",
" extrair_imagem_do_pdf(pdf_path)\n",
" imagem = \"C:\\\\Users\\\\garci\\\\OneDrive\\\\Área de Trabalho\\\\Programa PJM\\\\Programa final\\\\Scripts\\\\imagem_extraida_1_2.jpeg\"\n",
" return Nome, nim, posto, DTnasc, cc, ccval, nif, pai, mae, Morada, imagem"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"O comando seguinte é a operacionalização do bloco do codigo anterior, disponibilidazando ao utilizador a possibilidade de escoljer um ficheiro pdf para a extração das informações necessárias."
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('David José Ângelo Fonseca',\n",
" '11651621 RC',\n",
" 'SOLD',\n",
" '02-12-2001',\n",
" '31240392 ZX8',\n",
" '30-05-2028',\n",
" '280952228',\n",
" 'FRANCISCO ANTONIO NUNES FONSECA',\n",
" 'MARGARIDA DOS SANTOS ANGELO',\n",
" 'RUA DA IGREJA Nº 19, 3400 733, SÃO SEBASTIÃO DA FEIRA, Penalva de Alva e São Sebastião da Feira, Oliveira do Hospital',\n",
" 'C:\\\\Users\\\\garci\\\\OneDrive\\\\Área de Trabalho\\\\Programa PJM\\\\Programa final\\\\Scripts\\\\imagem_corrigida.jpeg')"
]
},
"execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pdf_path = filedialog.askopenfilename(filetypes=[(\"PDF files\", \"*.pdf\")])\n",
"retirarinfodafolha(pdf_path)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ora chegamos ao ponto em que temos a informação necessária para o programa em si.\n",
"\n",
"![Texto Alternativo](https://dl.dropboxusercontent.com/scl/fi/szf2i1ldohyb1uti1xl14/Menuprincipal.png?rlkey=bb71gw79rs4e8kds45yj9u2u6&st=4fs749zn&dl=0)\n",
"\n",
"Sendo que já temos até aqui práticamente tudo para que no programa esta informação seja colocada de forma a que o utilizador consiga a consultar facilmente falta então dar-mos a parte gráfica da mesma:\n",
"\n",
"- No nosso caso e para a vertente visual pouco interessa se o indiviuo é militar ou não, como tal juntamos as variaveis posto,nim e nome\n",
"- Assim como juntamos a validade do cartão de cidadão e a sua data de validade\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Postonimnome=posto+\" \"+nim+ \" \" +Nome\n",
"cceval=cc+\" válido até \"+ccval"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Assim e para conseguir a vertente visual no tkinter foi usado o pacote desta libraria que permite desenhar e manipular imagens, [Canvas](https://www.tutorialspoint.com/python/tk_canvas.htm) aplicamos o mesmo e disposemos a informação de forma a ser legivel para os usuários.\n",
"\n",
"```python\n",
"def mostrar_dados(parent_frame):\n",
" dados = Nome, nim, posto, DTnasc, cc, ccval, nif, pai, mae, Morada, imagem\n",
" for widget in parent_frame.winfo_children():\n",
" widget.destroy()\n",
" canvas = Canvas(parent_frame, width=600, height=400, bg=\"#2B2B2B\", highlightthickness=0)\n",
" canvas.grid(row=0, column=0, sticky=\"nsew\")\n",
" Postonimnome=posto+\" \"+nim+ \" \" +Nome\n",
" cceval=cc+\" válido até \"+ccval\n",
" \n",
" labels = [(\"Nome\", Postonimnome),(\"Data de Nascimento\", DTnasc),(\"Cartão de Cidadão\", cceval),(\"NIF\", nif),(\"Pai\", pai),(\"Mãe\", mae),(\"Morada\", Morada)]\n",
" y_position=10\n",
" for label_text, value in labels:\n",
" label = f\"{label_text}: {value}\"\n",
" wrapped_label = wrap_text(label, max_length=80) \n",
" canvas.create_text(10, y_position, anchor=\"nw\", text=wrapped_label, font=(\"Arial\", 10), fill=\"white\")\n",
" y_position += 40\n",
" try:\n",
" if imagem:\n",
" img = Image.open(imagem)\n",
" img = img.resize((150, 150))\n",
" img_tk = ImageTk.PhotoImage(img)\n",
" canvas.create_image(550, 10, anchor=\"ne\", image=img_tk)\n",
" canvas.image = img_tk \n",
" except Exception as e:\n",
" print(f\"Erro ao carregar a imagem: {e}\")\n",
"```\n",
"\n",
"O comando anterior tem o seguinte output no progrma em si (alguma informação pessoal mais sensivel foi removida prepositadamente, sendo que o programa pode ser visto a ser executado aquando a apresentação)\n",
"\n",
"![Texto Alternativo](https://dl.dropboxusercontent.com/scl/fi/v7ougbin990yn5iwv80el/Loyotpessoa.png?rlkey=3mscel1ylch706jf6y7lldirz&st=qfzsg8qc&dl=0)\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A informação do intervistado é utilizada tambem para o preenchimento dos relatórios que se encontram representados em cima pelos ficheiros pdf e word. Estes relatórios visam ser uma copia exata dos relatórios em uso na PJM, onde são constituidos pelo seguinte:\n",
"\n",
"![Texto Alternativo](https://dl.dropboxusercontent.com/scl/fi/ewrur2sg6el5yb1yi8il9/exemplorel.png?rlkey=6gru90rvk4d17nvf6d0s9zix4&st=wzgwkt2j&dl=0)\n",
"\n",
"Para isso criamos um vector com a informação referida e para aplicar-mos a mesma informação\n",
"\n",
"```python\n",
" cabecalho = [(\"RESERVADO\",red),('MINISTÉRIO DA DEFESA NACIONAL', black),('FORÇAS ARMADAS',black),('ESTADO-MAIOR DAS FORÇAS ARMADAS',black), ('RELATÓRIO DE ENTERVISTA - PJM',black)]\n",
"```\n",
"\n",
"Para aplicar esta informação da forma como foi apresentada foi então necessário a criação de uma função que chama-se a o cabeçalho sempre que necessário, ou seja sempre que seja necessário criar mais uma página para isso e na função que gera o relatório foram ciradas duas funções\n",
"\n",
"- Uma que define a latura da página\n",
"```python\n",
"def check_y_position():\n",
" nonlocal y_position\n",
" if y_position < 40:\n",
" c.showPage()\n",
" y_position = altura - 72\n",
" adicionar_cabecalho()\n",
"```\n",
"- E outra que coloca o cabeçalho de acordo com as nossas definições\n",
"```python\n",
"def adicionar_cabecalho():\n",
" nonlocal y_position\n",
" c.setFont(\"Helvetica-Bold\", 12)\n",
" c.setFillColor(black)\n",
" y_position = altura - 72\n",
" c.setFillColor(cabecalho[0][1])\n",
" c.setFont(\"Helvetica-Bold\", 14)\n",
" text_width = c.stringWidth(cabecalho[0][0], \"Helvetica\", 12)\n",
" c.drawString((largura - text_width) / 2, y_position, cabecalho[0][0])\n",
" y_position -= 30\n",
" \n",
" c.drawImage(caminho_imagem, (largura - 50) / 2, y_position - 20, width=40, height=40)\n",
" y_position -= 50\n",
" \n",
" for line, color in cabecalho[1:]:\n",
" check_y_position()\n",
" c.setFillColor(color)\n",
" text_width = c.stringWidth(line, \"Helvetica-Bold\", 14)\n",
" c.drawString((largura - text_width) / 2, y_position, line)\n",
" y_position -= 20\n",
" adicionar_cabecalho()\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('RUA NUNO DE BRAGANÇA Nº11 2º B - PORTO SALVO, 2740 282, PORTO SALVO, Porto Salvo, Oeiras',\n",
" 'Filho de WASHINGTON AMADOR e de DIRCE MARIA DE SÁ',\n",
" 'com 22 anos',\n",
" 'Com o numero de cartão de cidadão 32847447, válido até 01-10-2026')"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Morada = valor10 +\",\"+ \" \"+ valor11 +\",\"+ \" \"+ valor12+\",\"+ \" \"+ valor19 +\",\"+ \" \"+ valor20\n",
"Filiação = \"Filho de \" + pai + \" e de \" + mae\n",
"idade = datetime.strptime(DTnasc, \"%d-%m-%Y\")\n",
"dataatual = datetime.now()\n",
"idade =dataatual.year - idade.year - ((dataatual.month, dataatual.day) < (idade.month, idade.day))\n",
"idade\n",
"idadeescrito=f\"com {idade} anos\"\n",
"cartac=f\"Com o numero de cartão de cidadão {cc}, válido até {ccval}\"\n",
"\n",
"\n",
"Morada, Filiação, idadeescrito,cartac"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}