randime-scraper
Version:
Scraper untuk mencari anime di Randime
102 lines (85 loc) • 3.75 kB
JavaScript
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 };