/** * Nine Spices (新宿) — https://9spices.rinky.info/schedule/ * * WordPress ベースの独自テーマ。構造: *
*

タイトル

*
*
アーティスト
*
OPENhh:mm
START...
*
ADV¥XXX
*/ import * as cheerio from "cheerio"; import type { Scraper, VenueMeta } from "./base"; import type { EventInput } from "~/lib/db.server"; export const venue: VenueMeta = { id: "nine-spices", name: "Nine Spices", url: "https://9spices.rinky.info", area: "新宿", }; export const scraper: Scraper = { venue, async scrape(): Promise { const res = await fetch("https://9spices.rinky.info/schedule/"); if (!res.ok) throw new Error(`HTTP ${res.status}`); const $ = cheerio.load(await res.text()); const events: EventInput[] = []; $("div[class*='event-cont-par']").each((_, el) => { const $el = $(el); // class="event-cont-par 2026-05-01" → extract date const classAttr = $el.attr("class") ?? ""; const dateMatch = classAttr.match(/(\d{4}-\d{2}-\d{2})/); if (!dateMatch) return; const date = dateMatch[1]; const $titleLink = $el.find("h3.event-title a").first(); const title = $titleLink.text().trim(); if (!title) return; const sourceUrl = $titleLink.attr("href") ?? null; const artist = $el.find("span.actlist-name") .map((_, s) => $(s).text().trim()) .get() .join("、") || null; //
OPEN18:30
... let openTime: string | null = null; let startTime: string | null = null; $el.find("div.sch-time div").each((_, row) => { const spans = $(row).find("span"); const label = spans.eq(0).text().trim().toUpperCase(); const value = spans.eq(1).text().trim(); if (label === "OPEN") openTime = value || null; if (label === "START") startTime = value || null; }); //
ADV¥2,500
... const priceParts: string[] = []; $el.find("div.sch-price div").each((_, row) => { const spans = $(row).find("span"); const label = spans.eq(0).text().trim(); const value = spans.eq(1).text().trim(); if (label && value) priceParts.push(`${label} ${value}`); }); const price = priceParts.length ? priceParts.join(" / ") : null; const imageUrl = $el.find("img.wp-post-image").first().attr("src") ?? null; const ticketUrl = $el.find("a[href*='livepocket'], a[href*='eplus'], a[href*='pia'], a[href*='tiget'], a[href*='ticket']") .first().attr("href") ?? null; events.push({ venue_id: venue.id, title, artist, date, open_time: openTime, start_time: startTime, price, ticket_url: ticketUrl, image_url: imageUrl, source_url: sourceUrl, }); }); return events; }, };