Dados CAFIR - Imóveis Rurais - Receita Federal

Oi pessoal, boa tarde.
Baixei os dados do CAFIR na Receita Federal e apesar de que no site indicam como arquivo csv, quando faço o download são 10 arquivos K3243.K34313DP.D21223.PARTE01 , …02 , 03… .
Como faço pra unir os arquivos e converter pra csv?
Desde já agradeço.

1 curtida

Dei uma olhada no dataset e parece ser um arquivo de colunas com largura fixa. Os nomes e larguras das colunas estão documentados no dicionário de dados. Dá um pouco de trabalho para ler, em comparação com csv, mas não é nada de outro mundo. Para concatenar os arquivos, também depende de que ferramenta / linguagem você está usando.

Se você estiver usando Python, o Pandas tem o método pandas.read_fwf para isso. Para concatenar os dataframes lidos de cada arquivo, tem o pandas.concat.

Sim, estou usando (aprendendo) o Python. Que tipo de arquivo é esse? Obrigado!

São arquivos texto tabulares, onde cada coluna tem uma largura determinada de caracteres. Então, quando vistos em um editor de texto, as colunas aparecem alinhadas.

Pesquise por “fixed width file”. Segue um texto explicando como usar no Pandas.

Muito bom, obrigado.

Com este código você conseguirá ler todas as planilhas:

import pandas as pd

URL_BASE = "https://dadosabertos.rfb.gov.br/CAFIR/K3243.K34313DP.D21223"
arquivos = [f"{URL_BASE}.PARTE{parte:02}" for parte in range(1, 11)]

dfs = [pd.read_fwf(url, encoding="iso-8859-1", widths=[8,9,13,55,2,56,40,2,40,8,1,8,1]) for url in arquivos]
for numero, df in enumerate(dfs):
    print(f"processando arquivo {numero + 1}...")
    # reinsere a primeira linha, que o pandas interpreta como nome das colunas
    df.loc[-1] = df.columns
    df.index = df.index + 1
    df.sort_index(inplace=True)
    df.columns = [
        "NR-IMOVEL",
        "AREA-TOTAL",
        "NR-INCRA",
        "NOME-IMOVEL",
        "SIT-IMOVEL",
        "ENDEREÇO",
        "DISTRITO",
        "UF",
        "MUNICÍPIO",
        "CEP",
        "CD-IMUNE",
        "DT-INSCRIÇÃO",
        "SNCR",
]

cafir = pd.concat(dfs)
cafir.to_csv("cafir.csv", index=False)

Obs.: o download dos arquivos vai demorar bastante e vai consumir muita memória da sua máquina, pois o total tem quase 2 GB.

2 curtidas

Onde ele salva os arquivos? Rodei o código e ele depois de processar os arquivos retorna dois erros: Traceback(most recennt call last) e No objects to concatenate

Não chegou a salvar porque deu erro antes. Como o download é muito demorado, eu tinha testado apenas com 1 arquivo. Corrigi o código lá, foi só trocar os parênteses por colchetes, para dfs ser uma lista em vez de ser um gerador. Só que agora a linha que vai demorar é essa onde é criada a variável dfs, pois é quando ele vai fazer todos os downloads.

Deu certo, só que o arquivo cafir.csv ficou com pouco mais de 1gb.

Estava pensando em fazer uma api com esses dados e disponibilizar pro público (tudo open source), só que estou com algumas dúvidas referente à última coluna:

No layout, tá especificado que ela corresponde ao SNCR, não sei o que essa sigla representa, mas pode assumir quatro diferentes valores:

  1. VINCULACAO PROVISORIA REALIZADA;
  2. VINCULACAO CONFIRMADA;
  3. DESVINCULADO;
  4. DESCARACTERIZACAO DE DESTINACAO RURAL;

O problema é que, no dataset, esse campo só assume dois valores: “A” e “I”. Alguém sabe o que isso significa?

Ademais, como pretendo fazer uma CI/CD para todo o processo (principalmente para os testes), fiz um script (shell) para rodar na pipeline que só precisa do curl e baixa e trata os dados automaticamente para csv, óbvio que com uma footprint bem menor que usando o python e pandas KKKKK, também não gostaria de introduzir mais uma dependência. Vou compartilhar ele aqui, e, se for usar, acho que precisa provisionar uma máquina com no mínimo 228M de mémoria (tamanho dos arquivos).

#!/usr/bin/env bash
set -eo pipefail

# Check if curl is installed
if ! [ -x "$(command -v curl)" ]; then
  echo >&2 "Error: curl is not installed."
  exit 1
fi

BASE_URL="https://dadosabertos.rfb.gov.br/CAFIR/K3243.K34313DP.D21223"

for i in $(seq -w 10);
do
    echo >&2 "Processing file ${i}"
    # Download the file
    curl "${BASE_URL}.PARTE${i}" \
        # Pipe into awk, separating the fixed width fields using ";" as the separator
        | awk -v FIELDWIDTHS="8 9 13 55 2 56 40 2 40 8 1 8 1" -v OFS=";" '{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13}' \
        # Regex to remove whitespace between the separators
        | sed 's/ *; */;/g' \
        # Append to cafir.csv
        >> cafir.csv
done

>&2 echo "The CAFIR data has been treated, ready to go!"

Exemplo dos dados processados:

$ head -10 cafir.csv
00000027;000013000;;FAZENDDA AGUA LIMPA;02;BR 401- KM 85 REGIAO DO TUCANO;;RR;BONFIM;69380000;2;0180528N;A
00000175;000000977;;FAZENDA CURRAIS NOVOS - LOTE 46,35;02;LOTE 46, GLEBA 35, PAD MAL DUTRA, LINHA C-35;ZONA RURAL;RO;ARIQUEMES;76870192;2;0210331N;A
00000299;000001087;0010311067120;SITIO PRIMAVERA;02;LT 16 GL 30 PAD MAL DUTRA;;RO;ARIQUEMES;76870001;2;0210331N;A
00000418;000000735;9500331778066;SITIO ALVORADA  14/A E 16/B GLEBA 35 PAD MAL DUTRA;02;LOTES 14/A E 16/B GLEBA 35PAD MAL DUTRA;ZONA RURAL;RO;ARIQUEMES;76870001;2;0210331N;A
00000566;000000986;;SITIO CEU AZUL;02;LOTE 74, GLEBA 11, LINHA C -100;ZONA RURAL;RO;RIO CRESPO;76863000;2;0200724S;I
00000701;000000897;;SITIO RONDONIA;02;LOTE 33 C GLEBA 35/B PAD MARECHAL DUTRA;;RO;ARIQUEMES;76870970;2;0200724N;A
00000833;000000855;;SITIO BEIRA RIO;02;LINHA T4 LOTE 54 GL 14, ST SAO MIGUEL;ZONA RURAL;RO;SAO MIGUEL DO GUAPORE;76932000;2;0200724N;A
00000965;000000350;;SITIO BOA VISTA;02;LOTE 154 - GLEBA 01 - PA NOVA CONQUISTA;;RO;VILHENA;76980002;2;0200724S;I
00001066;000000981;;SITIO BOM JESUS;02;LOTE 171, SETOR TENENTE MARQUES;;RO;VILHENA;76980002;2;0200724N;A
00001180;000000400;;SITIO SAO LUIZ;02;LT 68 GL 10 LH 86 NORTE KM 06 ST SAO MIGUEL;;RO;SAO MIGUEL DO GUAPORE;76932000;2;0200724N;A

No final, o tamanho do arquivo é de 1,02G:

$ ls -l cafir.csv
-rw-r--r-- 1 user user 1098167058 Jan 28 18:15 cafir.csv

EDIT: comentei o arquivo

1 curtida

Boa tarde, SNCR é o sistema nacional de cadastro rural. Todo imóvel rural tem que fazer a inscrição ou atualização do sncr pela plataforma dcr para emitir o ccir. Esses cadastros são do INCRA

Feito isso tem que ser feita a vinculaçao do sncr(ccir) ao cib(antigo nirf) no cnir(cadastro nacional de imóveis rurais).

O cib é da receita Federal.

1 curtida

Obrigado por esclarificar, mas até agora não entendi o que os valores “A” e “I” desse campo representam.

Também vale ressaltar que os campos que esses valores não são “A” ou “I” (os outros valores possíveis são “O”, letra o, não 0, ou “1”) estão mal formatados, exemplo:

$ grep "[^AI]$" cafir.csv | head -10
00508268;000001053;1120620209405;FAZENDA CAMPESTRE;02;ESTRADA PALMA A LUSTRãO;M;AP;RESIDENTE DUTRA                        6;57600002;0;210331NA;O
01897780;000000053;5030290089152;SITIO SANTO QUATO;02;CORREGO DO DEZ - A 2 KM DE VINHáTICO;E;SM;ONTANHA                                2;98900002;0;210331NA;O
02109328;000000226;5041140164115;SíTIO STUHR                                           0;21;KM ANTES DO COMERCIO DE VITORINO KOSANKE;E;SS;ANTA MARIA DE JETIBA                   2;96450002;0;210331NA;O
02279070;000000280;5060520063278;SITIO DAS PEDRAS;02;CóRREGO SANTA CLARA;E;SI;BATIBA                                 2;93950002;0;210331NA;O
02438860;000000513;6290654976309;SíTIO MARINA                                          0;2E;STRADA BOTUCATU-FAZENDA MONTE ALEGRE KM 14;S;PB;OTUCATU                                1;86000012;0;210331NA;O
02519135;000000518;6281580021787;FAZENDA SANTA LUZIA;02;ESTRADA TEJUPá A TAQUARITUBA, KM 12;S;PT;EJUPA                                  1;88300012;0;210802NA;O
02627671;000000081;6250860159706;SíTIO BOTACIM                                         0;2B;AIRRO DAS LAVRAS DE BAIXO;S;PS;OCORRO                                 1;39600002;0;210331NA;O
02683482;000001067;6340340222099;SI­TIO SANTA IZABEL                                   0;2R;ODOVIA BRAGANCA - AMPARO KM 10 BAIRRO RIO ABAIXO;S;PB;RAGANCA PAULISTA                       1;29000022;0;210331NA;O
02821885;000000056;6250780083385;SITIO SAO JOSé                                        0;2B;AIRRO DAS TRES BARRAS;S;PS;ERRA NEGRA                             1;39300002;0;210331NA;O
02959313;000001412;6240200047667;SíTIO POROMBO - GLEBA C                               0;2R;ODOVIA WILSON FINARDI (SP 191), KM 34;S;PA;RARAS                                  1;36000012;0;210331NA;O

A razão disso é que esses campos tem caracteres que não são ascii, então acho que realmente só pode os valores A ou I e o resto da linha tá sendo cortada.

Depois vou tentar concertar essas linhas, mas são poucas.

Descibri esse problema, o layout está errado, o campo DT-INSCRICAO tem 7, não 8 caracteres, e o último campo não tem 1, ele tem 4 ou são na verdade dois campos KKKKK. Exemplo:

$ curl https://dadosabertos.rfb.gov.br/CAFIR/K3243.K34313DP.D21223.PARTE01 | head -10
00000027000013000             FAZENDDA AGUA LIMPA                                    02BR 401- KM 85 REGIAO DO TUCANO                                                                  RRBONFIM                                  6938000020180528NAO3
00000175000000977             FAZENDA CURRAIS NOVOS - LOTE 46,35                     02LOTE 46, GLEBA 35, PAD MAL DUTRA, LINHA C-35            ZONA RURAL                              ROARIQUEMES                               7687019220210331NAO3
000002990000010870010311067120SITIO PRIMAVERA                                        02LT 16 GL 30 PAD MAL DUTRA                                                                       ROARIQUEMES                               7687000120210331NAO1
000004180000007359500331778066SITIO ALVORADA  14/A E 16/B GLEBA 35 PAD MAL DUTRA     02LOTES 14/A E 16/B GLEBA 35PAD MAL DUTRA                 ZONA RURAL                              ROARIQUEMES                               7687000120210331NAO1
00000566000000986             SITIO CEU AZUL                                         02LOTE 74, GLEBA 11, LINHA C -100                         ZONA RURAL                              RORIO CRESPO                              7686300020200724SIM3
00000701000000897             SITIO RONDONIA                                         02LOTE 33 C GLEBA 35/B PAD MARECHAL DUTRA                                                         ROARIQUEMES                               7687097020200724NAO3
00000833000000855             SITIO BEIRA RIO                                        02LINHA T4 LOTE 54 GL 14, ST SAO MIGUEL                   ZONA RURAL                              ROSAO MIGUEL DO GUAPORE                   7693200020200724NAO3
00000965000000350             SITIO BOA VISTA                                        02LOTE 154 - GLEBA 01 - PA NOVA CONQUISTA                                                         ROVILHENA                                 7698000220200724SIM3
00001066000000981             SITIO BOM JESUS                                        02LOTE 171, SETOR TENENTE MARQUES                                                                 ROVILHENA                                 7698000220200724NAO3
00001180000000400             SITIO SAO LUIZ                                         02LT 68 GL 10 LH 86 NORTE KM 06 ST SAO MIGUEL                                                     ROSAO MIGUEL DO GUAPORE                   7693200020200724NAO3

Esse campo é NAO/SIM + 1 a 4. Ou na verdade são dois campos e não sei pra que serve o NAO ou SIM.

EDIT: eu não posso fazer mais nenhum comentário porque membros novos estão limitados a 3 respostas em um thread. Então minha resposta a mensagem abaixo tá aqui:

Achei o que significa isso em um pdf no site da câmara. Na página 4 tem o valor correto de todas as colunas, sendo que esse SIM/NAO representa CD-IMUNIDADE. Acredito que esse CD-IMUNIDADE corresponde à necessidade de pegar o imposto da propriedade.

Esse é o meu script atualizado, que também corrige o erro das caracteres unicode serem mais que uma caractere na conta do layout:

#!/usr/bin/env bash
set -eo pipefail

if ! [ -x "$(command -v curl)" ]; then
  echo >&2 "Error: curl is not installed."
  exit 1
fi

if ! [ -x "$(command -v awk)" ]; then
  echo >&2 "Error: awk is not installed."
  exit 1
fi

BASE_URL="https://dadosabertos.rfb.gov.br/CAFIR/K3243.K34313DP.D21223"

for i in $(seq -w 10);
do
    echo >&2 "Processing file ${i}"
    curl "${BASE_URL}.PARTE${i}" \
        | awk -b -v FIELDWIDTHS="8 9 13 55 2 56 40 2 40 8 8 3 1" -v OFS=";" '{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13}' \
        | sed 's/ *; */;/g' \
        >> cafir.csv
done

>&2 echo "The CAFIR data has been treated, ready to go!"

Com isso, o arquivo fica:

$ head -10 cafir.csv
00000027;000013000;;FAZENDDA AGUA LIMPA;02;BR 401- KM 85 REGIAO DO TUCANO;;RR;BONFIM;69380000;20180528;NAO;3
00000175;000000977;;FAZENDA CURRAIS NOVOS - LOTE 46,35;02;LOTE 46, GLEBA 35, PAD MAL DUTRA, LINHA C-35;ZONA RURAL;RO;ARIQUEMES;76870192;20210331;NAO;3
00000299;000001087;0010311067120;SITIO PRIMAVERA;02;LT 16 GL 30 PAD MAL DUTRA;;RO;ARIQUEMES;76870001;20210331;NAO;1
00000418;000000735;9500331778066;SITIO ALVORADA  14/A E 16/B GLEBA 35 PAD MAL DUTRA;02;LOTES 14/A E 16/B GLEBA 35PAD MAL DUTRA;ZONA RURAL;RO;ARIQUEMES;76870001;20210331;NAO;1
00000566;000000986;;SITIO CEU AZUL;02;LOTE 74, GLEBA 11, LINHA C -100;ZONA RURAL;RO;RIO CRESPO;76863000;20200724;SIM;3
00000701;000000897;;SITIO RONDONIA;02;LOTE 33 C GLEBA 35/B PAD MARECHAL DUTRA;;RO;ARIQUEMES;76870970;20200724;NAO;3
00000833;000000855;;SITIO BEIRA RIO;02;LINHA T4 LOTE 54 GL 14, ST SAO MIGUEL;ZONA RURAL;RO;SAO MIGUEL DO GUAPORE;76932000;20200724;NAO;3
00000965;000000350;;SITIO BOA VISTA;02;LOTE 154 - GLEBA 01 - PA NOVA CONQUISTA;;RO;VILHENA;76980002;20200724;SIM;3
00001066;000000981;;SITIO BOM JESUS;02;LOTE 171, SETOR TENENTE MARQUES;;RO;VILHENA;76980002;20200724;NAO;3
00001180;000000400;;SITIO SAO LUIZ;02;LT 68 GL 10 LH 86 NORTE KM 06 ST SAO MIGUEL;;RO;SAO MIGUEL DO GUAPORE;76932000;20200724;NAO;3

Tamanho de 1,04G:

-rw-r--r-- 1 user user 1117158000 Jan 28 21:02 cafir.csv

Será que o sim e não é referente ao imóvel estar com sncr e cib vinculados ao cnir?

ajustei para quem já baixou

import pandas as pd

arquivos = [f"K3243.K34313DP.D21223.PARTE{parte:02}" for parte in range(1, 11)]

dfs = [pd.read_fwf(url, encoding="iso-8859-1", widths=[8,9,13,55,2,56,40,2,40,8,1,8,1]) for url in arquivos]
for numero, df in enumerate(dfs):
    print(f"processando arquivo {numero + 1}...")
    # reinsere a primeira linha, que o pandas interpreta como nome das colunas
    df.loc[-1] = df.columns
    df.index = df.index + 1
    df.sort_index(inplace=True)
    df.columns = [
        "NR-IMOVEL",
        "AREA-TOTAL",
        "NR-INCRA",
        "NOME-IMOVEL",
        "SIT-IMOVEL",
        "ENDEREÇO",
        "DISTRITO",
        "UF",
        "MUNICÍPIO",
        "CEP",
        "CD-IMUNE",
        "DT-INSCRIÇÃO",
        "SNCR",
    ]

cafir = pd.concat(dfs)
cafir.to_csv("cafir.csv", index=False)
1 curtida