Consultando CEP direto dos correios com PHP

A idéia é usar o PHP para conectar no site dos Correios enviando o CEP a ser pesquisado, pelo mesmo endereço que os usuários normalmente consultam.

Atenção

Pois é amiguinhos, como eu temia, os correios abandonou a URL mobile, e perdemos acesso para a solução apresentada neste tutorial

Nesse caso busquem alternativas para a consulta. Vou listar algumas opções que conheço, sinta-se livre para postar outras soluções que atualizarei o post.

Essas sugestões são uma forma de escape, mas não ajudaremos vocês com nenhum deles, nesse caso se tiverem problemas ao tentar usar a API, peço que entre em contato com os respectivos sites. Sorry :(

Para efeitos de história, vou deixar abaixo a solução que usávamos

Antes de mais nada, existem soluções melhores que essa, mas eu quis ser diferente e capturar os dados de outra maneira. Já podem me julgar...
Como de costume: Se você manda bem no PHP, clique aqui ir direto ao código completo.

Começando a mineração

Os correios espera dois campos, o CEP e um parametro metodo com valor buscarCep. Deixaremos esses dados prontos para enviar via POST depois.

1
2
3
4
$data = array(
    'cepEntrada' => '04476240',
    'metodo' => 'buscarCep',
);

Hora de converter o array em uma query para facilitar no envio.

$data = http_build_query($data);

Iniciando o cURL e passando a URL dos correios

$curl = curl_init('http://m.correios.com.br/movel/buscaCepConfirma.do');

Configurar o envio como post e passar a variável com os dados do post

1
2
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

Informando ao cURL que queremos o resultado em uma variável

curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

Executando a conexão e guardando o resultado na variável

$html = curl_exec($curl);

Fechando a conexão

curl_close($curl);

Se você mandar imprimir na tela a variável $html vai ver que ele trouxe toda página dos correios com o resultado do frete.

É exatamente o que nós queremos. Agora é hora de eliminar o que não queremos da página. Usaremos a função explode para ir "partindo", os pedaços que queremos.

Se você ver a estrutura do HTML da página dos correios, poderá notar que se explodirmos resposta"> teremos a informação que precisamos.

Correios classe resposta
$html = explode('resposta">', $html);

Elininando o indice zero onde temos apenas o começo do HTML sem informação útil.

unset($html[0]);

Já temos um array com as informações que precisamos, vamos navegar pelos dados pegando só o necessário. Criaremos um array $cep para deixar as informações que recebemos do CEP.

1
2
3
4
$cep = array();
foreach ($html as $key => $row) {
//Trataremos tudo aqui
}

Dentro do laço (foreach) nossa missão é pegar o nome da informação, colocar na variável $label e o valor da informação colocando na variável $value

Pegando a primeira parte antes do ":", teremos nosso rótulo

1
2
$label = explode(':', $row);
$label = current($label);

Se quisermos deixar "bonitinho" e padronizado, poderemos usar a função Slugify

$label = slugify($label);

Pronto, nosso rótulo já está pronto. Podemos seguir para o próximo.

Correios classe resposta destaque

Note que podemos explodir respostadestaque"> e termos o valor da informação

$value = explode('respostadestaque">', $row);

O que importa para nós é o conteudo do indice 1

$value = $value[1];

O primeiro valor antes do span

1
2
$value = explode('</span>', $value);
$value = current($value);

Removendo os espaços antes e depois

$value = trim($value);

Removendo as quebras de linhas, tabs e retornos

$value = preg_replace('/[\n\t\r]/', ' ', $value);

Qualquer espaço duplo

$value = preg_replace('/\s(?=\s)/', '', $value);

Se sua página estiver em UTF-8, inclua a linha abaixo

$value = utf8_encode($value);

Pronto. Agora já temos toda informação que precisamos, do jeito que precisamos. Basta popular o array $cep, usando o $label como indice e $value como valor.

$cep[$label] = $value;
.

Missão cumprida.

Agora a idéia é colocar tudo dentro de uma função que receba o $cep e retorne as informações.

1
2
3
4
function CEP($cep) {
//Todo conteúdo passado anteriormente
    return $cep;
}

Código completo e já na função ficará algo como abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function CEP($cep) {
    $data = array(
        'cepEntrada' => $cep,
        'metodo' => 'buscarCep',
    );

    $data = http_build_query($data);

    $curl = curl_init('http://m.correios.com.br/movel/buscaCepConfirma.do');
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    $html = curl_exec($curl);
    curl_close($curl);

    $html = explode('resposta">', $html);
    unset($html[0]);

    $cep = array();
    foreach ($html as $key => $row) {
        $label = explode(':', $row);
        $label = current($label);
        $label = slugify($label);

        $value = explode('respostadestaque">', $row);
        $value = $value[1];
        $value = explode('</span>', $value);
        $value = current($value);
        $value = trim($value);
        $value = preg_replace('/[\n\t\r]/', ' ', $value);
        $value = preg_replace('/\s(?=\s)/', '', $value);
        $value = utf8_encode($value);

        $cep[$label] = $value;
    }

    return $cep;
}