UNPKG

randime-scraper

Version:

Scraper untuk mencari anime di Randime

102 lines (85 loc) 3.75 kB
const fetch = require('node-fetch'); const { JSDOM } = require('jsdom'); const BASE_URL = "https://www.randime.moe/anime/search"; // Fungsi untuk mengambil detail anime (genre & review platform) async function fetchAnimeDetails(url) { try { const response = await fetch(url); if (!response.ok) throw new Error(`Gagal fetch data: ${response.status} ${response.statusText}`); const data = await response.text(); // Regex untuk genre const genreRegex = /<div[^>]*class="[^"]*ui:text-xs[^"]*"[^>]*>(.*?)<\/div>/g; const genres = []; let match; while ((match = genreRegex.exec(data)) !== null) { genres.push(match[1]); } // Regex untuk platform streaming dan linknya const reviewRegex = /<a href="(https:\/\/[^"]+)"[^>]*>(.*?)<\/a>/g; const reviews = {}; let reviewMatch; while ((reviewMatch = reviewRegex.exec(data)) !== null) { const platform = reviewMatch[2].trim(); const link = reviewMatch[1].trim(); if (!link.includes("youtube.com")) { reviews[platform] = link; } } return { genre: genres, review: reviews }; } catch (error) { console.error(`Error fetching anime details from ${url}:`, error); return { genre: [], review: {} }; } } // Fungsi utama untuk mengambil data anime berdasarkan query async function fetchAnimeList(query) { try { const encodedQuery = encodeURIComponent(query); const fullUrl = `${BASE_URL}?query=${encodedQuery}`; const response = await fetch(fullUrl); if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`); const html = await response.text(); const dom = new JSDOM(html); const document = dom.window.document; // Ambil semua elemen <h3> untuk judul anime const titles = Array.from(document.querySelectorAll('h3')).map(h3 => h3.textContent.trim()); // Ambil semua elemen <img> yang memiliki src mengandung "/_next/image" const images = Array.from(document.querySelectorAll('img')) .map(img => img.getAttribute('src')) .filter(src => src && src.includes('/_next/image')) .map(src => "https://www.randime.moe" + src); // Ambil deskripsi const descriptions = Array.from(document.querySelectorAll('p.text-neutral-11.line-clamp-3')) .map(p => p.textContent.trim()); // Ambil URL untuk detail anime const urls = Array.from(document.querySelectorAll('a')) .map(a => ({ href: a.getAttribute('href'), text: a.textContent.trim() })) .filter(a => a.href && a.text.includes("See more")) .map(a => "https://www.randime.moe" + a.href); let list = []; // Iterasi untuk mengambil detail tambahan for (let i = 0; i < titles.length; i++) { const animeDetails = await fetchAnimeDetails(urls[i]); list.push({ imageUrl: images[i] || "", name: titles[i], description: descriptions[i] || "No description available", url: urls[i] || "", genre: animeDetails.genre, review: animeDetails.review }); } return { status: true, baseUrl: BASE_URL, query: query, totalResult: list.length, author: "© Hams - Official", list: list }; } catch (error) { console.error("Error fetching data:", error); return { status: false, message: "Gagal mengambil data." }; } } module.exports = { fetchAnimeList };