Sylvatica.

Back to Library

Scrape Nekopoi

js 1/26/2026
16
const axios = require("axios");
const cheerio = require("cheerio");

async function nekopoiSearch(query, page = 1) {
  const baseUrl = "https://nekopoi.care/search/";
  const results = [];

  try {
    const url =
      page === 1
        ? `${baseUrl}${query}`
        : `${baseUrl}${query}/page/${page}/?${query}`;
    const response = await axios.get(url, {
      headers: {
        "User-Agent":
          "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
      },
    });

    const $ = cheerio.load(response.data);
    const items = $("div.result ul li");

    if (items.length === 0) throw "Tidak ada hasil ditemukan di halaman ini.";

    items.each((index, element) => {
      const titleElement = $(element).find("h2 a");
      const title = titleElement.text().trim();
      const url = titleElement.attr("href");
      const thumbnail = $(element).find("img").attr("src");
      if (title && url) results.push({ title, url, thumbnail });
    });

    return results;
  } catch (error) {
    throw `Gagal melakukan pencarian: ${error.message || error}`;
  }
}

async function nekopoiDetail(url) {
  try {
    const response = await axios.get(url, {
      headers: {
        "User-Agent":
          "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, seperti Gecko) Chrome/91.0.4472.124 Safari/537.36",
      },
    });

    const $ = cheerio.load(response.data);
    const result = {
      title: $("div.eroinfo h1").text().trim(),
      parody: "",
      producer: "",
      duration: "",
      views: "",
      date: "",
      thumbnail: $("div.thm img").attr("src"),
      sizes: {},
      streams: [],
      downloads: {},
    };

    $("div.konten p").each((_, el) => {
      const text = $(el).text().trim();
      if (text.startsWith("Parody")) result.parody = text.replace("Parody : ", "").trim();
      else if (text.startsWith("Producers")) result.producer = text.replace("Producers : ", "").trim();
      else if (text.startsWith("Duration")) result.duration = text.replace("Duration : ", "").trim();
      else if (text.includes("Size")) {
        const sizeMatches = text.match(/(\d+P)\s*:\s*(\d+mb)/g);
        if (sizeMatches) {
          sizeMatches.forEach((match) => {
            const [res, size] = match.split(" : ");
            result.sizes[res.trim()] = size.trim();
          });
        }
      }
    });

    const info = $("div.eroinfo p").text().trim();
    result.views = info.match(/Dilihat\s+(\d+)\s+kali/)?.[1] || "N/A";
    result.date = info.match(/\/\s+(.+)/)?.[1]?.trim() || "N/A";

    $("div#show-stream div.openstream iframe").each((i, el) => {
      const src = $(el).attr("src");
      if (src) result.streams.push({ name: `Stream ${i + 1}`, url: src });
    });

    $("div.boxdownload div.liner").each((_, el) => {
      const res = $(el).find("div.name").text().match(/\[(\d+p)\]/)?.[1];
      if (res) {
        const links = { normal: [], ouo: [] };
        $(el)
          .find("div.listlink p a")
          .each((__, link) => {
            const href = $(link).attr("href");
            const text = $(link).text().trim();
            if (href.includes("ouo.io"))
              links.ouo.push({ name: text.replace("[ouo]", ""), url: href });
            else links.normal.push({ name: text, url: href });
          });
        result.downloads[res] = links;
      }
    });

    if (!result.title) throw "Data detail tidak ditemukan.";
    return result;
  } catch (error) {
    throw `Gagal mengambil detail: ${error.message || error}`;
  }
}

module.exports = { nekopoiSearch, nekopoiDetail };