:::: MENU ::::

php_curl – automatização de procedimentos

Neste artigo vou mostrar uma classe que eu mesmo criei, para automatizar um processo aqui da empresa.

A necessidade aqui era basicamente criar um script que fizesse o download de arquivos e os descompactasse automaticamente, evitando assim os procedimento abaixo:

  1. Efetuar login
  2. Clicar na página de download
  3. Selecionar as opções
  4. Aguardar script que gera os arquivos
  5. Clicar no link para download
  6. Descompactar os arquivos

É isso mesmo, com esta automatização, economizamos quase uns 30 minutos de mão de obra do usuário, e ainda colocamos todos estes procedimentos na cron.

É constituído de 3 arquivos:
Robo.class.php – Classe mãe que provê todos os métodos necessários para rodar o robo
RoboImplemetacao.class.php – Classe que efetua os procedimento necessários para o download do arquivo
index.php – Arquivo que instancia a classe, e chama o método

Download dos Arquivos: robo.zip

Robo.class.php

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
<?php
/**
 * Robo
 * Provê os métodos necessário para automatização de processos repetitivos
 * utilizando-se da classe php_curl do php
 * @author Dinaerte Neto <dinaerteneto@gmail.com>
 * @version 1.0
 * @date 09/09/2013
 */
class Robo {
 
    private $_cookie = null;
    private $_oCurl = null;
    private $_html = null;
 
    public function __construct() {
 
    }
 
    /**
     * acessa a página que gera o cookie
     * grava o cookie em arquivo
     * registra o cookie no atributo _cookie
     * @param String $sUrl = url da página a ser aberta pelo curl
	 * @return void
     */
    public function setCookie($sUrl) {
        $this->_oCurl = curl_init();
        curl_setopt($this->_oCurl, CURLOPT_URL, $sUrl);
        curl_setopt($this->_oCurl, CURLOPT_COOKIEJAR, $this->getDir() . 'cookie.txt');
        curl_exec($this->_oCurl);
        curl_close($this->_oCurl);
        $cookieFile = fopen($this->getDir() . 'cookie.txt', 'r');
        while (!feof($cookieFile)) {
            $linha = fgets($cookieFile, 4096);
            if (preg_match("(JSESSIONID(.*))", $linha, $aCookie)) {
                $this->_cookie = str_replace('	', '=', $aCookie[0]);
            }
        }
        fclose($cookieFile);
    }
 
    /**
     * retorna o cookie
     * @return string
     */
    public function getCookie() {
        return $this->_cookie;
    }
 
    /**
     * retorna o diretório da aplicação
     * @return string
     */
    public function getDir() {
        return $this->_dir;
    }
 
    /**
     * define o diretório da aplicação
     * @param String $sDir
     */
    public function setDir($sDir) {
        $this->_dir = $sDir;
    }
 
	/**
	 * define o atributo _html com o html retorna pelo curl
	 * mas para que isso seja possível é necessário que CURLOPT_RETURNTRANSFER esteja definido como true
	 * @param String $sHtml = html retornado pelo curl
	 * @return void
	 */
    public function setHtml($sHtml) {
        $this->_html = $sHtml;
    }
 
	/**
	 * retorna o conteúdo do atributo _html
	 * @return String
	 */
    public function getHtml() {
        return $this->_html;
    }
 
    /**
     * abre a pagina
     * @param String $sUrl = url a ser aberta
     * @param array $aPost = array a ser enviado como post/get
     */
    protected function openPage($sUrl, $aPost = null, $sMethod = 'post') {
        $this->_oCurl = curl_init();
        curl_setopt($this->_oCurl, CURLOPT_URL, $sUrl); //CURLOPT_URL: - abre a página
        curl_setopt($this->_oCurl, CURLOPT_COOKIE, $this->getCookie()); //CURLOPT_COOKIE: - pega o cookie da página
        curl_setopt($this->_oCurl, CURLOPT_SSL_VERIFYPEER, true); //CURLOPT_SSL_VERIFYPEER: - para os casos de https://
 
        curl_setopt($this->_oCurl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'); //CURLOPT_USERAGENT: - informações do navegador utilizado
        curl_setopt($this->_oCurl, CURLOPT_HTTPHEADER, array('pt-br')); //CURLOPT_HTTPHEADER: - Idioma utitlizado pelo navegados
        curl_setopt($this->_oCurl, CURLOPT_AUTOREFERER, true); //CURLOPT_AUTOREFERER: - Informa o cabeçalho da aplicação a página anterior, ou seja, de onde veio, antes de chegar a página atual.
 
        curl_setopt($this->_oCurl, CURLOPT_HEADER, false); //CURLOPT_HEADER: - para incluir o header na saída
        curl_setopt($this->_oCurl, CURLOPT_RETURNTRANSFER , true); //CURLOPT_RETURNTRANSFER - retorna o html em formato String
 
        if ($aPost) {
            curl_setopt($this->_oCurl, CURLOPT_POST, true); //CURLOPT_POST: - Necessário para enviar $_POST ao servidor
            curl_setopt($this->_oCurl, CURLOPT_POSTFIELDS, $this->_encodeURL($aPost)); //CURLOPT_POST: - Também necessário para enviar $_POST ao servidor
        }
        $sHtml = curl_exec($this->_oCurl); //aqui acontece a mágina, é onde o curl é executado
        curl_close($this->_oCurl); //encerra o curl
        $this->setHtml($sHtml); //seta o atributo _html com o retorno
    }
 
    /**
     * lê todos os options do html
     * e retorna seus valores em formato de array
     * @return array
     */
    public function readComboBox() {
        $doc = new DOMDocument();
        $doc->loadHTML($this->getHtml());
        $aOptions = array();
        $aElement = $doc->getElementsByTagName('option');
        foreach ($aElement as $oElement) {
            $aNodes = $oElement->childNodes;
            foreach ($aNodes as $oNode) {
                $aOptions[] = $oNode->nodeValue;
            }
        }
        return $aOptions;
    }
 
    /**
     * recebe um array e retorna em formato de url
     * field1=value1&field2=value2
     * @param array $aPost
     * @return string
     */
    private function _encodeURL($aPost) {
        $sPost = null;
        if (isset($aPost)) {
            $i = 1;
            foreach ($aPost as $sField => $sValue) {
                $sPost.= $sField . '=' . urlencode($sValue);
                if (count($aPost) > $i) {
                    $sPost.='&';
                }
                $i++;
            }
        }
        return $sPost;
    }
 
    /**
     * faz download do arquivo
     * @param String $sUrl = url requisitada
     * @param String $sRequest = post ou get
     * @param String $sFilename = caminho/nome do arquivo para gravar
     * @return void
     */
    protected function downloadFile($sUrl, $sFilename) {
        $this->_oCurl = curl_init();
        curl_setopt($this->_oCurl, CURLOPT_COOKIE, $this->getCookie());
        curl_setopt($this->_oCurl, CURLOPT_URL, $sUrl);
        curl_setopt($this->_oCurl, CURLOPT_RETURNTRANSFER, true);
        $data = curl_exec($this->_oCurl);
        curl_close($this->_oCurl);
        file_put_contents($this->getDir() . $sFilename, $data);
    }
}
?>

RoboImplementacao.class.php

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<?php
/**
 * RoboImplementacao
 * criado para fazer download dos arquivos
 * sem a necessidade de que o usuário tenha que entrar no site
 * @author Dinaerte Neto <dinaerteneto@gmail.com>
 * @version 1.0
 * @date 09/09/2013
 */
class RoboImplementacao extends Robo {
    /**
     * executa os procedimentos necessários
     * para executação do robo
     */
    public function init() {
        $this->setDir(getcwd().'/robo'); //diretorio onde será mantido os arquivos
        if(!is_dir($this->getDir().'/unzip/'.date('m-Y'))) {
            mkdir($this->getDir().'/unzip/'.date('m-Y'));
        }
        $this->setCookie('https://enderecodosite.com.br/subdiretorio/acao.extensao'); //este é o endereço da página que cria o cookie
 
        //array com nomedocampo => valor as ser enviado via post
        $aPost = array(
            'login' => 'usuario',
            'password' => 'senha'
        );
        $this->openPage('https://enderecodosite.com.br/subdiretorio/pagina-login.extensao', $aPost, 'post'); //abre a página enviado o post
 
		//abre a página que deve-se abrir quando o usuários estiver logado
        $this->openPage('https://enderecodosite.com.br/subdiretorio/pagina-logado.extensao');
        $aSelecionarCombo = $this->readComboBox(); //lê o combobox da página e armazena todos os seus valores em array
		//criando os dados que serão enviados via post
        $aPost = array(
           'field1' => 'valor1',
           'field2' => 'valor2'
        );
		//percorrendo cada item do combo da página e enviando cada um destes itens via post
        foreach ($aSelecionarCombo as $sValue) {
            $aPost['fieldSelecionado'] = $sValue; //envia item a item, dos que foram selecionados no combobox
            $this->openPage('https://enderecodosite.com.br/subdiretorio/pagina-escolhas.extensao', $aPost, 'post'); //envia o post para a página
            $this->downloadFile('https://enderecodosite.com.br/subdiretorio/downloadTXT.zip', '/download/' . $sValue . '.zip'); //faz download do arquivo
 
			//após download do arquivo é solicitado o unzip deste
            $sFile = $this->getDir() . 'download/' . $sValue . '.zip';
            $sDir = $this->getDir() . 'unzip/' . date('m-Y') . '/' . $sValue . '/';
            if ($this->unzip($sFile, $sDir)) {
                echo $sValue . ' UNZIP OK ';
            } else {
                echo $sValue . ' ERRO NO UNZIP ';
            }
            echo "<br /> \n";
        }
    }
 
    /**
     * descompacta o arquivo
	 * Nesta caso em especifico, temos um zip, e dentro deste zip outros arquivos zipados
	 * por isso o unzip é realizado 2 vezes, sendo uma delas dentro do for.
     * @param string $sFile nome do arquivo a ser descompactado
     * @param string $sDir url para a qual o arquivo será enviado após descompactado
     * @return boolean
     */
    public function unzip($sFile, $sDir) {
		//se não existir o diretório de destino, então tenta cria-lo
        if (!is_dir($sDir)) {
            $old = umask(0);
            mkdir($sDir, 0777);
            umask($old);
        }
        $aZip = array();
        $oZip = new ZipArchive;
        if ($oZip->open($sFile) === true) {
			//percorre todos os zips existentes dentro do zip original e adiciona no array $aZip
			for ($i = 0; $i < $oZip->numFiles; $i++) {
                $aZip[] = $oZip->getNameIndex($i);
            }
			//extrai o arquivo original para o diretório de destino
            $oZip->extractTo($sDir);
            $oZip->close();
            unlink($sFile);
 
			//percorre o array $aZip e descompacta um por um
            foreach ($aZip as $sZipname) {
                $oZip = new ZipArchive;
                if ($oZip->open($sDir . '/' . $sZipname) === true) {
                    $oZip->extractTo($this->getDir() . '/unzip/'.date('m-Y').'/');
                    $oZip->close();
                    unlink($sDir . '/' . $sZipname); //remove o arquivo zip
                    rmdir($sDir); //remove o diretório como o nome do arquivo
                } else {
                    return false;
                }
            }
        } else {
            return false;
        }
        return true;
    }
}
?>

index.php

1
2
3
4
<?php
   $oRobo = new RoboImplementacao();
   $oRobo->init();
?>

So, what do you think ?