diff --git a/parse/ collect_dealers_2gis.js b/parse/ collect_dealers_2gis.js new file mode 100644 index 0000000..69a8baf --- /dev/null +++ b/parse/ collect_dealers_2gis.js @@ -0,0 +1,89 @@ +(async () => { + + const processed = new Set(); + const results = []; + + let page = 1; + + while (true) { + console.log(`📄 Страница ${page} — сбор...`); + + const cardContainers = document.querySelectorAll('div._1kf6gff'); + + for (let i = 0; i < cardContainers.length; i++) { + const container = cardContainers[i]; + + const link = container.querySelector('a[href*="/firm/"]'); + if (!link) continue; + + const href = link.href.split('?')[0]; + const idMatch = href.match(/\/firm\/([^/]+)/); + const id = idMatch ? idMatch[1] : null; + + if (!id || processed.has(id)) continue; + processed.add(id); + + const name = container.querySelector('span._lvwrwt span, h3, [class*="name"]')?.innerText.trim() || '—'; + + console.log(` 🔥 ${processed.size} — ${name}`); + + container.click(); + await new Promise(r => setTimeout(r, 300)); + + const phoneBtn = document.querySelector('button, [role="button"], [class*="phone"], [aria-label*="телефон"]'); + if (phoneBtn && /телефон|позвонить|показать/i.test(phoneBtn.innerText || phoneBtn.getAttribute('aria-label') || '')) { + phoneBtn.click(); + await new Promise(r => setTimeout(r, 300)); + } + + let secondPhone = '—'; + const allPhones = []; + document.querySelectorAll('a[href^="tel:"]').forEach(l => allPhones.push(l.href.replace('tel:', '').trim())); + + if (allPhones.length >= 2) secondPhone = allPhones[1]; + else if (allPhones.length === 1) secondPhone = allPhones[0]; + + const address = container.querySelector('[class*="address"], ._sfdp8cg, ._klarpw, ._14quei')?.innerText.trim() || '—'; + + results.push({ + name: name, + address: address, + phones: secondPhone, + link: href + }); + + const closeBtn = document.querySelector('button[aria-label*="закрыть"], [class*="close"], [class*="modal"] button'); + if (closeBtn) closeBtn.click(); + await new Promise(r => setTimeout(r, 300)); + } + + console.log(`✅ Страница ${page} обработана (${results.length} записей)`); + + const nextBtn = document.querySelector('div._n5hmn94 svg:not([style*="rotate(90deg)"])'); + const nextButtonContainer = nextBtn ? nextBtn.closest('div._n5hmn94') : null; + + if (!nextButtonContainer) { + console.log('✅ Достигнут конец списка'); + break; + } + + nextButtonContainer.click(); + console.log(`➡️ Переход на страницу ${page + 1}`); + await new Promise(r => setTimeout(r, 500)); + + page++; + } + + console.table(results); + + const csv = "data:text/csv;charset=utf-8," + + "Название;Адрес;Телефоны;Ссылка\n" + + results.map(r => `"${r.name}";"${r.address}";"${r.phones}";"${r.link}"`).join("\n"); + + const a = document.createElement('a'); + a.href = encodeURI(csv); + a.download = `автосалоны_только_вторые_${new Date().toISOString().slice(0,10)}.csv`; + a.click(); + + console.log('%c🎉 Готово! Собрано ' + results.length + ' записей (только вторые номера)', 'color:#00ff00;font-size:18px'); +})(); \ No newline at end of file