UNPKG

tester-scraper

Version:

Sebuah Module Scraper yang dibuat oleh Sxyz dan SuzakuTeam untuk memudahkan penggunaan scraper di project ESM maupun CJS.

389 lines (334 loc) 11.2 kB
import axios from "axios"; import * as cheerio from "cheerio"; import FormDatas from "form-data"; const anime = { animeIndo: async (type, opt) => { if (type === "latest") { const { data } = await axios.get("https://anime-indo.lol/"); const $ = cheerio.load(data); const result = []; $("div.menu a").each((_, el) => { const element = $(el); const img = element.find("img.lazy").attr("data-original"); const title = element.find("p").text().trim(); const episode = element.find("span.eps").text().trim(); const link = "https://anime-indo.lol" + element.attr("href"); if (!title || !episode || !img) return; result.push({ title, episode, img, link, }); }); return result; } else if (type === "search") { const query = opt?.query; if (!query) return { error: "Query kosong. Masukkan `query`." }; const formattedQuery = query.replace(/\s+/g, "-").toLowerCase(); const { data: Search } = await axios.get( `https://anime-indo.lol/search/${formattedQuery}/`, ); const $$ = cheerio.load(Search); const results = []; $$(".menu table.otable").each((_, el) => { const element = $$(el); const linkPart = element.find("td.vithumb a").attr("href"); const link = "https://anime-indo.lol" + linkPart; const img = "https://anime-indo.lol" + element.find("td.vithumb img").attr("src"); const title = element.find("td.videsc a").first().text().trim(); const description = element.find("td.videsc p.des").text().trim(); results.push({ title, img, link, description, }); }); return results; } return { msg: "Type Tidak Di Kenali!", availableType: "latest, search", availableOptions: { query: "Pakai Jika Type Anda Adalah Search", }, }; }, quotes: async () => { let { data } = await axios.get(`https://otakotaku.com/quote/feed`); let $ = cheerio.load(data); let quotes = []; $(".kotodama-list").each((i, el) => { let character = $(el).find(".char-name").text().trim(); let anime = $(el).find(".anime-title").text().trim(); let episode = $(el).find(".meta").text().trim(); let quote = $(el).find(".quote").text().trim(); let image = $(el).find(".char-img img").attr("data-src"); let link = $(el).find("a.kuroi").attr("href"); quotes.push({ character, anime, episode, quote, image, link: `https://otakotaku.com${link}`, }); }); return quotes.length > 0 ? quotes[Math.floor(Math.random() * quotes.length)] : null; }, anime9Search: async (anime) => { const { data: dataa } = await axios.get( `https://9animetv.to/search?keyword=${anime}`, ); const $ = cheerio.load(dataa); const result = []; $(".flw-item").each((i, element) => { const title = $(element).find(".film-name a").attr("title"); const url = "https://9animetv.to" + $(element).find(".film-name a").attr("href"); const imgSrc = $(element).find(".film-poster-img").attr("data-src"); const quality = $(element).find(".tick-quality").text(); const subOrDub = $(element).find(".tick-sub").text() || $(element).find(".tick-dub").text(); const episode = $(element) .find(".tick-eps") .text() .replace(/\s+/g, " ") .trim(); result.push({ title, url, imgSrc, quality, subOrDub, episode, }); }); return result; }, anime9Details: async (url) => { try { let { data } = await axios.get(url); let $ = cheerio.load(data); let title = $(".film-name").text().trim(); let image = $(".film-poster img").attr("src"); let alias = $(".alias").text().trim(); let description = $(".film-description p").text().trim(); let type = $(".item-title:contains('Type:')").next().text().trim(); let studio = $(".item-title:contains('Studios:')").next().text().trim(); let aired = $(".item-title:contains('Date aired:')").next().text().trim(); let status = $(".item-title:contains('Status:')").next().text().trim(); let score = $(".item-title:contains('Scores:')").next().text().trim(); let duration = $(".item-title:contains('Duration:')") .next() .text() .trim(); let quality = $(".item-title:contains('Quality:')").next().text().trim(); let views = $(".item-title:contains('Views:')").next().text().trim(); let genres = []; $(".item-title:contains('Genre:')") .next() .find("a") .each((_, el) => genres.push($(el).text().trim())); return { title, image, alias, description, type, studio, aired, status, score, duration, quality, views, genres, }; } catch (error) { console.error("Error fetching details:", error); return null; } }, ikoapp: { daftarAnime: async () => { const { data } = await axios.get("https://ikoapp.com/daftar_anime"); const $ = cheerio.load(data); const hasil = []; $(".grid > div").each((i, el) => { const element = $(el); const link = element.find("a").attr("href")?.trim(); const thumb = element.find("img").attr("src")?.trim(); const title = element.find("h3").text().trim(); const episode = element.find("span").first().text().trim(); const type = element.find("span").last().text().trim(); hasil.push({ title, link: "https://ikoapp.com" + link, thumbnail: "https://ikoapp.com" + thumb, episode, type, }); }); return hasil; }, search: async (animeh) => { if (!animeh) return "Masukkan Nama Anime"; const formData = new FormDatas(); formData.append("q", animeh); formData.append("type", ""); formData.append("genre", ""); formData.append("status", ""); formData.append("sort", ""); const headers = { headers: { ...formData.getHeaders(), }, }; const { data } = await axios.post( "https://ikoapp.com/anime/filter", formData, headers, ); const $ = cheerio.load(data); const results = []; $(".grid > div").each((_, el) => { const $el = $(el); const link = $el.find("a").attr("href"); const title = $el.find("h3").text().trim(); const image = $el.find("img").attr("src"); const episode = $el.find("span").eq(0).text().trim(); const type = $el.find("span").eq(1).text().trim(); results.push({ title, link: "https://ikoapp.com" + link, image: image.startsWith("http") ? image : "https://ikoapp.com" + image, episode, type, }); }); return results; }, sedangTayang: async () => { const { data } = await axios.get("https://ikoapp.com/"); const $ = cheerio.load(data); const hasil = []; $("#sedang-tayang .card-anime").each((i, el) => { const $el = $(el); const title = $el.find("h5.title").text().trim(); const image = "https://ikoapp.com" + $el.find("img").attr("src"); const type = $el.find(".badge-type").text().trim(); const episode = $el.find(".episode").text().trim(); const views = $el.find(".views").text().trim(); const link = "https://ikoapp.com" + $el.find("a.play-icon").attr("href"); hasil.push({ title, image, type, episode, views, link, }); }); return hasil; }, animeAdd: async () => { try { const { data } = await axios.get("https://ikoapp.com"); const $ = cheerio.load(data); const result = []; $("#baru-ditambahkan .col-6.col-md-4.col-lg-3").each((_, el) => { const element = $(el); const image = element.find("img").attr("src"); const title = element.find("h5.title").text().trim(); const type = element.find(".badge-type").text().trim(); const status = element.find(".status").text().trim(); const link = element.find("a.play-icon").attr("href"); result.push({ title, image: image?.startsWith("/") ? `https://ikoapp.com${image}` : image, type, status, link: link?.startsWith("/") ? `https://ikoapp.com${link}` : link, }); }); return result; } catch (err) { console.error("Gagal mengambil data:", err.message); } }, recommended: async () => { const { data } = await axios.get("https://ikoapp.com/recommendations"); const $ = cheerio.load(data); const results = []; $("main .grid > a").each((_, el) => { const $el = $(el); const title = $el.find("h2").text().trim(); const href = $el.attr("href")?.trim(); const image = $el.find("img").attr("src")?.trim(); const year = $el.find(".fa-calendar-alt").parent().text().trim(); const descShort = $el.find("p.italic").text().trim(); const descFull = $el.find("p.text-gray-400").text().trim(); const genres = []; $el.find(".flex.flex-wrap.gap-2 span").each((_, span) => { genres.push($(span).text().trim()); }); const rating = $el.find(".fa-star").parent().text().trim(); const status = $el.find(".fa-check-circle").parent().text().trim(); const views = $el.find(".fa-users").parent().text().trim(); results.push({ title, link: "https://ikoapp.com" + href, image: "https://ikoapp.com" + image, year, descShort, descFull, genres, rating, status, views, }); }); return results; }, }, otakudesu: { search: async (anime) => { if (!anime) throw new Error("Please Input A Anime Name"); const { data } = await axios.get( `https://otakudesu8.com/search/?q=${encodeURIComponent(anime)}`, ); const $ = cheerio.load(data); const results = []; $(".xrelated").each((_, el) => { const title = $(el).find(".titlelist").text().trim(); const link = $(el).find("a").attr("href"); const thumbnail = $(el).find("img").attr("src"); const rating = $(el).find(".starlist").text().trim(); const episode = $(el).find(".eplist").text().trim(); results.push({ title, link, thumbnail, rating, episode, }); }); return { success: true, searchResult: results, }; }, }, }; export default anime;