Awesome
Este scraper recolhe as iniciativas legislativas a partir do site do Parlamento.
Método
O site do Parlamento foi programado em ASP, o que dificulta muito a tarefa de raspar informação (scraping). Assim, adotámos uma técnica bruta, recorrendo aos ID's numéricos de cada documento.
O endereço de uma iniciativa específica é algo como
http://www.parlamento.pt/ActividadeParlamentar/Paginas/DetalheIniciativa.aspx?BID=38526
Ora, ao alterar o valor da variável BID, podemos chegar a cada documento individual. Mas como não sabemos quais os ID's a pesquisar, batemos à porta de todos e apanhamos o que vem à rede.
Isto faz com que o processo seja muito mais demorado do que o necessário, já que existem milhares de ID's vazios e os mais recentes estão na ordem dos 38000, significando que temos de fazer mais de 38000 pedidos ao site para assegurar que temos tudo. Mas graças a um cache inteligente (obrigado @medecau), a descarga só é feita uma vez e todos os processamentos subsequentes usam uma cópia local da página HTML original. Assim, não há risco de sobrecarregar desnecessariamente o site do Parlamento.
Como usar
Para a ajuda dos comandos do script:
python scraper-iniciativas.py --help
Para experimentar sacando apenas 10 documentos a partir do 38000:
python scraper-iniciativas.py --start 38000 --end 38010
Para fazer a mesma coisa usando 4 processos (mais rápido mas puxa mais pelo CPU):
python scraper-iniciativas.py --start 38000 --end 38010 --processes 4
Campos do JSON resultante
Os campos que podem ser encontrados no JSON resultante são:
title
-- Título da iniciativa (Proposta de Lei 231/XII)summary
-- Sumário da iniciativaid
-- Número de identificação do documento no Parlamento.pt (38526)authors
-- Lista dos autores do documentoparlgroup
-- Grupo parlamentar responsável pelo documento (PSD, CDS-PP)events
-- Lista com as várias fases do processo legislativo. Contém objetos com os seguintes atributos:date
-- Data do evento (2014-05-29)type
-- Tipo de evento (Envio para promulgação)info
-- Pormenores do evento como links e detalhes das comissões e votações. Este campo só está expresso em texto, um dos afazeres é processá-lo para uma lista de links e outras informações.
doc_url
-- URL do ficheiro Word com o texto integral do documentopdf_url
-- URL do ficheiro PDF com o texto integral do documentopdf_url
-- URL do ficheiro PDF com o texto integral do documentourl
-- URL da iniciativa no Parlamento.ptscrape_date
-- Data e hora completa de quando o documento foi raspado
Como obter o texto completo de cada iniciativa
O JSON apenas inclui o sumário da iniciativa, mas o texto completo permite análises bem mais potentes. O campo doc_url
aponta-nos para um ficheiro Word, por isso primeiro tratamos de encontrar todos esses campos e fazer uma lista de URLs; depois usarmos o wget
para os descarregar. Neste comando usamos o pythonpy para chegar ao pedaço que queremos.
cat iniciativas.json | grep doc_url | \ # Isolar as linhas doc_url
py -x 'print(x.split("\"")[3])' | \ # Extrair o url entre aspas
xargs wget --content-disposition # O --content-disposition mantém
# o nome do ficheiro original
Com isto, temos agora um diretório cheio de ficheiros .doc
. Como não gostamos de formatos fechados, podemos convertê-los facilmente para texto usando o fantástico antiword
:
for f in *.doc; do antiword -w 0 ${f} > ${f/doc/txt}; done
Agora que temos as iniciativas completas em texto, é hora de esconder as provas de que tivemos ficheiros sujos e proprietários no nosso computador:
rm *.doc
Afazeres
- Processar corretamente os campos
info
dos eventos para determinar links e outras informações que lá existem - Detetar entradas sobre a substituição do texto original (exemplo)