基于Puppeteer解析Leaflet地图弹窗中污染物浓度数据的技术问题
问题解决:Puppeteer解析Leaflet地图弹窗污染物数据
问题背景
页面http://ecodata.kz:3838/app_dem_visual/上存在Leaflet交互式标记(类为awesome-marker leaflet-interactive),点击标记会弹出包含污染物浓度表格的弹窗,需要提取表格中CO、NO、NO2、SO2的实际值及24/48小时预测值。但弹窗关闭后元素会消失,原Puppeteer脚本无法正确获取数据。
原脚本核心问题
- 选择器错误:原脚本用
.ico定位标记,但实际标记的类是awesome-marker leaflet-interactive - 逻辑错误:通过
page.setContent(icon)替换页面内容,并非模拟点击原页面上的标记,无法触发弹窗加载
修正后的Puppeteer脚本
const puppeteer = require('puppeteer'); (async () => { try { const browser = await puppeteer.launch({ headless: false }); const page = await browser.newPage(); await page.goto('http://ecodata.kz:3838/app_dem_visual/', { waitUntil: 'networkidle2' }); // 等待地图标记加载完成 await page.waitForSelector('.awesome-marker.leaflet-interactive'); const markers = await page.$$('.awesome-marker.leaflet-interactive'); const allPollutantData = []; for (const [index, marker] of markers.entries()) { try { // 点击标记触发弹窗 await marker.click(); // 等待弹窗内容加载 await page.waitForSelector('.leaflet-popup-content', { timeout: 10000 }); // 提取弹窗内的所有数据 const data = await page.$eval('.leaflet-popup-content', content => { // 获取时间 const timeText = content.childNodes[0].textContent.trim(); // 获取站点名称 const stationName = content.querySelector('table caption span').textContent.trim(); // 提取表格行数据(跳过空行) const rows = Array.from(content.querySelectorAll('table tbody tr')).slice(1); const pollutants = {}; rows.forEach(row => { const cells = row.querySelectorAll('td'); if (cells.length === 4) { const pollutant = cells[0].textContent.trim(); pollutants[pollutant] = { actual: cells[1].textContent.trim(), forecast24h: cells[2].textContent.trim(), forecast48h: cells[3].textContent.trim() }; } }); return { stationName, time: timeText, pollutants }; }); allPollutantData.push(data); // 关闭弹窗,避免影响下一个标记点击 const closeBtn = await page.$('.leaflet-popup-close-button'); if (closeBtn) { await closeBtn.click(); // 等待弹窗消失 await page.waitForSelector('.leaflet-popup-content', { hidden: true, timeout: 5000 }); } console.log(`已获取第 ${index + 1} 个站点数据`); } catch (error) { console.error(`处理第 ${index + 1} 个标记时出错:`, error); // 若弹窗未正常加载,尝试关闭现有弹窗继续 const closeBtn = await page.$('.leaflet-popup-close-button'); if (closeBtn) await closeBtn.click(); } } console.log('\n所有站点污染物数据:', JSON.stringify(allPollutantData, null, 2)); await browser.close(); } catch (error) { console.error('脚本执行出错:', error); } })();
脚本说明
- 使用正确选择器定位地图标记
- 逐个点击标记,等待弹窗加载后提取完整数据(站点名称、时间、污染物数值)
- 提取完成后关闭弹窗,确保不干扰下一个标记的操作
- 增加错误处理,避免单个标记的问题导致整个脚本中断
内容的提问来源于stack exchange,提问作者Magzhan Malades
相关产品推荐
相关产品推荐

