-
-
Notifications
You must be signed in to change notification settings - Fork 409
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 raspador para Maragogi-AL #1176 #1186
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.
@gabrielqr esse sistema é muito chatinho e tem bastante coisa a mão, fora de ordem e documentos que não deveriam estar aqui. Infelizmente a lógica vai precisar acomodar essas características :/ Se precisar de dicas, ajuda, qualquer coisa, manda um grito aí
allowed_domains = ["maragogi.al.gov.br"] | ||
base_url = "https://maragogi.al.gov.br/diarios-oficiais/diario-oficial-" | ||
start_urls = ["https://maragogi.al.gov.br/diarios-oficiais/"] | ||
start_date = date(2020, 1, 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.
Vi que somente a partir de 17/04/2024 começaram a publicar os diários individuais de Maragogi, sendo antes disso todos da Associação dos Municípios Alagoanos, diários já cobertos pelo raspador al_associacao_municipios
.
Seria importante modificar essa data inicial pra gente não pegar esses diários da associação como sendo apenas do município de Maragogi, e talvez, como uma medida extra de segurança, colocar uma verificação para não baixar arquivos que contém "AMA" no título, pois esse é o padrão que estão usando, aparentemente.
O que acha?
base_url = "https://maragogi.al.gov.br/diarios-oficiais/diario-oficial-" | ||
start_urls = ["https://maragogi.al.gov.br/diarios-oficiais/"] | ||
start_date = date(2020, 1, 1) | ||
end_date = date.today() |
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.
Este atributo já é inserido automaticamente como date.today()
na BaseGazetteSpider
, então pode omitir aqui.
end_date = date.today() |
freq=YEARLY, dtstart=self.start_date, until=self.end_date | ||
): | ||
base_url = f"{self.base_url}{date_of_interest.year}/" | ||
yield scrapy.Request(url=base_url, callback=self.parse) |
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.
Pode omitir pois self.parse
é o callback padrão dos objetos Request
yield scrapy.Request(url=base_url, callback=self.parse) | |
yield scrapy.Request(url=base_url) |
if item_date < self.start_date: | ||
self.stop_crawling = True | ||
return |
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.
Pela natureza assíncrona do Scrapy, o uso de self.stop_crawling
vai gerar comportamentos inesperados e é necessário remover essa lógica.
Um exemplo:
Se os anos a pesquisar fossem 2024, 2023, 2022, 2021 e 2020 e a start_date
inserida por usuário fosse 2023-12-22
(finalzinho do ano).
2 requisições iniciais seriam enviadas (2024 e 2023), porém, não é garantido que a primeira resposta a ser processada seria do ano mais recente, seria a que voltasse primeiro. Ou seja, seria possível que a primeira resposta a ser processada fosse de 2023, onde alguns itens seriam raspados, mas a self.stop_crawling
logo seria colocada para True
e nenhum item de 2024 seria raspado.
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.
@ogecece Talvez aqui seria o uso do continue nã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.
@ogecece analisando o site aqui tem uma request que achei aqui que podemos usar pra sanar melhor essa questão de data inicial + data final, utilizando o menu de busca com a opção de busca avançada ele gera uma request onde podemos trazer as publicações de diários com as datas já configurada, talvez tendo cuidado de fazer uma iteração nos anos das datas como fiz no SAE
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.
@ogecece Talvez aqui seria o uso do continue não?
Continuando com o problema das datas fora de ordem, sim, perfeito, se a data fosse menor que self.start_date
usaria continue
. E sugeri que se a data identificada fosse dois meses anterior a self.start_date
, poderia encerrar, aí poderia dar o return
.
@ogecece analisando o site aqui tem uma request que achei aqui que podemos usar pra sanar melhor essa questão de data inicial + data final
Bicho, o sistema mudou mesmo. Pode ver que no print que tinha tirado antes era totalmente diferente. Vale testar até pra ver se algo do código do raspador ainda é aproveitável. Mas que bom que pelo menos a parte das datas parece estar resolvida.
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.
Consegui achar uma request aqui, estou fazendo o raspador do zero, pois com uma request consigo retornar os raspadores filtrado pela data e ordem que eu preciso
return | ||
|
||
titles = response.css(".arq-list-item-content h1::text").getall() | ||
dates = response.css(".data::text").getall() |
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.
Abrindo os arquivos vemos que essa data não é a data de publicação do diário. A data de publicação está no título do documento :/
O que é chato, pois o título do documento não está totalmente padronizado e o padrão de data vai precisar ser extraído com regex. É necessário mudar e fazer uma boa validação, pra ver se o regex está pegando todos os documentos desejados que conhecemos.
except ValueError: | ||
continue | ||
|
||
if item_date < self.start_date: |
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.
Outra coisa importante a se considerar com extração de datas a partir do título. Duas páginas em 2024:
As datas podem ficar muito fora de ordem, inclusive entre páginas... Pra não dispensarmos totalmente a verificação de data e fazermos a busca no ano inteiro (mesmo quando quiséssemos só o último dia, por exemplo, que seria muito mal otimizado) poderíamos considerar até dois meses antes do mês do start_date
como o limite para executar o return
e até então só executar continue
. O que acha?
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.
Ah, outra coisa para ser adicionada aqui é uma verificação para não coletar itens depois posteriores a end_date
if item_date > self.end_date:
continue
if title.endswith("."): | ||
title = title[:-1] | ||
|
||
if not title.endswith(".pdf"): | ||
title += ".pdf" |
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.
Isso poderia ser mais fácil se no começo da função não extraísse diretamente os h1::text
mas sim os a
externos ao h1
onde ainda teria acesso à URL. O que acha?
Ou até ficar no nível de article
mesmo e pegar .arq-list-item-content h1::text
pra extrair title
e .arq-list-item-content a::attr(href)
pra pegar a URL.
yield Gazette( | ||
date=item_date, | ||
edition_number=edition_number, | ||
is_extra_edition=False, |
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 extrair_numero(self, arquivo): | ||
match = re.search(r"no-(\d+)-", arquivo) | ||
if match: | ||
return match.group(1) | ||
return 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.
Geralmente, a não ser que o parsing para um campo seja muito complexo, não compensa desviar o foco da lógica de parsing para outro método, prejudicando o fluxo de leitura. Nesse caso, acho que não precisamos desse método.
|
||
next_page = response.css("a.next.page-numbers::attr(href)").get() | ||
if next_page: | ||
yield scrapy.Request(url=next_page, callback=self.parse) |
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.
Pode omitir pois self.parse
é o callback padrão dos objetos Request
yield scrapy.Request(url=next_page, callback=self.parse) | |
yield scrapy.Request(url=next_page) |
Esta PR está a mais de um mês sem resposta, vou assumir ela a pattir daqui @gabrielqr @ogecece |
Solicito o fechamento desta PR em dentrimento de #1290 , principalmente por causa da aparente mudança no site |
#### Layout do site publicador de diários oficiais Marque apenas um dos itens a seguir: - [x] O *layout* não se parece com nenhum caso [da lista de *layouts* padrão](https://docs.queridodiario.ok.org.br/pt-br/latest/contribuindo/lista-sistemas-replicaveis.html) - [ ] É um *layout* padrão e esta PR adiciona a spider base do padrão ao projeto junto com alguns municípios que fazem parte do padrão. - [ ] É um *layout* padrão e todos os municípios adicionados usam a [classe de spider base](https://github.com/okfn-brasil/querido-diario/tree/main/data_collection/gazette/spiders/base) adequada para o padrão. #### Código da(s) spider(s) - [x] O(s) raspador(es) adicionado(s) tem os [atributos de classe exigidos](https://docs.queridodiario.ok.org.br/pt-br/latest/contribuindo/raspadores.html#UFMunicipioSpider). - [x] O(s) raspador(es) adicionado(s) cria(m) objetos do tipo Gazette coletando todos [os metadados necessários](https://docs.queridodiario.ok.org.br/pt-br/latest/contribuindo/raspadores.html#Gazette). - [x] O atributo de classe [start_date](https://docs.queridodiario.ok.org.br/pt-br/latest/contribuindo/raspadores.html#UFMunicipioSpider.start_date) foi preenchido com a data da edição de diário oficial mais antiga disponível no site. - [x] Explicitar o atributo de classe [end_date](https://docs.queridodiario.ok.org.br/pt-br/latest/contribuindo/raspadores.html#UFMunicipioSpider.end_date) não se fez necessário. - [x] Não utilizo `custom_settings` em meu raspador. #### Testes - [x] Uma coleta-teste **da última edição** foi feita. O arquivo de `.log` deste teste está anexado na PR. - [x] Uma coleta-teste **por intervalo arbitrário** foi feita. Os arquivos de `.log`e `.csv` deste teste estão anexados na PR. - [x] Uma coleta-teste **completa** foi feita. Os arquivos de `.log` e `.csv` deste teste estão anexados na PR. #### Verificações - [x] Eu experimentei abrir alguns arquivos de diários oficiais coletados pelo meu raspador e verifiquei eles [conforme a documentação](https://docs.queridodiario.ok.org.br/pt-br/latest/contribuindo/raspadores.html#diarios-oficiais-coletados) não encontrando problemas. - [x] Eu verifiquei os arquivos `.csv` gerados pela minha coleta [conforme a documentação](https://docs.queridodiario.ok.org.br/pt-br/latest/contribuindo/raspadores.html#arquivos-auxiliares) não encontrando problemas. - [x] Eu verifiquei os arquivos de `.log` gerados pela minha coleta [conforme a documentação](https://docs.queridodiario.ok.org.br/pt-br/latest/contribuindo/raspadores.html#arquivos-auxiliares) não encontrando problemas. #### Descrição Reimplementação do raspador do município de Maragogi AL , anteriormente citado nesta issue #1176 e feito parcialmente nesta PR #1186, porém o mesmo ficou muito tempo esperando retorno do desenvolvedor, visto que houve mudanças drásticas no site dos diários oficiais em questão, decidi abrir esta nova PR para facilitar o fluxo de revisão - Logs e outputs de uma extração completa: [output-all.log](https://github.com/user-attachments/files/17197804/output-all.log) [output-all.csv](https://github.com/user-attachments/files/17197805/output-all.csv) - Logs e outputs de uma extração com data aleatória (2024-05-10 até 2024-08-23): [output-date.csv](https://github.com/user-attachments/files/17197810/output-date.csv) [output-date.log](https://github.com/user-attachments/files/17197809/output-date.log)
Layout do site publicador de diários oficiais
Marque apenas um dos itens a seguir:
é apenas para Maragogi-AL
Código da(s) spider(s)
custom_settings
em meu raspador.Testes
.log
deste teste está anexado na PR.ultimaedicao4.log
.log
e.csv
deste teste estão anexados na PR.intervalo.csv intervalo.log
.log
e.csv
deste teste estão anexados na PR.completo.csv completo.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
Criando raspador para Maragogi-AL para resolver a issue #1176