-
-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Prototipo funcional] data-processing e Associação AMA exoonero #44
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Winzen, obrigado pelo submissão do PR.
Parabéns por ter conseguido chegar em um protótipo funcional!
Olhei brevemente o código e apontei alguns pontos de melhoria, peço que avalie se as sugestões fazem sentido pra você. Também levantei alguns questionamentos, responda quando possível
README.md
Outdated
# Objetivos inicias e principais | ||
- [x] Segmentar Diarios dentro do storage(Separados por id e suas datas). | ||
- [x] Fazer o registros dos metadados dos diarios segmetados. | ||
- [x] Fazer a indexação dos diarios segmetados com elasticsearch. | ||
# Passos a serem adicionados e melhorados. | ||
- [x] Criar verificador no registro dos metadados para evitar duplicados. ➡️ [Parte a modificar](https://github.com/Winzen/querido-diario-data-processing/blob/prototype/tasks/gazette_text_extraction.py#L272) | ||
- [ ] Verificar melhor formar de tratar duplicadas.(Naturalmente o projeto já evita que elas seram adicionadas. Porém, ele levanta um erro e para o processo) | ||
- [ ] Colocar um tratador de erro caso ele não consiga pegar territory_id. ➡️ [Parte a modificar](https://github.com/Winzen/querido-diario-data-processing/blob/prototype/tasks/get_territorie_info.py#L5) | ||
- [x] Verificar porque aparamente ele não esta conseguindo processar todos os pdfs de uma vez | ||
- [ ] Criar `self.url` corretamente usando o `get_file_endpoint()`.➡️ [Parte a modificar](https://github.com/Winzen/querido-diario-data-processing/blob/prototype/tasks/diario_municipal.py#L72) | ||
- [ ] Atualização da documentação. | ||
- [ ] Como conectar querido-diario e data-processing(lembrar de falar do csv) | ||
- [ ] Configurar ambiente no windons(wsl) | ||
- [ ] Verificar se está com um consumo excessivo de ram |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Acredito que o melhor lugar para documentar as melhorias futuras seja nas Issues. Nesse caso, sugiro formatar essas ideias e abrir novas issues com esse conteúdo
database/postgresql.py
Outdated
@@ -49,9 +49,12 @@ def _commit_changes(self, command: str, data: Dict = {}) -> None: | |||
cursor.execute(command, data) | |||
self._connection.commit() | |||
|
|||
def select(self, command: str) -> Iterable[Tuple]: | |||
def select(self, command: str, data: Dict = {}) -> Iterable[Tuple]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
É estranho um comando de select receber um conjunto de dados para executar. Não seria melhor usar a função de insert?
tasks/diario_municipal.py
Outdated
municipio = municipio.rstrip().replace('\n', '') # limpeza inicial | ||
# Alguns nomes de municípios possuem um /AL no final, exemplo: Viçosa no diário 2022-01-17, ato 8496EC0A. Para evitar erros como "vicosa-/al-secretaria-municipal...", a linha seguir remove isso. | ||
municipio = re.sub("(\/AL.*|GABINETE DO PREFEITO.*|PODER.*|http.*|PORTARIA.*|Extrato.*|ATA DE.*|SECRETARIA.*|Fundo.*|SETOR.*|ERRATA.*|- AL.*|GABINETE.*)", "", municipio) | ||
self.id = self._computa_id(municipio) | ||
self.nome = municipio |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sugiro separar a lógica de extração do nome do município da classe que representa o município. A regex não é uma característica do município, mas sim um padrão de publicação da associação
tasks/diario_municipal.py
Outdated
self.id = self._computa_id(municipio) | ||
self.nome = municipio | ||
|
||
def _computa_id(self, nome_municipio): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def _recupera_id_ibge(self, nome_municipio):
tasks/get_territorie_info.py
Outdated
state = state.strip() | ||
name = limpar_name(name) | ||
|
||
for territorie in territories: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for territory in territories:
tasks/diario_municipal.py
Outdated
""" | ||
m = hashlib.md5() | ||
while True: | ||
d = file.read(8096) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Algum motivo para esse limite?
tasks/extrair_diarios.py
Outdated
def extrarir_diarios(pdf_text, path_pdf, territories): | ||
|
||
diarios = extrair_diarios_municipais(pdf_text, path_pdf, territories) | ||
|
||
return diarios |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A função extrair_diarios está atuando como um proxy para extrair_diarios_municipais. Não seria melhor fazer a chamada de forma direta?
tasks/gazette_text_extraction.py
Outdated
gazette, database, storage, index, text_extractor | ||
) | ||
|
||
if str(gazette["territory_id"][-4:]).strip() == "0000": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Houve um acordo para as associações terem um territory_id com o sufixo "0000"?
tasks/gazette_text_extraction.py
Outdated
|
||
for diario in diarios: | ||
|
||
duplicates = seach_for_duplicate(diario, database) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A necessidade de buscar por duplicatas na base surgiu por qual motivo?
for territorie in database.select(command): | ||
territories.append(format_territories_data(territorie)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
territories = [format_territories_data(territory) for territory in database.select(command)]
- Cria módulo `segmentation` para organizar o código dos segmentadores - O módulo segue o padrão de classe base e classes derivadas para cada segmentador específico - O primeiro segmentador base é o `AssociationSegmenter` para segmentar documentos de associações de municípios - Uma dataclass para segmentos `GazetteSegment` também foi criada - Os segmentadores são instanciados por meio de uma fábrica `get_segmenter`
Deleta módulo associations para usar o segmentation Remove arquivo sem uso Move funções relacionadas aos territórios para um único arquivo Move arquivo que lida com territórios para o módulo utils Atualiza referências para o módulo territories Troca referência para o módulo segmentation Remove atribuição da url para usar a url da associação Remove uso dos territórios nos módulos superiores aos de segmentação Remove tratamento de exceção para nomes errados na limpeza Refatora forma de obtenção dos dados dos territórios Corrige type hinting da segmentação da AMA Adiciona chamada para obter os territórios para os segmentadores Corrige type hint no módulo segmentation factory Remove tratamentos específicos de associações do módulo territories Adapta segmentador da AMA para obter o territory id dos segmentos Correções no processo de extração Remove construção da url ao fazer upload do conteúdo dos segmentos
Torna a busca pelos territórios em uma task Melhora a obtenção de dados do município a partir do nome Trata erros que ocorreram em diários recentes Lança exceção ao obter território se este não for encontrado Faz ajustes para não ser preciso instanciar a database no segmentador Refatora bifurcação entre diários normais e de associações Modifica uso de territories e gazette por segmentadores Territories agora são utilizados por segmentadores por meio de um atributo de instância criado na inicialização da classe. Também não parecia necessária a atribuição do objeto `Gazette` à instância do segmentador, então o objeto passa a ser usado apenas como argumento na `.get_gazette_segments()` e não mais na inicialização. Como a instância do segmentador pode ser reutilizada sem problemas, um padrão de singleton foi utilizado na criação das instâncias. Corrige segmentação com marcador de início falso Na edição de 7 de Dezembro de 2023 do diário da Associação dos Municípios Alagoanos, o diário de Dois Riachos possui o cabeçalho ``` ESTADO DE ALAGOAS PREFEITURA MUNICIPAL DE EDUCAÇÃO SECRETARIA MUNICIPAL DE EDUCAÇÃO DE DOIS RIACHOS ``` no meio do texto de um ato. Isso fazia com que a segmentação fosse engatilhada novamente, resultando em um segmento anterior quase vazio (praticamente apenas o cabeçalho) e o segmento atual com o nome de município incorreto ("EDUCAÇÃO"). Agora, a palavra EDUCAÇÃO foi inserida no regex como uma exceção notável. Refatora mapeamento de município para python-slugify Biblioteca já implementa as transformações que usamos e ainda provê mais funcionalidades. Agora, a chave criada para um município fica em formato mais clássico de slug ("uf-nome-municipio"). Refatora split_text de al_associacao_municipios O método `split_text_by_territory()` estava com problemas de extração incompleta. Ex: ``` { "_index" : "querido-diario", "_type" : "_doc", "_id" : "7b7ed1557de74c25cff6a04023ed525f", "_score" : null, "_source" : { "id" : 6, "territory_name" : "Maribondo", "source_text" : "Alagoas , 02 de Outubro de 2023 • Diário Oficial dos Municípios do Estado de Alagoas • ANO XI | Nº 2145", "date" : "2023-10-02", "edition_number" : "2145", "is_extra_edition" : false, "power" : "executive_legislative", "file_checksum" : "7b7ed1557de74c25cff6a04023ed525f", "scraped_at" : "2023-12-11T20:25:43.705771", "created_at" : "2023-12-11T20:25:45.500616", "processed" : true, "file_path" : "2700000/2023-10-02/a4c2994ffab9f0dabc0d2c3ad46436f917d61efb.pdf", "file_url" : "https://www-storage.voxtecnologia.com.br?m=sigpub.publicacao&f=9878&i=publicado_91279_2023-09-29_564051d01bafcfea6f84735fc59f4d94.pdf", "state_code" : "AL", "territory_id" : "2704807", "file_raw_txt" : "/2704807/2023-10-02/7b7ed1557de74c25cff6a04023ed525f.txt", "url" : "http://google.com/2700000/2023-10-02/a4c2994ffab9f0dabc0d2c3ad46436f917d61efb.pdf" }, ``` Neste caso, o `source_text` está apenas com o cabeçalho. Além disso, o código estava um pouco confuso, então uma refatoração foi realizada para simplificar a segmentação, passando a utilizar mais `re.split()` ao invés de iterar diretamente linha-a-linha. Outra consequência dessa mudança é que além de mais segmentos estarem sendo coletados, os textos dos segmentos refletem o texto original mais fielmente, pois o tratamento de espaços em branco e quebras de linha não está sendo feito linha-a-linha no corpo do segmento. Refatora gazette_text_extraction por conta de associações O fluxo da task estava um pouco confuso, especialmente na bifurcação entre arquivo de diário agregado ou diário completo. Essa refatoração tem como objetivo simplificar esse fluxo e por consequência, assim como a task, os segmentadores também foram simplificados. Refatora criação de índices para tasks Corrige slug na segmentação Para eliminar a necessidade de exceções por conta de municípios com alguma palavra separada por espaço em seu nome indevidamente, o slug agora não utiliza mais um separador e concatena tudo. Ex: - al-senador-rui-palmeira -> alsenadorruipalmeira - al-senador-rui-palme-ira -> alsenadorruipalmeira
PR referente as Issues #43 #40
Essa não é uma versão final e busca passar por varias revisões.
O protótipo foca em sondar possíveis problemas, dar molde para uma versão final e limpa.
Ele já consegui segmentar os diários da AMA e chegar ao ponto final do processamento dos diários .
Objetivos inicias e principais
Passos a serem adicionados e melhorados.
self.url
,self.file_raw_txt
corretamente usando oget_file_endpoint()
.➡️ Parte a modificarObs: Logo estarei colocando a explicação, caminho tomado pelo protótipo para concluir o processamento e limpa o
Readme
do repositório.