GazetteDateFilteringPipeline (querido_diario_raspadores/gazette/pipelines.py:20-33) só compara o item com spider.start_date; nunca com spider.end_date:
class GazetteDateFilteringPipeline:
def process_item(self, item):
spider = self.crawler.spider
if hasattr(spider, "start_date"):
if spider.start_date > item.get("date"):
raise DropItem("Droping all items before {}".format(spider.start_date))
return item
Reprodução (uv run python dentro de querido_diario_raspadores/):
from datetime import date
from unittest.mock import Mock
from gazette.pipelines import GazetteDateFilteringPipeline
from gazette.items import Gazette
spider = Mock(start_date=date(2020, 1, 1), end_date=date(2020, 1, 31))
crawler = Mock(spider=spider)
pipeline = GazetteDateFilteringPipeline(crawler)
item = Gazette(date=date(2026, 9, 9), file_urls=["http://x/y.pdf"], power="executive", is_extra_edition=False)
print(pipeline.process_item(item)["date"]) # 2026-09-09 -- sobrevive ao pipeline mesmo com end_date=2020-01-31
Isso normalmente não é percebido porque a maioria dos raspadores implementa o corte de end_date na própria parse() (as classes em gazette/spiders/base/* fazem isso). Mas pelo menos 3 raspadores de capitais que herdam BaseGazetteSpider diretamente (sem base replicável) não filtram end_date em lugar nenhum do próprio código, e por isso dependem inteiramente do pipeline para isso — que não faz o filtro:
gazette/spiders/go/go_goiania.py: parse() só verifica if gazette_date < self.start_date. Pior, async def start() usa end_year = datetime.date.today().year (hardcoded) em vez de self.end_date.year, então nem a paginação por ano respeita end_date.
gazette/spiders/am/am_manaus.py: mesmo padrão, só if gazette_date < self.start_date.
gazette/spiders/rr/rr_boa_vista.py: mesmo padrão, só if date < self.start_date.
Impacto: rodar qualquer um desses três raspadores com -a end=AAAA-MM-DD (por exemplo, para reproduzir uma falha específica, ou na "coleta de intervalo" pedida no checklist de PR) não limita a coleta superiormente — diários publicados depois do end_date pedido são coletados normalmente e silenciosamente, sem erro ou aviso. Como são 3 capitais (prioridade 5 na tabela do CONTRIBUTING), o volume de dados afetado por uma coleta "de intervalo" mal contida pode ser grande.
Sugestão: fazer GazetteDateFilteringPipeline também descartar itens com date > spider.end_date (mesma lógica simétrica ao start_date já existente), como rede de segurança para todos os raspadores — e adicionar o filtro de end_date na parse() dos três raspadores citados.
GazetteDateFilteringPipeline(querido_diario_raspadores/gazette/pipelines.py:20-33) só compara o item comspider.start_date; nunca comspider.end_date:Reprodução (
uv run pythondentro dequerido_diario_raspadores/):Isso normalmente não é percebido porque a maioria dos raspadores implementa o corte de
end_datena própriaparse()(as classes emgazette/spiders/base/*fazem isso). Mas pelo menos 3 raspadores de capitais que herdamBaseGazetteSpiderdiretamente (sem base replicável) não filtramend_dateem lugar nenhum do próprio código, e por isso dependem inteiramente do pipeline para isso — que não faz o filtro:gazette/spiders/go/go_goiania.py:parse()só verificaif gazette_date < self.start_date. Pior,async def start()usaend_year = datetime.date.today().year(hardcoded) em vez deself.end_date.year, então nem a paginação por ano respeitaend_date.gazette/spiders/am/am_manaus.py: mesmo padrão, sóif gazette_date < self.start_date.gazette/spiders/rr/rr_boa_vista.py: mesmo padrão, sóif date < self.start_date.Impacto: rodar qualquer um desses três raspadores com
-a end=AAAA-MM-DD(por exemplo, para reproduzir uma falha específica, ou na "coleta de intervalo" pedida no checklist de PR) não limita a coleta superiormente — diários publicados depois doend_datepedido são coletados normalmente e silenciosamente, sem erro ou aviso. Como são 3 capitais (prioridade 5 na tabela do CONTRIBUTING), o volume de dados afetado por uma coleta "de intervalo" mal contida pode ser grande.Sugestão: fazer
GazetteDateFilteringPipelinetambém descartar itens comdate > spider.end_date(mesma lógica simétrica aostart_datejá existente), como rede de segurança para todos os raspadores — e adicionar o filtro deend_datenaparse()dos três raspadores citados.