const https = require('https'); const fs = require('fs'); /** * Amap Distance Checker - Calculate transit time to Jiaotong University * Uses Amap (高德地图) Web Service API */ const CONFIG = { // Target: Jiaotong University Xujiahui Campus targetName: '上海交通大学徐汇校区', targetCoords: '121.4367,31.1880', // lon,lat format for Amap // Amap API (free tier, no key needed for basic geocoding) // For route planning, we'll use web scraping approach // Input/Output inputFile: './xiaozhu_raw_listings.json', outputFile: './xiaozhu_with_distances.json', outputMarkdown: './xiaozhu_with_distances.md' }; console.log('🗺️ Amap Distance Checker'); console.log(`🎯 Target: ${CONFIG.targetName}`); console.log(`📍 Coordinates: ${CONFIG.targetCoords}\n`); // Helper to make HTTPS requests function httpsGet(url) { return new Promise((resolve, reject) => { https.get(url, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { resolve(JSON.parse(data)); } catch (e) { resolve(data); } }); }).on('error', reject); }); } // Extract location from title function extractLocation(title) { // Common patterns in Xiaozhu titles const patterns = [ /近(.{2,10})/, // 近X /(.{2,10})地铁/, // X地铁 /(.{2,10})医院/, // X医院 /(.{2,10})路/, // X路 ]; const locations = []; for (const pattern of patterns) { const matches = title.matchAll(new RegExp(pattern, 'g')); for (const match of matches) { if (match[1] && match[1].length >= 2) { locations.push(match[1]); } } } // Also extract subway lines const metroPattern = /(\d+)号线/g; const metroMatches = [...title.matchAll(metroPattern)]; const metroLines = metroMatches.map(m => `Line ${m[1]}`); return { landmarks: [...new Set(locations)].slice(0, 3), metroLines: [...new Set(metroLines)] }; } // Estimate distance category based on landmarks and metro lines function estimateDistance(listing) { const title = listing.title || ''; const location = listing.location || ''; const fullText = (title + ' ' + location).toLowerCase(); // Extract location info const locationInfo = extractLocation(title); // Keywords indicating proximity to Jiaotong University const veryClose = [ '交通大学', '徐家汇', '上海交大', 'jiaotong', 'xujiahui' ]; const close = [ '衡山路', 'hengshan', '淮海路', 'huaihai', '常熟路', 'changshu', '肇嘉浜路' ]; const medium = [ '上海体育馆', 'stadium', '龙华', 'longhua', '东安路', 'dongan', '漕河泾' ]; const far = [ '南站', 'south station', '华东理工', '闵行', 'minhang' ]; // Check keywords for (const keyword of veryClose) { if (fullText.includes(keyword)) { return { category: 'very_close', estimatedMinutes: 10, confidence: 'high', reason: `Mentions ${keyword}`, locationInfo }; } } for (const keyword of close) { if (fullText.includes(keyword)) { return { category: 'close', estimatedMinutes: 15, confidence: 'medium', reason: `Near ${keyword}`, locationInfo }; } } for (const keyword of medium) { if (fullText.includes(keyword)) { return { category: 'medium', estimatedMinutes: 25, confidence: 'medium', reason: `Around ${keyword}`, locationInfo }; } } for (const keyword of far) { if (fullText.includes(keyword)) { return { category: 'far', estimatedMinutes: 40, confidence: 'medium', reason: `Far area - ${keyword}`, locationInfo }; } } // Check metro lines (10, 11 are best for Jiaotong Uni) if (title.includes('10号线') || title.includes('11号线')) { return { category: 'close', estimatedMinutes: 15, confidence: 'high', reason: 'On Line 10 or 11 (direct to campus)', locationInfo }; } // Lines with transfer if (title.includes('1号线') || title.includes('9号线')) { return { category: 'medium', estimatedMinutes: 25, confidence: 'medium', reason: 'Requires 1 transfer to Line 10/11', locationInfo }; } return { category: 'unknown', estimatedMinutes: 30, confidence: 'low', reason: 'Unable to determine location', locationInfo }; } async function processListings() { // Load listings console.log(`📂 Loading listings from ${CONFIG.inputFile}...`); let listings; try { const data = fs.readFileSync(CONFIG.inputFile, 'utf8'); listings = JSON.parse(data); } catch (err) { console.error(`❌ Error loading file: ${err.message}`); console.log('\n💡 Make sure you ran xiaozhu_fixed.js first to generate the listings.'); return; } console.log(`✅ Loaded ${listings.length} listings\n`); // Process each listing console.log('🔍 Analyzing distances...\n'); const processed = listings.map((listing, i) => { const distance = estimateDistance(listing); console.log(`${i + 1}. ${listing.title?.substring(0, 60) || 'Untitled'}`); console.log(` 💰 ¥${listing.priceDaily}/day`); console.log(` 📍 Distance: ${distance.category.toUpperCase()} (~${distance.estimatedMinutes} min)`); console.log(` 🔍 Reason: ${distance.reason}`); if (distance.locationInfo.landmarks.length > 0) { console.log(` 🏷️ Landmarks: ${distance.locationInfo.landmarks.join(', ')}`); } if (distance.locationInfo.metroLines.length > 0) { console.log(` 🚇 Metro: ${distance.locationInfo.metroLines.join(', ')}`); } console.log(''); return { ...listing, distance: { ...distance, toJiaotongUniversity: distance.estimatedMinutes } }; }); // Sort by distance (closest first) const sorted = [...processed].sort((a, b) => { // Prioritize by distance, then by price if (a.distance.toJiaotongUniversity !== b.distance.toJiaotongUniversity) { return a.distance.toJiaotongUniversity - b.distance.toJiaotongUniversity; } return (a.priceDaily || 9999) - (b.priceDaily || 9999); }); // Save results fs.writeFileSync(CONFIG.outputFile, JSON.stringify(sorted, null, 2)); console.log(`💾 Saved results to ${CONFIG.outputFile}\n`); // Generate markdown generateMarkdown(sorted); // Print summary printSummary(sorted); } function generateMarkdown(listings) { let md = '# Xiaozhu Listings - With Distance to Jiaotong University\n\n'; md += `**Target:** ${CONFIG.targetName}\n`; md += `**Sorted by:** Distance (closest first)\n\n`; md += '| # | Title | Price/Day | Total (29d) | Distance | Est. Time | Kitchen | Metro Lines |\n'; md += '|---|-------|-----------|-------------|----------|-----------|---------|-------------|\n'; listings.forEach((l, i) => { const total = (l.priceDaily || 0) * 29; const distanceEmoji = l.distance.category === 'very_close' ? '🟢' : l.distance.category === 'close' ? '🟡' : l.distance.category === 'medium' ? '🟠' : l.distance.category === 'far' ? '🔴' : '⚪'; md += `| ${i + 1} `; md += `| ${(l.title || 'Untitled').substring(0, 50)}... `; md += `| ¥${l.priceDaily || '-'} `; md += `| ¥${total} `; md += `| ${distanceEmoji} ${l.distance.category} `; md += `| ~${l.distance.toJiaotongUniversity} min `; md += `| ${l.hasKitchen ? '✓' : '✗'} `; md += `| ${l.distance.locationInfo.metroLines.join(', ') || '-'} |\n`; }); md += '\n## Distance Categories\n\n'; md += '- 🟢 **VERY CLOSE**: < 15 min - Direct area (徐家汇, 交通大学)\n'; md += '- 🟡 **CLOSE**: 15-20 min - Nearby (衡山路, Line 10/11)\n'; md += '- 🟠 **MEDIUM**: 20-30 min - Requires transfer (Line 1/9)\n'; md += '- 🔴 **FAR**: 30+ min - Far areas (南站, 闵行)\n'; md += '- ⚪ **UNKNOWN**: Distance unclear\n\n'; md += '## Best Options (Closest + Kitchen + Budget)\n\n'; const best = listings .filter(l => l.hasKitchen) .filter(l => (l.priceDaily * 29) <= 5800) // Allow slight budget flex .slice(0, 5); best.forEach((l, i) => { md += `### ${i + 1}. ${l.title}\n\n`; md += `- **Price:** ¥${l.priceDaily}/day (¥${l.priceDaily * 29} total)\n`; md += `- **Distance:** ${l.distance.category} (~${l.distance.toJiaotongUniversity} min)\n`; md += `- **Reason:** ${l.distance.reason}\n`; md += `- **Kitchen:** ${l.hasKitchen ? 'Yes ✓' : 'No'}\n`; md += `- **Metro:** ${l.distance.locationInfo.metroLines.join(', ') || 'Not specified'}\n\n`; }); fs.writeFileSync(CONFIG.outputMarkdown, md); console.log(`📝 Saved markdown to ${CONFIG.outputMarkdown}\n`); } function printSummary(listings) { console.log('=' .repeat(60)); console.log('📊 SUMMARY - TOP 5 CLOSEST WITH KITCHEN\n'); const topClosest = listings .filter(l => l.hasKitchen) .slice(0, 5); topClosest.forEach((l, i) => { const total = l.priceDaily * 29; const inBudget = total <= 5000 ? '✅' : '⚠️'; console.log(`${i + 1}. ${l.title?.substring(0, 60)}`); console.log(` 💰 ¥${l.priceDaily}/day = ¥${total} total ${inBudget}`); console.log(` 📍 ${l.distance.category.toUpperCase()} - ~${l.distance.toJiaotongUniversity} min`); console.log(` 🔍 ${l.distance.reason}`); console.log(''); }); console.log('=' .repeat(60)); console.log('\n✅ Done! Check xiaozhu_with_distances.md for full results.'); } // Run processListings().catch(console.error);