Skip to content
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

Trabalhando na issue #695 #968

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open

Trabalhando na issue #695 #968

wants to merge 5 commits into from

Conversation

luxu
Copy link

@luxu luxu commented Oct 11, 2023

AO ABRIR um Pull Request de um novo raspador (spider), marque com um X cada um dos items do checklist
abaixo. NÃO ABRA um novo Pull Request antes de completar todos os items abaixo.

Checklist - Novo spider

  • Você executou uma extração completa do spider localmente e os dados retornados estavam corretos.
  • Você executou uma extração por período (start_date e end_date definidos) ao menos uma vez e os dados retornados estavam corretos.
  • Você verificou que não existe nenhum erro nos logs (log_count/ERROR igual a zero).
  • Você definiu o atributo de classe start_date no seu spider com a data do Diário Oficial mais antigo disponível na página da cidade.
  • Você garantiu que todos os campos que poderiam ser extraídos foram extraídos de acordo com a documentação.

Descrição

<Descreva o seu Pull Request informando a issue (caso exista) que está sendo solucionada ou uma descrição do código apresentado>

@luxu
Copy link
Author

luxu commented Oct 11, 2023

Não está sendo pego os diários após chamar o callback sendo que ao criar um projeto do zero tudo funciona.

@luxu luxu marked this pull request as ready for review October 17, 2023 22:57
@trevineju trevineju added the hacktoberfest-accepted Pull Requests aprovados na Hacktoberfest label Oct 18, 2023
@trevineju trevineju linked an issue Oct 26, 2023 that may be closed by this pull request
@trevineju
Copy link
Member

trevineju commented Nov 14, 2023

arquivos de execução do raspador (executado em 14/11/2023):
log_parauabepas.txt
pa_parauapebas.csv

Copy link
Member

@ogecece ogecece left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oi @luxu ! Seu PR foi revisado no encontro do Grupo de Trabalho (GT) de Raspadores nessa terça (14/11).

Felizmente uma brecha no site foi encontrada pelo @alexjbs. Vou descrever ela no próximo review (pedindo mudanças) e deixar esse aqui apenas como comentários de melhorias no que foi desenvolvido (mas que provavelmente pouca coisa será aproveitada).


Uma dica geral pra contribuições seria que atualizar a branch usando merge deixa o histórico de commits bem confuso. Vou te mostrar aqui como tá o histórico da branch usando git log --oneline --graph:

image

Os dois commits que realmente tem conteúdo estão destacados. E ao usar git rebase main (com a main atualizada), como fica:

image

Assim suas alterações ficam no "topo" e dessa maneira conseguimos manter um histórico de commits mais organizado com essa estrutura aqui onde cada PR fica facilmente demarcado na história quando é mesclado com um commit de merge:

image

Isso não é obrigação sua de saber, é mais dever de quem está mantendo em preservar um histórico de commits organizado, mas achei que valia a dica :) Saber um pouco a mais sobre git vai bem longe porque é usado em quase todo projeto de código.

import datetime as dt

import scrapy
from dateparser import parse
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Como usamos bastante o parse no contexto de raspagem, seria preferível evitar o import direto da função e assim o contexto ficaria explícito usando dateparser.parse.

Suggested change
from dateparser import parse
import dateparser

Comment on lines +17 to +31
ano_atual = dt.datetime.now().year
for year in [2022, ano_atual]:
for month in range(1, 13):
for day in range(1, 32):
if len(str(day)) < 2:
day = "".join(("0", str(day)))
if len(str(month)) < 2:
month = "".join(("0", str(month)))
data = f"{year}-{month}-{day}"
url = f"{response.url}?data={data}"
yield scrapy.Request(
url,
callback=self.parse_gazette,
cb_kwargs={"data": data},
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aqui temos dois comentários importantes:

  1. Para gerar datas em um dado intervalo a função rrule da biblioteca dateutil é uma mão na roda gigante e evita gerarmos datas inválidas (como 31 de fevereiro).
  2. É obrigatório implementar o filtro por datas por meio dos atributos self.start_date e self.end_date. É importante dar uma lida nessa página da documentação.
Suggested change
ano_atual = dt.datetime.now().year
for year in [2022, ano_atual]:
for month in range(1, 13):
for day in range(1, 32):
if len(str(day)) < 2:
day = "".join(("0", str(day)))
if len(str(month)) < 2:
month = "".join(("0", str(month)))
data = f"{year}-{month}-{day}"
url = f"{response.url}?data={data}"
yield scrapy.Request(
url,
callback=self.parse_gazette,
cb_kwargs={"data": data},
)
for date in rrule(DAILY, dtstart=self.start_date, until=self.end_date): # fazer uso do rrule para não gerar datas inválidas
# fazer uso de start_date e end_date é obrigatório na escrita do raspador
yield scrapy.Request(
f"{response.url}?data={date.date().isoformat()}",
callback=self.parse_gazette,
cb_kwargs={"data": date.date()},

Comment on lines +34 to +35
link_diario = response.css("a[target]").css("::attr(href)").extract_first()
data_do_diario = link_diario.split("/")[-1].split(".")[:-2]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alguns comentários aqui, em tom de sugestão:

  1. Não precisaria encadear uso do seletor, fica um pouco menor colocar tudo na mesma chamada do .css
  2. .extract_first está em desuso, dê preferência a usar .get
  3. Porém, ao deixar de usar .get acima podemos aproveitar o método .re_first da resposta do seletor e deixar a construção da variável da data mais legível
  4. Como já temos a data da publicação no argumento data, mudaria o nome dessa aqui já que será utilizada apenas para validação em dias onde não há publicação
Suggested change
link_diario = response.css("a[target]").css("::attr(href)").extract_first()
data_do_diario = link_diario.split("/")[-1].split(".")[:-2]
link_diario = response.css("a[target='diario']::attr(href)")
data_no_link = link_diario.re_first(r"\d{4}\.\d{2}\.\d{2}")

Comment on lines +36 to +47
data_no_formato_string = str(data)
data = data_no_formato_string.split("-")
if data_do_diario == data:
data_no_formato_date = parse(
data_no_formato_string, languages=["br"]
).date()
yield Gazette(
date=data_no_formato_date,
file_urls=[link_diario],
is_extra_edition=False,
power="executive",
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mais algumas sugestões e por último uma correção:

  1. Usar curto-circuito (essa condicional onde caso seja verdadeira encerra a execução da subrotina) em Python é interessante pois evita o crescimento horizontal do código (algo bem comum por conta das identações)
  2. Já temos a data a partir do argumento data, faria sentido usá-la no item
  3. Se link_diario não usar .get acima, seria necessário usar aqui
  4. O power não é apenas executive. Precisa ser executive_legislative por conta de diários como os de 15/10/2021, 22/10/2021 e 22/10/2021 onde há atos da câmara legislativa.
Suggested change
data_no_formato_string = str(data)
data = data_no_formato_string.split("-")
if data_do_diario == data:
data_no_formato_date = parse(
data_no_formato_string, languages=["br"]
).date()
yield Gazette(
date=data_no_formato_date,
file_urls=[link_diario],
is_extra_edition=False,
power="executive",
)
if dt.datetime.strptime(data_no_link, "%Y.%m.%d").date() != data: # usar curto-circuito é uma boa prática em python para o código não crescer muito horizontalmente
self.logger.debug(f"Não existe diário para esta data: {data}. Data encontrada: {data_no_link}") # log de debug ajudará caso esse comportamento mude e também ajuda na autodocumentação desse condicional
return
yield Gazette(
date=data, # como já temos a data pronta, faz sentido utilizá-la aqui
file_urls=[link_diario.get()], # como não usamos .get acima, é necessário colocar aqui
is_extra_edition=False,
power="executive_legislative", # provavelmente
)

Copy link
Member

@ogecece ogecece left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Como mencionei na revisão anterior, o @alexjbs descobriu uma brecha!

Todos os arquivos estão acessíveis a partir do link https://apps.ioepa.com.br/Parauapebas/Busca/Arquivos/ .

Como a data de publicação no link é confiável, não perdemos nenhuma informação. E essa implementação otimizaria muito as requisições para fazer a raspagem completa (e faria uma requisição a menos na execução diária).

Pode desenrolar a reescrita do raspador?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hacktoberfest-accepted Pull Requests aprovados na Hacktoberfest
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Parauapebas-PA
3 participants