mirror of
https://github.com/Powerful-517/yys-editor.git
synced 2026-03-05 06:55:26 +00:00
fix: 修复式神抓取脚本缺失L和G类型的问题
- 添加 type=ld (L类型) 和 type=gt (G类型) 的抓取支持 - 将 RARITY_TYPES 改为对象数组,支持 URL 参数和目录名映射 - 修复图片保存路径,确保 L 和 G 类型图片正确保存到对应目录 - 现在可以完整抓取所有 8 种稀有度类型的式神数据 (SSR/SP/UR/SR/R/N/L/G)
This commit is contained in:
200
scripts/scrape-shikigami-puppeteer.js
Normal file
200
scripts/scrape-shikigami-puppeteer.js
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
const puppeteer = require('puppeteer');
|
||||||
|
const https = require('https');
|
||||||
|
const http = require('http');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const IMAGE_DIR = path.join(__dirname, '../public/assets/Shikigami');
|
||||||
|
const JSON_FILE = path.join(__dirname, '../src/data/Shikigami.json');
|
||||||
|
|
||||||
|
// Rarity types mapping: URL parameter -> directory name
|
||||||
|
const RARITY_TYPES = [
|
||||||
|
{ urlParam: 'ssr', dir: 'ssr' },
|
||||||
|
{ urlParam: 'sp', dir: 'sp' },
|
||||||
|
{ urlParam: 'ur', dir: 'ur' },
|
||||||
|
{ urlParam: 'sr', dir: 'sr' },
|
||||||
|
{ urlParam: 'r', dir: 'r' },
|
||||||
|
{ urlParam: 'n', dir: 'n' },
|
||||||
|
{ urlParam: 'ld', dir: 'l' },
|
||||||
|
{ urlParam: 'gt', dir: 'g' }
|
||||||
|
];
|
||||||
|
|
||||||
|
// Ensure image directory exists
|
||||||
|
function ensureDir(dir) {
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download image
|
||||||
|
function downloadImage(url, filepath) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const protocol = url.startsWith('https') ? https : http;
|
||||||
|
const file = fs.createWriteStream(filepath);
|
||||||
|
|
||||||
|
protocol.get(url, (response) => {
|
||||||
|
if (response.statusCode === 200) {
|
||||||
|
response.pipe(file);
|
||||||
|
file.on('finish', () => {
|
||||||
|
file.close();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
} else if (response.statusCode === 302 || response.statusCode === 301) {
|
||||||
|
downloadImage(response.headers.location, filepath).then(resolve).catch(reject);
|
||||||
|
} else {
|
||||||
|
reject(new Error(`Failed: ${response.statusCode}`));
|
||||||
|
}
|
||||||
|
}).on('error', (err) => {
|
||||||
|
fs.unlink(filepath, () => {});
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main function
|
||||||
|
async function main() {
|
||||||
|
let browser;
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('Starting Shikigami scraper with Puppeteer...\n');
|
||||||
|
|
||||||
|
// Launch browser
|
||||||
|
console.log('Launching browser...');
|
||||||
|
browser = await puppeteer.launch({
|
||||||
|
headless: 'new',
|
||||||
|
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
||||||
|
});
|
||||||
|
|
||||||
|
const page = await browser.newPage();
|
||||||
|
await page.setViewport({ width: 1920, height: 1080 });
|
||||||
|
|
||||||
|
const allShikigami = [];
|
||||||
|
const seenIds = new Set();
|
||||||
|
|
||||||
|
// Scrape each rarity type
|
||||||
|
for (const rarity of RARITY_TYPES) {
|
||||||
|
console.log(`Fetching ${rarity.dir.toUpperCase()} Shikigami (type=${rarity.urlParam})...`);
|
||||||
|
const url = `https://yys.163.com/shishen/index.html?type=${rarity.urlParam}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
|
||||||
|
|
||||||
|
// Wait for content to load
|
||||||
|
await page.waitForSelector('.shishen_item', { timeout: 10000 });
|
||||||
|
|
||||||
|
// Extract data from page
|
||||||
|
const shikigami = await page.evaluate((rarityDir) => {
|
||||||
|
const items = document.querySelectorAll('.shishen_item');
|
||||||
|
const results = [];
|
||||||
|
|
||||||
|
items.forEach(item => {
|
||||||
|
const link = item.querySelector('a');
|
||||||
|
const img = item.querySelector('img');
|
||||||
|
const nameSpan = item.querySelector('.name');
|
||||||
|
|
||||||
|
if (link && img && nameSpan) {
|
||||||
|
const href = link.getAttribute('href');
|
||||||
|
const imgSrc = img.getAttribute('src');
|
||||||
|
const name = nameSpan.textContent.trim();
|
||||||
|
const id = href.replace('.html', '');
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
imgSrc,
|
||||||
|
rarity: rarityDir.toUpperCase()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}, rarity.dir);
|
||||||
|
|
||||||
|
// Add only unique shikigami (avoid duplicates)
|
||||||
|
shikigami.forEach(s => {
|
||||||
|
if (!seenIds.has(s.id)) {
|
||||||
|
seenIds.add(s.id);
|
||||||
|
allShikigami.push(s);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Found ${shikigami.length} ${rarity.dir.toUpperCase()} Shikigami (${seenIds.size} unique total)\n`);
|
||||||
|
|
||||||
|
// Small delay
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error fetching ${rarity}:`, err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await browser.close();
|
||||||
|
|
||||||
|
console.log(`\nTotal unique Shikigami found: ${allShikigami.length}`);
|
||||||
|
|
||||||
|
if (allShikigami.length === 0) {
|
||||||
|
console.log('\n⚠ No Shikigami found. Please check the website manually.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by ID descending (newest first)
|
||||||
|
allShikigami.sort((a, b) => parseInt(b.id) - parseInt(a.id));
|
||||||
|
console.log(`Sorted by ID (newest first): ${allShikigami[0].id} -> ${allShikigami[allShikigami.length - 1].id}`);
|
||||||
|
|
||||||
|
console.log('\nDownloading images...\n');
|
||||||
|
|
||||||
|
// Ensure directories exist
|
||||||
|
RARITY_TYPES.forEach(rarity => {
|
||||||
|
ensureDir(path.join(IMAGE_DIR, rarity.dir));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Download images with progress
|
||||||
|
let downloaded = 0;
|
||||||
|
const total = allShikigami.length;
|
||||||
|
|
||||||
|
for (let i = 0; i < allShikigami.length; i++) {
|
||||||
|
const shikigami = allShikigami[i];
|
||||||
|
const { id, imgSrc, rarity, name } = shikigami;
|
||||||
|
const filename = `${id}.png`;
|
||||||
|
const filepath = path.join(IMAGE_DIR, rarity.toLowerCase(), filename);
|
||||||
|
|
||||||
|
// Skip if file already exists
|
||||||
|
if (fs.existsSync(filepath)) {
|
||||||
|
downloaded++;
|
||||||
|
process.stdout.write(`\rProgress: ${downloaded}/${total} (${name}) - skipped`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await downloadImage(imgSrc, filepath);
|
||||||
|
downloaded++;
|
||||||
|
process.stdout.write(`\rProgress: ${downloaded}/${total} (${name})`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`\n✗ Failed ${id} (${name}): ${err.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`\n\nDownloaded ${downloaded}/${total} images`);
|
||||||
|
|
||||||
|
// Update JSON file
|
||||||
|
console.log('\nUpdating JSON configuration...');
|
||||||
|
const jsonData = allShikigami.map(s => ({
|
||||||
|
avatar: `/assets/Shikigami/${s.rarity.toLowerCase()}/${s.id}.png`,
|
||||||
|
name: s.name,
|
||||||
|
rarity: s.rarity
|
||||||
|
}));
|
||||||
|
|
||||||
|
fs.writeFileSync(JSON_FILE, JSON.stringify(jsonData, null, 4), 'utf8');
|
||||||
|
console.log(`✓ Updated ${JSON_FILE}`);
|
||||||
|
|
||||||
|
console.log('\n✓ Scraping completed successfully!');
|
||||||
|
console.log(`Total: ${allShikigami.length} unique Shikigami`);
|
||||||
|
console.log(`Sorted by ID descending (newest first)`);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error:', error);
|
||||||
|
if (browser) await browser.close();
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
Reference in New Issue
Block a user