Obter a legislação do dre.pt – versão de 2021

Mais uma vez o site dos Diários da República Electrónicos foi refeito. A nova versão foi colocada no ar no dia 2 de Novembro, sem pompa nem circunstância (numa busca rápida não encontrei nenhum anúncio). Esta nova versão mantém o aspecto do site anterior mas mudou o código que o constitui completamente.

Assim o método para obter a legislação mudou. Neste post mostro como se pode continuar a obter esta informação. Notar que a estrutura interna do site é extremamente ineficiente, são desperdiçados muito recursos que tornam o site mais lento do que necessitaria ser. Não me vou pronunciar mais sobre estes problemas, talvez num outro post.

O novo site carrega uma página simples e depois faz pedidos XHR para obter os dados a mostrar. Estes pedidos são feitos usando métodos HTTP POST. Os parâmetros dos métodos post são passados usando JSON. As respostas obtidas são também JSON.

Devido à arquitectura usada o trabalho para obter os documentos do DRE fica muito simplificado. Fundamentalmente necessitamos de identificar a forma de obter 3 tipos de informação:

  1. Lista dos DRs de uma determinada data
  2. Lista dos documentos de um dado DR
  3. Obter um determinado documento

Os ficheiros com a informação necessária para obter cada um destes tipos de informação pode ser obtido aqui (ZIP). Dentro deste ficheiro zip temos três scripts para cada um dos tipos de informação. Estes scripts foram testados em Linux, dependem do wget e jq.

Lista dos DRs de uma determinada data

Para aceder à lista dos DRs numa determinada data usamos o seguinte endpoint:

https://www.dre.pt/dre/screenservices/DRE/Home/home/DataActionGetDRByDataCalendario

Os parâmetros têm sempre a seguinte estrutura (onde o que está entre chavetas tem de ser JSON válido):

payload = {
    "versionInfo": { ... },
    "viewName": "Home.home",
    "screenData": {
        "variables": { ... }
    },
    "clientVariables": { ... }
    }

No caso deste endpoint a data é indicada em formato YYYY-MM-DD em:

payload["screenData"]["variables"]["DataCalendario"]

Por exemplo:

payload["screenData"]["variables"]["DataCalendario"] = "2021-11-02"

Notar que se analisarem o conteúdo do payload no site vão constatar que existem muito mais variáveis definidas. Eu não estive a testar exactamente quais as variáveis necessárias excepto para obter o texto dos documentos. Na maior parte dos casos estas variáveis não influem nos resultados devolvidos no entanto, neste caso onde desejamos obter a lista de DRs de uma dada data, existe a variável “DataUltimaPublicacao” que tem de estar no futuro em relação à data actual dado que os resultados devolvidos serão dessa data se esta for menor do que a data que desejamos analisar.

Para obter a lista dos diários publicados num dado dia temos de fazer o seguinte:

  1. Obter o payload para o endpoint referido. Isso pode ser feito usando as ferramentas disponíveis nos browsers (eu uso o Firefox), ou adaptar o que disponibilizei acima.
  2. Editar o payload para obtermos a data desejada;
  3. Uma forma de obtermos os dados é usar o seguinte comando:
    wget \
        --quiet \
        --output-document=- \
        --header="content-type: application/json; charset=utf-8" \
        --header="X-CSRFToken: NECESSARIO" \
        --post-file=./payload.json \
        https://www.dre.pt/dre/screenservices/DRE/Home/home/DataActionGetDRByDataCalendario
    

    Notar o CSRF token, não é feita qualquer verificação de validade do que é aqui inserido (quando comecei analisar este problema pensei que seria usado). Apenas se verifica se o cabeçalho existe no pedido ou não.

Em termos genéricos estes são os passos necessários para extrair qualquer tipo de informação do site.

Os dados são devolvidos numa estrutura como a seguinte:

{
  "versionInfo": {
    "hasModuleVersionChanged": true,
    "hasApiVersionChanged": false
  },
  "data": {
    "Json_Out": "{\"took\":5,\"timed_out\":false,\"_shards\":{\"total\":3,\"successful\":3,\"skipped\":0,\"failed\":0},\"hits\":{\"total\":{\"value\":4,\"relation\":\"eq\"},\"max_score\":null,\"hits\":[{\"_index\":\"dre-prod-22082021\",\"_type\":\"_doc\",\"_id\":\"173690372_DiarioRepublica\",\"_score\":null,\"_source\":{\"numero\":\"212\",\"dbId\":173690372,\"dataPublicacao\":\"2021-11-02\",\"conteudoTitle\":\"Diário da República n.º 212/2021, Série I de 2021-11-02\"},\"sort\":[0]},{\"_index\":\"dre-prod-22082021\",\"_type\":\"_doc\",\"_id\":\"173593640_DiarioRepublica\",\"_score\":null,\"_source\":{\"numero\":\"212\",\"dbId\":173593640,\"dataPublicacao\":\"2021-11-02\",\"conteudoTitle\":\"Diário da República n.º 212/2021, Série II de 2021-11-02\"},\"sort\":[0]},{\"_index\":\"dre-prod-22082021\",\"_type\":\"_doc\",\"_id\":\"173707589_DiarioRepublica\",\"_score\":null,\"_source\":{\"numero\":\"212\",\"dbId\":173707589,\"dataPublicacao\":\"2021-11-02\",\"conteudoTitle\":\"Diário da República n.º 212/2021, 1º Suplemento, Série II de 2021-11-02\"},\"sort\":[1]},{\"_index\":\"dre-prod-22082021\",\"_type\":\"_doc\",\"_id\":\"173732817_DiarioRepublica\",\"_score\":null,\"_source\":{\"numero\":\"212\",\"dbId\":173732817,\"dataPublicacao\":\"2021-11-02\",\"conteudoTitle\":\"Diário da República n.º 212/2021, 2º Suplemento, Série II de 2021-11-02\"},\"sort\":[2]}]},\"aggregations\":{\"SerieAgg\":{\"doc_count_error_upper_bound\":0,\"sum_other_doc_count\":0,\"buckets\":[{\"key\":\"II\",\"doc_count\":3},{\"key\":\"I\",\"doc_count\":1}]}}}"
  },
  "rolesInfo": ","
}

A string “Json_Out” é, como o nome indica, JSON. Podemos obter este JSON directamente usando o utilitário “jq”:

wget \
    --quiet \
    --output-document=- \
    --header="content-type: application/json; charset=utf-8" \
    --header="X-CSRFToken: NECESSARIO" \
    --post-file=./payload.json \
    https://www.dre.pt/dre/screenservices/DRE/Home/home/DataActionGetDRByDataCalendario \
    | jq ".data.Json_Out" | sed -e 's/\\"/"/g' -e 's/\\\\/\\/g' -e 's/^"//' -e 's/"$//' | jq .

A informação relativa a cada DR publicado na data escolhida é a seguinte:

...
"hits": [
    {
    "_index": "dre-prod-22082021",
    "_type": "_doc",
    "_id": "173690372_DiarioRepublica",
    "_score": null,
    "_source": {
        "numero": "212",
        "dbId": 173690372,
        "dataPublicacao": "2021-11-02",
        "conteudoTitle": "Diário da República n.º 212/2021, Série I de 2021-11-02"
        },
    "sort": [ 0 ]
    }, 
...

Para obtermos a lista de documentos contidos num determinado DR necessitamos do seu número de identificação que é dado por “dbId”.

Lista dos documentos de um dado DR

Para aceder à lista dos documentos de um dado DR usamos o seguinte endpoint:

https://www.dre.pt/dre/screenservices/DRE/Legislacao_Conteudos/ListaDiplomas/DataActionGetDados

A estrutura das variáveis é idêntica à que mostrámos anteriormente.

Tal como para obtermos a lista de DRs de um dado dia, agora só temos de compor o payload do pedido que vamos fazer ao site e ajustar as respectivas variáveis, neste caso apenas temos definir “DiarioId”.

Podemos extrair uma lista de documentos usando:

wget \
    --quiet \
    --output-document=- \
    --header="content-type: application/json; charset=utf-8" \
    --header="X-CSRFToken: NECESSARIO" \
    --post-file=./payload_doc_list.json \
    https://www.dre.pt/dre/screenservices/DRE/Legislacao_Conteudos/ListaDiplomas/DataActionGetDados \
    | jq .

Os dados devolvidos vêm na forma:

"List": [
    {
    "Titulo": "Resolução da Assembleia da República n.º 271/2021",
    "Emissor": "Assembleia da República",
    "Sumario": "Recomenda ao Governo a regulamentação de piscinas de lazer integradas em empreendimentos turísticos e alojamentos
locais e de uso doméstico",
    "DiplomaLegisId": "173690374",
    "ContratoPublicoId": "2",
    "TipoDiploma": "Resolução da Assembleia da República",
    "Numero": "271/2021",
    "Isnoindex": false,
    "ResumoEN": ""
    },
    ...

O identificador “DiplomaLegisId” é a chave para obtermos o documento completo. Notar que se se tratar de um contrato publico o identificador muda de nome para “ContratoPublicoId”:

{
"Titulo": "Anúncio de procedimento  n.º 13630/2021",
"Emissor": "Gestão e Obras do Porto, E. M.",
"Sumario": "Aquisição de serviços de Fiscalização da Empreitada de Requalificação da EB dos Correios",
"DiplomaLegisId": "0",
"ContratoPublicoId": "173785288",
"TipoDiploma": "anuncio-procedimento",
"Numero": "13630/2021",
"Isnoindex": false,
"ResumoEN": ""
},

Como são sempre devolvidos os dois identificadores, temos de saber distinguir entre um e outro tipo de documento.

Obter um determinado documento

Para aceder a um dado documento usamos o seguinte endpoint:

https://dre.pt/dre/screenservices/DRE/Legislacao_Conteudos/Conteudo_Detalhe/DataActionGetConteudo2

Há que distinguir entre os documentos normais e os contratos públicos. O parâmetro a definir será:

  • Para documentos normais: “DipLegisId”
  • Para documentos de contratos públicos: “ContPubId”

Para obter a informação relativa a um documento usamos:

wget \
    --quiet \
    --output-document=- \
    --header="content-type: application/json; charset=utf-8" \
    --header="X-CSRFToken: NECESSARIO" \
    --post-file=./payload_document.json \
    https://dre.pt/dre/screenservices/DRE/Legislacao_Conteudos/Conteudo_Detalhe/DataActionGetConteudo2 \
    | jq .

A informação devolvida é:

  "data": {
    "DetalheConteudo": {
      "Id": "175397134",
      "Titulo": "Decreto do Presidente da República n.º 91/2021 ",
      "Publicacao": "Diário da República n.º 234-B/2021, Série I de 2021-12-05",
      "DataPublicacao": "2021-12-05",
      "Empresa": "",
      "Concelho": "",
      "Conservatoria": "",
      "Emissor": "Presidência da República",
      "DataEmQueFoiPedido": "",
      "TipoDiploma": "Decreto do Presidente da República",
      "Numero": "91/2021",
      "Pagina": "2 - 2",
      "Assunto": "",
      "ELI": "https://data.dre.pt/eli/decpresrep/91/2021/12/05/p/dre",
      "VersaoPDF": "https://files.dre.pt/1s/2021/12/234b00/0000200002.pdf",
      "Resumo": "",
      "Sumario": "Dissolve a Assembleia da República",
      "Texto": "Decreto do Presidente da República n.º 91/2021\nde 5 de dezembro\nSumário: Dissolve a Assembleia da República.\nConsiderando que foram ouvidos os partidos representados na Assembleia da República e o Conselho de Estado, nos termos constitucionalmente consagrados;\nTendo, consequentemente, em consideração o disposto nos artigos 113.º, n.º 6, da Constituição e 19.º, n.º 1, da Lei n.º 14/79, de 16 de maio, que aprova a Lei Eleitoral para a Assembleia da República, na sua atual redação:\nO Presidente da República decreta, nos termos dos artigos 133.º, alínea e), 145.º, alínea a), e, consequentemente, dos artigos 113.º, n.º 6, da Constituição e 19.º, n.º 1, da Lei n.º 14/79, de 16 de maio, na sua atual redação, o seguinte:\nArtigo 1.º\nÉ dissolvida a Assembleia da República.\nArtigo 2.º\nÉ fixado o dia 30 de janeiro de 2022 para a eleição dos Deputados à Assembleia da República.\nArtigo 3.º\nO presente decreto produz efeitos no dia da sua publicação.\nAssinado em 5 de dezembro de 2021.\nPublique-se.\nO Presidente da República, Marcelo Rebelo de Sousa.\n114792686",
...

Desta forma consegue-se obter todo o conteúdo do Diário da República Electrónico.

1 thought on “Obter a legislação do dre.pt – versão de 2021

  1. Pingback: Obter a legislação do dre.pt – versão de 2014 | Tretas.org

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão /  Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão /  Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão /  Alterar )

Connecting to %s