/** * 新代田 FEVER — https://www.fever-popo.com * * Movable Type CMS。月別 URL: /schedule/YYYY/MM/ * DOM 構造: *
アーティスト1
アーティスト2
ADV ¥XXXX (+1drink) / DOOR ¥XXXX (+1drink)
in body
const $h3 = $el.find("div.asset-body h3").first();
const artist = $h3.find("p").text()
.split(/\n|
/i)
.map((s) => s.replace(/<[^>]+>/g, "").trim())
.filter(Boolean)
.join("、") || null;
// Time: div containing "OPEN" / "START"
let openTime: string | null = null;
let startTime: string | null = null;
$el.find("div.asset-body div").each((_, d) => {
const text = $(d).text();
if (/OPEN/i.test(text) && /START/i.test(text)) {
const om = text.match(/OPEN\s*(\d{1,2}:\d{2})/i);
const sm = text.match(/START\s*(\d{1,2}:\d{2})/i);
if (om) openTime = om[1];
if (sm) startTime = sm[1];
}
});
// Price: div after the time div
let price: string | null = null;
$el.find("div.asset-body div").each((_, d) => {
const text = $(d).text().trim();
if (/[¥¥]/.test(text) && /(ADV|DOOR|前売|当日)/i.test(text)) {
price = text.replace(/\s+/g, " ").split("\n")[0].trim() || null;
}
});
// Image
const imageUrl = $el.find("img.scpickup").first().attr("src") ?? null;
// Ticket URL
const ticketUrl =
$el.find("a[href*='eplus'], a[href*='pia'], a[href*='tiget'], a[href*='livepocket'], a[href*='t-dv.com']")
.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;
}
export const scraper: Scraper = {
venue,
async scrape(): Promise