is_cli = php_sapi_name() === 'cli';
$this->initStorage();
$this->showMenu();
}
private function initStorage() {
if (!file_exists($this->storage_file)) {
file_put_contents($this->storage_file, json_encode([
'series' => [],
'episodes' => []
], JSON_PRETTY_PRINT));
}
}
private function getData() {
return json_decode(file_get_contents($this->storage_file), true);
}
private function saveData($data) {
file_put_contents($this->storage_file, json_encode($data, JSON_PRETTY_PRINT));
}
private function showMenu() {
if ($this->is_cli) {
echo "\n=== Goyabu Scraper ===\n";
echo "1. Adicionar série\n";
echo "2. Extrair episódios e players\n";
echo "3. Mostrar resultados\n";
echo "4. Sair\n";
echo "Escolha: ";
$option = trim(fgets(STDIN));
} else {
echo "
Goyabu Scraper
";
if (!isset($_GET['option'])) {
echo "
";
return;
}
$option = $_GET['option'];
}
switch ($option) {
case '1':
$this->addSeries();
break;
case '2':
$this->extractEpisodesAndPlayers();
break;
case '3':
$this->showResults();
break;
case '4':
exit("Saindo...\n");
default:
echo "Opção inválida!\n";
$this->showMenu();
}
}
private function addSeries() {
if ($this->is_cli) {
echo "\nURL da série (ex: {$this->base_url}/assistir/nome-do-anime/): ";
$url = trim(fgets(STDIN));
} else {
if (!isset($_POST['url'])) {
echo "
";
return;
}
$url = $_POST['url'];
}
if (!filter_var($url, FILTER_VALIDATE_URL)) {
$this->showMessage("URL inválida!");
return;
}
$data = $this->getData();
$data['series'][] = [
'url' => $url,
'processed' => false,
'added_at' => date('Y-m-d H:i:s')
];
$this->saveData($data);
$this->showMessage("Série adicionada com sucesso!");
if (!$this->is_cli) {
echo "
Voltar ao menu";
} else {
$this->showMenu();
}
}
private function extractEpisodesAndPlayers() {
$data = $this->getData();
if (empty($data['series'])) {
$this->showMessage("Nenhuma série para processar.");
return;
}
foreach ($data['series'] as &$series) {
if ($series['processed']) continue;
$this->showMessage("\nProcessando: {$series['url']}");
$html = $this->fetchUrl($series['url']);
if (!$html) {
$this->showMessage("Falha ao acessar a página da série.");
continue;
}
// Encontrar a posição do texto "Episódios"
$episodes_pos = stripos($html, 'Episódios');
if ($episodes_pos === false) {
$this->showMessage("Não encontrou o texto 'Episódios' na página.");
continue;
}
// Pegar o conteúdo após "Episódios"
$html_after_episodes = substr($html, $episodes_pos);
// Extrair os itens da lista que terminam com "Episódio XX"
preg_match_all('/
]*href=["\']([^"\']+)["\'][^>]*>(.*? - Episódio \d+)<\/a>/i', $html_after_episodes, $matches, PREG_SET_ORDER);
if (empty($matches)) {
$this->showMessage("Não encontrou episódios no formato esperado.");
continue;
}
$episodes = [];
foreach ($matches as $match) {
$url = $match[1];
$title = trim($match[2]);
// Extrair o número do episódio
preg_match('/Episódio (\d+)$/', $title, $ep_match);
$ep_number = $ep_match[1] ?? '0';
// Garantir URL absoluta
if (!parse_url($url, PHP_URL_SCHEME)) {
$url = $this->base_url . $url;
}
$episodes[] = [
'url' => $url,
'title' => $title,
'number' => $ep_number
];
}
$this->showMessage("Encontrados " . count($episodes) . " episódios.");
// Processar cada episódio para extrair players
foreach ($episodes as $episode) {
$this->showMessage(" Processando: {$episode['title']}");
$play_links = $this->extractPlayLinks($episode['url']);
if (!empty($play_links)) {
$this->showMessage(" Encontrados " . count($play_links) . " links de play.");
$data['episodes'][] = [
'series_url' => $series['url'],
'episode_url' => $episode['url'],
'title' => $episode['title'],
'number' => $episode['number'],
'play_links' => $play_links,
'processed_at' => date('Y-m-d H:i:s')
];
} else {
$this->showMessage(" Nenhum link de play encontrado.");
}
sleep(2); // Delay entre episódios
}
$series['processed'] = true;
$series['processed_at'] = date('Y-m-d H:i:s');
$this->saveData($data);
sleep(3); // Delay entre séries
}
$this->showMessage("\nProcessamento concluído!");
if (!$this->is_cli) {
echo "Voltar ao menu";
} else {
$this->showMenu();
}
}
private function extractPlayLinks($episode_url) {
$html = $this->fetchUrl($episode_url);
if (!$html) return [];
// Padrões para encontrar players
$patterns = [
// Iframes
'/