Search neighborhood from street

Asked

Viewed 440 times

0

Looking a little I found this method of consulting the zip code from neighborhood and city or all data from the zip code. But this query is only working when I put the information directly in the code between quotes. I’m not able to use a variable (that I enter the data passed by POST) inside $buscarcep->busca('[Aqui dentro!]').

The proleme is la at the bottom in // Show Routine

That is the code:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Documento</title>
</head>

<body>



<?php
$rua01 = 'Rua diadema';
$cidade01 = 'Foz do Iguaçu';

$endereco01 = $rua01.' '.$cidade01;

class BuscaCEP
{
    protected function formata($response)
    {
        $dom = new DOMDocument();
        @$dom->loadHTML($response);
        $xpath = new DOMXPath($dom);
        $values = $xpath->query('//*[@class="respostadestaque"]');
        $result = [];

        // Se não encontrar CEP, retorna false
        if (!$values->length) {
            return false;
        }

        // Obtém informações desejadas, tratando-as quando necessário
        foreach ($values as $value) {
            $result[] = preg_replace(
                '~[\s]{2,}~',
                '',
                trim($value->childNodes->item(0)->nodeValue)
            );
        }

        list($logradouro, $bairro, $localidade, $cep) = $result;
        list($localidade, $uf) = explode('/', $localidade);

        return compact('logradouro', 'bairro', 'localidade', 'uf', 'cep');
    }

    public function busca($cep)
    {
        $response = file_get_contents(
            'http://m.correios.com.br/movel/buscaCepConfirma.do',
            false,
            stream_context_create([
                'http' => [
                    'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
                    'method' => 'POST',
                    'content' => http_build_query([
                        'cepEntrada' => $cep,
                        'metodo' => 'buscarCep',
                    ]),
                ],
            ])
        );

        return $this->formata($response);
    }
}

// Rotina de Exibir
$buscarcep = new BuscaCEP();
$dados = $buscarcep->busca($endereco01);
print_r($dados['bairro']);

?>

</body>
</html>

I already put in

$dados = $buscarcep->busca($enderecoP);
$dados = $buscarcep->busca("$enderecoP");

And just nothing came up. No error, just nothing printed.

Updating with more information, as they generated different forms of interpretation. There at the end of the code when I put:

// Rotina de Exibir
$buscarcep = new BuscaCEP();
$dados = $buscarcep->busca($endereco01);
print_r($dados['bairro']);

Within the variable $address01 I have $rua01. ' '.$city01, that if I were to echo her, I would be shown Rua diadema Foz do Iguaçu. But the way this one doesn’t recognize! Now if I take $address01 and put only 'Rua diadema Foz do Iguaçu' in this way:

// Rotina de Exibir
$buscarcep = new BuscaCEP();
$dados = $buscarcep->busca('Rua diadema Foz do Iguaçu');
print_r($dados['bairro']);

He recognizes perfectly and shows me the information of this address.

  • Here the output was Jardim Curitibano, works. Enable errors.

  • What are the values of $rua01 and $cidade01? Shouldn’t be $ruaP and $cidadeP?

  • @Andersoncarloswoss yes, I ended up putting wrong, I’m using 01 at the end, but to pass here I decided to put P.

  • And yet it doesn’t work? Try putting var_dump($enderecoP) before $buscarcep->busca(...)

  • @Papacharlie is working pq if you repair this --- $data = $buscarcep->search('85869510'); --- Has the zip already inside, what I want to put is a variable in place of the number, because I will pass by POST this information.

  • @Andersoncarloswoss not, as he told me he printed C: wamp64 www delivery2 test index.php:69:string 'Rua diadema Foz do Iguaçu' (length=26) In this case 'Rua diadema Foz do Iguaçu' are the data that I am going through by POST.

  • Here worked perfectly the way you did, I didn’t change any line the problem should be elsewhere, has no relation to enter or not in $buscarcep->busca(...), the variables POST inclusive are not sent to $buscarcep->busca();, you are sending a '85869510'. The problem for sure is the moment you pass the POST, or better not even be arriving in the POST. Show how you are doing the search for the address instead of zip code.

  • @Guilhermenascimento I think I should have taken this '85869510', because they are misinterpreting me. The code like this, is working. But I need to put this zip code directly into the code. An example, if you say $cepConsult = '85869510'; and put $cepConsult into $buscarcep->search(inside), it just doesn’t recognize that the contents of that variable when it’s inside.

  • @daltongonzaloFuentes already explained, the problem is not ae, you have to explain how you did, wait a little while I am formulating an answer that may help you.

  • @daltongonzaloFuents how are you calling this script? From a form submission?

  • @Andersoncarloswoss right now I’m right in php, I took if(isset(...), IE, every time I update the page it running the Script

  • But if you are not submitting a form, you will not have information in $_POST. Possibly about this William will respond. And that if(isset(...)) is the one that’s not in the code?

  • @Guilhermenascimento It happens like this: if I put in the dots $buscarcep->search(...) '85869510', he looks for the information about this zip code, but if I put tbm directly in the dots 'Rua diadema Foz do Iguaçu' he also looks for the information about this address. Now if I put 'Rua diadema Foz do Iguaçu' inside a variable, $cepConsult for example, and put this variable inside the dots, it does not recognize. $buscarcep->busca('Rua diadema Foz do Iguaçu') -> Reconhece $cepConsulta = 'Rua diadema Foz do Iguaçu'; $buscarcep->busca($cepConsulta) -> Does not recognize

  • @daltongonzaloFuentes Can you give us exactly the code you are testing when using the variable? You can play it on Pastebin, Ideone, whatever you want, and pass the link here.

  • As I said, this with problem of handling errors and input data, I’m not being critical, I’m just saying, you are the programmer, PHP and even no language has to guess things if you as a programmer do not program for it to detect. ;)

  • @Andersoncarloswoss I updated the question with my code exactly like this one. Here is the link: https://ideone.com/fork/sXozcO I think this is correct.

Show 11 more comments

1 answer

4


Here worked perfectly the way you did, I didn’t change any line the problem must be elsewhere, has no relation whether or not to $buscarcep->busca(...)

The problem must be either in the data coming from the POST or in the answer that you didn’t treat with the $xpath->query('//*[@class="respostadestaque"]');, if the mail page does not find the address then it must be sending an error message, which you have not captured, PHP there’s no way to guess that an HTML page is reporting an error, unless you program it to do this, let’s go in stages:

First stage

Most important of all, always check the input values:

if (empty($_POST['rua'])) {
   die('Você não informou a rua');
} else if (empty($_POST['cidade'])) {
   die('Você não informou a cidade');
}

$ruaP = $_POST['rua'];
$cidadeP = $_POST['cidade'];
$enderecoP = $ruaP.' '.$cidadeP;

Note: In $enderecoP = $ruaP.' '.$cidadeP; parentheses are not necessary to concactenate, they are necessary to isolate, like when it will concactenate something that requires different "treatments" or if it will concactenate "calculations" with "string" or make "calculations in order"

This should help avoid a lack of information

Second step

The print_r not to print strings (although it works) is for array, print_r also does not recognize boolean values, your script must be returning false (false and true are boolean) due to this:

// Se não encontrar CEP, retorna false
if (!$values->length) {
    return false;
}

So switch to var_dump, because the var_Dump "debugs" your variables saying the type and value:

$dados = $buscarcep->busca($enderecoP);
var_dump($dados);

Third step

Check if there was an error in the reply of the post office page, as I said PHP is not guesswork, you should do the human behavior and program PHP to do this, for example I opened the http://m.correios.com.br/mobile/buscaCepConfirma.do and typed meaningless random words and got the error page, the post page in the HTML view-source returned this:

<div class="erro">
            Dados nao encontrados         <br>
        </div>

So just adjust for this:

$checkError = $xpath->query('//*[@class="erro"]');

if ($checkError->length) {
    return trim($checkError->item(0)->nodeValue);
}

$values = $xpath->query('//*[@class="respostadestaque"]');
$result = [];

// Se não encontrar CEP, retorna false
if (!$values->length) {
    throw new \Exception('CEP não encontrado');
}

You can also convert to a Exception, something like:

$checkError = $xpath->query('//*[@class="erro"]');

if ($checkError->length) {
    throw new \Exception(trim($checkError->item(0)->nodeValue));
}

Extra step

An extra detail the Xpath //*[@class="erro"] does not work well for classes (attribute class="..."), for example it will work with:

But it won’t work with:

<div class="class1 class2 respostadestaque class4" ...

Then the most appropriate Xpath would be this:

//*[contains(concat(" ", normalize-space(@class), " "), " ' . $classname . ' ")]

Extra step 2 to decode

Just like I explained in this answer documents can be saved as utf-8, in which case it is likely that the input data coming from strings or POST/GET ends up being utf-8, in which case Anderson noticed, the page does not support "accents", but in this case it should only be accents in "Unicode", if you are sure your script is in utf-8 then you should use utf8_decode:

 $dados = $buscarcep->busca(utf8_decode($enderecoP));

If your PHP scripts are using ANSI and iso-8859-1 then it is not necessary:

 $dados = $buscarcep->busca($enderecoP);

Final result

It should look something like this

<?php

if (empty($_POST['rua'])) {
   die('Você não informou a rua');
} else if (empty($_POST['cidade'])) {
   die('Você não informou a cidade');
}

$ruaP = $_POST['rua'];
$cidadeP = $_POST['cidade'];
$enderecoP = $ruaP . ' ' . $cidadeP;

class BuscaCEP
{
    private static function classSelector($classname) {
        return '//*[contains(concat(" ", normalize-space(@class), " "), " ' . $classname . ' ")]';
    }

    protected function formata($response)
    {
        $dom = new DOMDocument();
        @$dom->loadHTML($response);
        $xpath = new DOMXPath($dom);

        $checkError = $xpath->query(self::classSelector('erro'));

        if ($checkError->length) {
            throw new \Exception(trim($checkError->item(0)->nodeValue));
        }

        $values = $xpath->query(self::classSelector('respostadestaque'));
        $result = [];

        // Se não encontrar CEP, retorna false
        if (!$values->length) {
            throw new \Exception('CEP não encotrado');
        }

        // Obtém informações desejadas, tratando-as quando necessário
        foreach ($values as $value) {
            $result[] = preg_replace(
                '~[\s]{2,}~',
                '',
                trim($value->childNodes->item(0)->nodeValue)
            );
        }

        list($logradouro, $bairro, $localidade, $cep) = $result;
        list($localidade, $uf) = explode('/', $localidade);

        return compact('logradouro', 'bairro', 'localidade', 'uf', 'cep');
    }

    public function busca($cep)
    {
        $response = file_get_contents(
            'http://m.correios.com.br/movel/buscaCepConfirma.do',
            false,
            stream_context_create([
                'http' => [
                    'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
                    'method' => 'POST',
                    'content' => http_build_query([
                        'cepEntrada' => $cep,
                        'metodo' => 'buscarCep',
                    ]),
                ],
            ])
        );

        return $this->formata($response);
    }
}

try {
    $buscarcep = new BuscaCEP();
    $dados = $buscarcep->busca(utf8_encode($enderecoP));
    echo $dados['bairro'];
} catch (\Exception $e) {
    var_dump('Erro:', $e->getMessage()); //Exibe erro
}

If your scripts are saved in ANSI (probably iso-8859-1/windows-1252):

try {
    $buscarcep = new BuscaCEP();
    $dados = $buscarcep->busca($enderecoP);
    echo $dados['bairro'];
} catch (\Exception $e) {
    var_dump('Erro:', $e->getMessage()); //Exibe erro
}

  • The problem is the coding of values. As it is using "Foz de Iguaçu", the system does not find the result, while "Foz de Iguacu" (with C) works or correcting the coding.

  • @Andersoncarloswoss that’s just another one of many mistakes in the script, the mailing page should use ISO-8859-1 and does not understand Unicode, I will check, but I have a script to remove accents and should already solve.

  • Exactly. In his code, just doing $buscarcep->busca(utf8_decode($endereco01)) already makes it work, but you better understand the coding details than I do xD

  • Guys, I really don’t know how to thank you. I was focusing on other sides and I didn’t realize it could be this. Thank you so much @Guilhermenascimento and Anderson Carlos Woss for helping me!!!!

  • Now who can post the answer so I can confirm as correct answer?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.