-
-
Notifications
You must be signed in to change notification settings - Fork 417
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
Cria spider para Duque de Caxias RJ no padrão atual do projeto #1333
base: main
Are you sure you want to change the base?
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.
Valeu @slfabio .
Tem algumas coisinhas para fazermos antes de aceitar.
Favor ver comentários.
Outra coisa, em relação ao que disse aqui:
Foi utilizada a data inicial de 02/01/2017, pois as versões anteriores não disponibilizam a data da edição. Os diários anteriores a 2017 exibem apenas a data de modificação do arquivo, que não tem relação com a data de publicação do diário.
Apesar da data da edição de diários antigos não estar explicita na página que contém os links para baixar, é possível extraí-la atraéz da url final para o diário.
Por exemplo: https://duquedecaxias.rj.gov.br/portal/boletim-oficial/2014/07-Julho/6148-15.pdf
O ano, mês, e dia estão aí. O dia é o número após a edição.
Isso não implica na não aceitação desta PR, mas significa que teremos que escrever outro raspador para pegar aqueles restantes.
data_collection/gazette/utils.py
Outdated
def extract_date(text): | ||
"""Extract a date from a text. This method attempts to correct typing errors in the month. | ||
|
||
Args: | ||
text: A text containing a date with the name of the month full version (%B) | ||
Returns: | ||
The date, if match. Otherwise, returns None. | ||
""" | ||
|
||
text = re.sub(" +", " ", text).strip() | ||
match_date = re.search(r"\d{1,2}º?(\sde)? +(\w+)(\sde)? +\d{4}", text) | ||
if not match_date: | ||
return None | ||
|
||
raw_date = match_date.group(0) | ||
raw_date = raw_date.replace("º", "").replace("°", "") | ||
month = match_date.group(2) | ||
if month.lower() not in MONTHS: | ||
match_month, score = process.extractOne(month, MONTHS) | ||
if score < 70: | ||
return None | ||
raw_date = raw_date.replace(month, match_month) | ||
|
||
parsed_datetime = dateparser.parse(raw_date, languages=["pt"]) | ||
return parsed_datetime.date() if parsed_datetime else None |
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.
Gostei da ideia.
O formato de data que definiu é genérico o suficiente para que seja útil para outros.
Seria bom saber se existe uma necessidade real. Quantas ocorrências de erros de digitação na data você encontrou na base inteira de diários deles?
Eu mudaria o nome do método para deixar claro exatamente o que ele faz. Indicando que ele recebe um texto por extenso E utiliza um fuzzy match para evitar erros de digitação.
Algo como date_from_text_with_fuzzy_match
?
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.
Esse é um problema recorrente em municípios que utilizam data por extenso (Ex: Duque de Caxias/RJ, Barra Mansa/RJ, Campos/RJ)
Até deixei esse comentário na issue de Campos/RJ (#1323 (comment)) para saber o que vocês acham da solução.
Sobre a quantidade de ocorrências, eu posso testar novamente nesses 3 municípios para saber, acho que não chega a 10 edições para cada município, mas pra mim o principal é que mesmo que seja pontual, o problema ocorre em diversos municípios e a há uma solução simples de contorno.
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.
Vou aguardar a definição desse item para corrigir os outros apontamentos.
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.
Entendido.
Concordo que vale a pena implementar essa estratégia.
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.
Alterado nome da função alterado.
import re | ||
|
||
import dateparser | ||
from fuzzywuzzy import process |
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.
Todas as novas bibliotecas precisam ser adicionadas no requirements.in
para que outros dev tenham acesso.
Inclusive a que mencionou na descrição: python-Levenshtein
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.
Alterações realizadas nos arquivos de requirements.
|
||
|
||
class RjDuqueCaxiasSpider(BaseGazetteSpider): | ||
name = "rj_duque_caxias" |
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.
Colocamos o nome inteiro do município no nome do arquivo. 😛
Adicione o _de_
que faltou para ficar duque_de_caxias
.
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.
Corrigido.
|
||
def parse(self, response): | ||
pdf_divs = response.xpath( | ||
"//i[contains(@class, 'fa-file-pdf')]/ancestor::div[1]" |
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.
Boa sacada de buscar por um filho para pegar o pai.
return | ||
|
||
raw_gazette_edtion = pdf_div.xpath("./preceding-sibling::div[2]/text()") | ||
is_extra_edition = bool( |
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.
@slfabio Eu vi vários diários com o termo "vol2". Não parece que eles são edições extra porque isso não está explícito no seu conteúdo.
Você conseguiu entender o que eles são? Será que são uma continuação?
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.
Exatamente. São a continuação de uma mesma edição.
Tarefa criada para os diários antigos, caso aceitemos esta PR sem fazer isso. |
95e762c
to
93a884b
Compare
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.
Obrigado pelas mudanças! Faltou só modificar o nome do arquivo em si. Para rj_duque_de_caxias.py
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.
Feito!
Cria spider para Duque de Caxias / RJ
93a884b
to
c466990
Compare
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.
Bala!
@trevineju pode juntar essa! |
AO ABRIR uma Pull Request de um novo raspador (spider), marque com um
X
cada um dos items da checklist abaixo. Caso algum item não seja marcado, JUSTIFIQUE o motivo.Layout do site publicador de diários oficiais
Marque apenas um dos itens a seguir:
Código da(s) spider(s)
custom_settings
em meu raspador.Testes
.log
deste teste está anexado na PR..log
e.csv
deste teste estão anexados na PR..log
e.csv
deste teste estão anexados na PR.completa.csv
completa.log
intervalo.csv
intervalo.log
ultima.csv
ultima.log
Verificações
.csv
gerados pela minha coleta conforme a documentação não encontrando problemas..log
gerados pela minha coleta conforme a documentação não encontrando problemas.Descrição
Resolve #616
Atualiza o código do PR #705 para o padrão atual do projeto, coletando todos os atributos do gazette.
Obs. Foi utilizada a data inicial de 02/01/2017, pois as versões anteriores não disponibilizam a data da edição. Os diários anteriores a 2017 exibem apenas a data de modificação do arquivo, que não tem relação com a data de publicação do diário.
Obs2. Revisar esse PR anrtes do #1323, pois se for integrada a função extract_date no utils, eu modificarei o código do spider de Campos-RJ para usar o método do utils.
Adiciona a função extract_date no utils do projeto para fazer o parse das datas escritas por extenso, corrigindo eventuais erros de digitação no mês.
O código utiliza a biblioteca fuzzywuzzy, que usa o algoritmo de distância Levenshtein para medir a semelhança entre duas strings e, a partir da lista de meses, selecionar o mês com a grafia correta antes de fazer o dateparser.
Para usar o fuzzywuzzy, é necessário instalar 2 bibliotecas ao projeto: fuzzywuzzy e python-Levenshtein