Skip to content

Instantly share code, notes, and snippets.

@ranisalt
Created July 6, 2014 19:12
Show Gist options
  • Save ranisalt/8a125eb62fac0d61ca07 to your computer and use it in GitHub Desktop.
Save ranisalt/8a125eb62fac0d61ca07 to your computer and use it in GitHub Desktop.
crawler
#!/usr/bin/env php
<?php
require 'simple_html_dom.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
/**
* Configurando URL, cookie e retorno da transferência
*/
curl_setopt($ch, CURLOPT_URL, 'https://sistemas.ufsc.br/login');
$get_login = trim(curl_exec($ch));
if (!$get_login) {
exit('Erro ao acessar página de login: ' . curl_error($ch));
}
echo 'Página de login acessada com sucesso', PHP_EOL;
/**
* Pegar o token da página usando simple html dom
*/
$token = str_get_html(file_get_html('https://sistemas.ufsc.br/login'))->find('input[name="lt"]')[0]->value;
/**
* Construção
*/
$post_login_fields = http_build_query(array(
'userType' => 'alunoGraduacao',
'username' => 'username',
'admin' => '0',
'password' => 'password',
'lt' => $token,
'_eventId' => 'submit',
));
/**
* Configurando o POST para fazer login
*/
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_login_fields);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
/**
* Executando login
*/
$post_login = curl_exec($ch);
if (strpos($post_login, 'Sucesso ao se logar') === FALSE)
exit('Erro ao fazer login!');
echo 'Login efetuado com sucesso!', PHP_EOL;
/**
* Limpando o cURL para o próximo request
*/
curl_setopt($ch, CURLOPT_POSTFIELDS, null );
curl_setopt($ch, CURLOPT_HTTPHEADER, array());
/**
* Configurando o GET para a página de turmas
*/
curl_setopt($ch, CURLOPT_POST, false );
curl_setopt($ch, CURLOPT_URL, 'https://cagr.sistemas.ufsc.br/modules/aluno/cadastroTurmas/' );
$get_cadastro_turmas = trim(curl_exec($ch));
if (strpos($get_cadastro_turmas, 'Cadastro de Turmas') === FALSE)
exit('Erro ao acessar cadastro de turmas: ' . curl_error($ch));
echo 'Cadastro de turmas acessado com sucesso', PHP_EOL;
$dom = str_get_html(utf8_encode($get_cadastro_turmas));
$view_state = $dom->find('input[name="javax.faces.ViewState"]')[0]->value;
$post_turmas_fields = array(
'AJAXREQUEST' => '_viewRoot',
'formBusca:selectSemestre' => $dom->find('select[id="formBusca:selectSemestre"] option[selected="selected"]')[0]->value,
'formBusca:selectDepartamento' => '',
'formBusca:selectCampus' => '0',
'formBusca:selectCursosGraduacao' => '0',
'formBusca:codigoDisciplina' => '',
'formBusca:j_id136_selection' => '',
'formBusca:filterDisciplina' => '',
'formBusca:j_id140' => '',
'formBusca:j_id144_selection' => '',
'formBusca:filterProfessor' => '',
'formBusca:selectDiaSemana' => '0',
'formBusca:selectHorarioSemana' => '',
'formBusca' => 'formBusca',
'autoScroll' => '',
'javax.faces.ViewState' => $view_state,
'formBusca:dataScroller1' => '1',
'AJAX:EVENTS_COUNT' => '1',
);
curl_setopt($ch, CURLOPT_POST, true );
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
function request_next_page(&$ch, &$dom, &$fields) {
/**
* Para incrementar a página, precisamos aumentar o valor da pesquisa
*/
++$fields['formBusca:dataScroller1'];
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
$dom = str_get_html(trim(curl_exec($ch)));
}
function request_next_campus(&$ch, &$dom, &$fields) {
/**
* Para requisitar o próximo campus, precisamos retornar à página 1 e incrementar o campus
*/
$fields['formBusca:dataScroller1'] = 1;
++$fields['formBusca:selectCampus'];
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
$dom = str_get_html(trim(curl_exec($ch)));
}
function parse_ufsc_xhtml($dom, &$dados) {
/**
* Procurar todas as linhas da tabela de horários da página atual ($dom)
*/
$search = $dom->find('table[id="formBusca:dataTable"] > tbody[id="formBusca:dataTable:tb"] > tr');
/**
* A primeira linha é o cabeçalho, porque o Simple HTML DOM é bugado
*/
array_shift($search);
/**
* Iterar sobre todas as linhas da pesquisa
*/
foreach($search as $key) {
$valor = $key->find('td');
$id = trim($valor[3]->plaintext);
/**
* No caso de ser uma disciplina nova, precisa inicializar o nome, as turmas e horas-aula.
* Caso contrário é só adicionar.
*/
if (empty($dados[$id])) {
$dados[$id] = array(
// Turmas
't' => array(),
// Nome
'n' => html_entity_decode(trim($valor[5]->plaintext)),
// Horas-aula
'h' => (int)rtrim($valor[6]->plaintext),
);
}
/**
* Explode o campo de horário + sala em:
* [1] => dia
* [2] => hora
* [3] => aulas em sequência
* [4] => sala
*/
preg_match_all('/(\d)\.(\d{4})\-(\d)\s*\/\s*(\w{3}\-\w{6})/', $valor[12]->plaintext, $horario);
$horarios = array();
for($j = 0, $max = count($horario[0]); $j < $max; ++$j)
$horarios[] = array(
// Dia
'd' => $horario[1][$j],
// Horário
'h' => $horario[2][$j],
// Aulas em sequência
'a' => $horario[3][$j],
// Sala
's' => $horario[4][$j]
);
$professor = preg_replace('/\s{2,}/', '|', trim($valor[13]->plaintext));
$dados[$id]['t'][trim($valor[4]->plaintext)] = array(
// Vagas
'v' => (int)trim($valor[7]->plaintext),
// Alunos (vagas ocupadas)
'a' => (int)trim($valor[8]->plaintext),
// Alunos especiais
'e' => (int)trim($valor[9]->plaintext),
// Horários da aula/sala
'h' => $horarios,
// Professor(es)
'p' => explode('|', $professor),
);
}
}
// Configuração do horário para o output
date_default_timezone_set('America/Sao_Paulo');
$i = 0;
$campi = $dom->find('select[id="formBusca:selectCampus"] option');
for($campus = 0, $max = count($campi); $campus < $max; ++$campus) {
$dados = array();
$i = 0;
do {
echo '[', date('H:i:s'), '] ', $campi[$campus]->innertext, ': parseando dados da página ', ++$i, PHP_EOL;
parse_ufsc_xhtml($dom, $dados);
$buttons = $dom->find('td.rich-datascr-button');
$hasnext = count($buttons) && strpos($buttons[4]->class, 'rich-datascr-button-dsbld') === FALSE;
request_next_page($ch, $dom, $post_turmas_fields);
$view_state = $dom->find('input[name="javax.faces.ViewState"]')[0]->value;
} while ($hasnext);
file_put_contents(str_replace('UFSC/', '', $campi[$campus]->innertext) . '@' . $post_turmas_fields['formBusca:selectSemestre'] . '.json', json_encode($dados));
request_next_campus($ch, $dom, $post_turmas_fields);
}
exit('Parseado com sucesso!' . PHP_EOL);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment