initial commit
This commit is contained in:
commit
8e7903dc34
20
.gitignore
vendored
Normal file
20
.gitignore
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
.output
|
||||
|
||||
# Vite files
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
.vite/
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
200
parse/collect_dealers_autoru.js
Normal file
200
parse/collect_dealers_autoru.js
Normal file
@ -0,0 +1,200 @@
|
||||
(async function() {
|
||||
const csrfToken = "79684b90849bec4c80846f355dd1671b48338cc739007d81"; // ← ОБНОВИ!
|
||||
const url = "https://auto.ru/krasnodar/dilery/cars/new/?place_lat_from=46.65304&place_lon_from=38.80775&place_lat_to=48.07858&place_lon_to=40.5024&geo_radius=300"; // Вставьте URL здесь
|
||||
const params = new URLSearchParams(url.split('?')[1]);
|
||||
const latMin = parseFloat(params.get('place_lat_from'));
|
||||
const latMax = parseFloat(params.get('place_lat_to'));
|
||||
const lonMin = parseFloat(params.get('place_lon_from'));
|
||||
const lonMax = parseFloat(params.get('place_lon_to'));
|
||||
const numLatSplits = 2;
|
||||
const numLonSplits = 2;
|
||||
const maxDepth = 10; // Максимальная глубина рекурсии (чтобы не бесконечно разбивать)
|
||||
let allDealers = [];
|
||||
const seenCodes = new Set();
|
||||
// Функция для задержки (чтобы не спамить API)
|
||||
function delay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
// Рекурсивная функция для обработки области
|
||||
async function processArea(latFrom, latTo, lonFrom, lonTo, depth = 0) {
|
||||
if (depth > maxDepth) {
|
||||
console.warn(`🚨 Максимальная глубина (${maxDepth}) достигнута для lat ${latFrom}-${latTo}, lon ${lonFrom}-${lonTo}. Пропускаем.`);
|
||||
return;
|
||||
}
|
||||
const body = {
|
||||
"section": "new",
|
||||
"category": "cars",
|
||||
"place_lat_from": latFrom.toFixed(6),
|
||||
"place_lat_to": latTo.toFixed(6),
|
||||
"place_lon_from": lonFrom.toFixed(6),
|
||||
"place_lon_to": lonTo.toFixed(6),
|
||||
"__dont_change_map": 1,
|
||||
"geo_radius": 300,
|
||||
"geo_id": [35],
|
||||
"page": 1,
|
||||
"page_size": 100
|
||||
};
|
||||
const areaDesc = `lat ${body.place_lat_from}-${body.place_lat_to}, lon ${body.place_lon_from}-${body.place_lon_to}`;
|
||||
console.log(`\n${depth > 0 ? 'Рекурсия lvl ' + depth + ': ' : ''}Запрос для ${areaDesc}`);
|
||||
try {
|
||||
await delay(50); // Пауза 0.5 сек между запросами
|
||||
const res = await fetch("https://auto.ru/-/ajax/desktop-search/dealersListing/", {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Csrf-Token": csrfToken,
|
||||
"Accept": "application/json",
|
||||
"Referer": "https://auto.ru/"
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
if (!res.ok) {
|
||||
console.warn(`Ошибка ${res.status} для ${areaDesc}`);
|
||||
return;
|
||||
}
|
||||
const data = await res.json();
|
||||
if (data.totalResultsCount && data.totalResultsCount > 100) {
|
||||
console.log(`⚠️ Total = ${data.totalResultsCount} > 100. Разбиваем на 4 под-области (глубина ${depth + 1}).`);
|
||||
// Разбиваем на 2x2
|
||||
const latMid = (latFrom + latTo) / 2;
|
||||
const lonMid = (lonFrom + lonTo) / 2;
|
||||
await processArea(latFrom, latMid, lonFrom, lonMid, depth + 1);
|
||||
await processArea(latFrom, latMid, lonMid, lonTo, depth + 1);
|
||||
await processArea(latMid, latTo, lonFrom, lonMid, depth + 1);
|
||||
await processArea(latMid, latTo, lonMid, lonTo, depth + 1);
|
||||
return; // Не обрабатываем текущую область дальше, т.к. разбили
|
||||
}
|
||||
if (!data.dealers) return;
|
||||
let newCount = 0;
|
||||
for (const d of data.dealers) {
|
||||
const code = d.dealerCode || d.code || d.id || d.dealerName;
|
||||
if (code && !seenCodes.has(code)) {
|
||||
seenCodes.add(code);
|
||||
allDealers.push(d);
|
||||
newCount++;
|
||||
}
|
||||
}
|
||||
console.log(` +${data.dealers.length} дилеров (новых: ${newCount}, всего: ${allDealers.length})`);
|
||||
console.log(` Total в области: ${data.totalResultsCount || 'неизвестно'}`);
|
||||
} catch (e) {
|
||||
console.error(`Ошибка для ${areaDesc}:`, e);
|
||||
}
|
||||
}
|
||||
// Генерация начальных областей
|
||||
const latStep = (latMax - latMin) / numLatSplits;
|
||||
const lonStep = (lonMax - lonMin) / numLonSplits;
|
||||
const subAreas = [];
|
||||
for (let i = 0; i < numLatSplits; i++) {
|
||||
const latFrom = latMin + i * latStep;
|
||||
const latTo = (i === numLatSplits - 1 ? latMax : latMin + (i + 1) * latStep);
|
||||
for (let j = 0; j < numLonSplits; j++) {
|
||||
const lonFrom = lonMin + j * lonStep;
|
||||
const lonTo = (j === numLonSplits - 1 ? lonMax : lonMin + (j + 1) * lonStep);
|
||||
subAreas.push({ latFrom, latTo, lonFrom, lonTo });
|
||||
}
|
||||
}
|
||||
console.log(`Сгенерировано начальных областей: ${subAreas.length} (${numLatSplits}×${numLonSplits})`);
|
||||
console.log(`Размер одного квадрата ≈ ${(latStep * 111).toFixed(1)} × ${((lonStep * 111) * Math.cos((latMin + latMax) / 2 * Math.PI / 180)).toFixed(1)} км`);
|
||||
// Обработка всех начальных областей последовательно
|
||||
for (let idx = 0; idx < subAreas.length; idx++) {
|
||||
const { latFrom, latTo, lonFrom, lonTo } = subAreas[idx];
|
||||
await processArea(latFrom, latTo, lonFrom, lonTo);
|
||||
}
|
||||
console.log(`\n✅ Готово! Собрано уникальных дилеров: ${allDealers.length}`);
|
||||
// Вывод всех дилеров в консоль в табличном виде
|
||||
console.table(allDealers);
|
||||
const codes = allDealers.map(d => d.dealerCode || d.code || d.id || d.dealerName || 'unknown');
|
||||
navigator.clipboard.writeText(codes.join('\n')).then(() => {
|
||||
console.log("Коды успешно скопированы в буфер!");
|
||||
}).catch(err => {
|
||||
console.error("Ошибка копирования:", err);
|
||||
});
|
||||
// НОВАЯ ЧАСТЬ: Запрос телефонов для каждого dealerCode
|
||||
console.log("\n📞 Запрашиваем телефоны для всех дилеров...");
|
||||
let allPhones = {}; // { code: [phones] }
|
||||
let counter = 0;
|
||||
for (const d of allDealers) {
|
||||
counter++;
|
||||
console.log(counter)
|
||||
// if (counter > 10) continue;
|
||||
|
||||
const code = d.dealerCode; // Используем dealerCode, если есть
|
||||
if (!code) {
|
||||
console.warn(`Пропуск: Нет dealerCode для ${d.dealerName || d.code || d.id}`);
|
||||
continue;
|
||||
}
|
||||
console.log(`Запрос телефонов для ${code}...`);
|
||||
try {
|
||||
await delay(100); // Пауза между запросами
|
||||
const r = await fetch("https://auto.ru/-/ajax/desktop-search/getSalonPhones/", {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Csrf-Token": csrfToken,
|
||||
"Accept": "application/json",
|
||||
"Referer": "https://auto.ru/"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
code: code,
|
||||
category: "cars",
|
||||
section: "all",
|
||||
geo_radius: 300,
|
||||
geo_id: [35]
|
||||
})
|
||||
});
|
||||
console.log(`Статус для ${code}: ${r.status}`);
|
||||
if (!r.ok) {
|
||||
console.warn(`Ошибка ${r.status} для ${code}`);
|
||||
continue;
|
||||
}
|
||||
const data = await r.json();
|
||||
console.log(`Полный ответ для ${code}:`, data);
|
||||
const phones = data || [];
|
||||
phones.map((v) => {
|
||||
// phones: [{phone: '', ...}]
|
||||
if (v.phone) {
|
||||
v.phone = v.phone.replace(/\D/g, ''); // Оставляем только цифры
|
||||
}
|
||||
// add to allPhones
|
||||
if (!allPhones[code]) {
|
||||
allPhones[code] = [];
|
||||
}
|
||||
if (v.phone && !allPhones[code].includes(v.phone)) {
|
||||
allPhones[code].push(v.phone);
|
||||
}
|
||||
})
|
||||
console.log(`Телефоны для ${code}:`, phones.length ? phones : "нет телефонов");
|
||||
} catch (e) {
|
||||
console.error(`Ошибка для ${code}:`, e);
|
||||
}
|
||||
}
|
||||
// Вывод всех телефонов в таблицу
|
||||
console.log("\n📋 Все телефоны:");
|
||||
console.table(Object.entries(allPhones).map(([code, phones]) => ({
|
||||
code,
|
||||
phones: phones.join(', ') || 'нет'
|
||||
})));
|
||||
// Скопировать телефоны в буфер (code: phones)
|
||||
const phonesText = Object.entries(allPhones).map(([code, phones]) => `${code}: ${phones.join(', ') || 'нет'}`).join('\n');
|
||||
navigator.clipboard.writeText(phonesText).then(() => {
|
||||
console.log("Телефоны (code: phones) скопированы в буфер!");
|
||||
}).catch(err => {
|
||||
console.error("Ошибка копирования телефонов:", err);
|
||||
});
|
||||
})()
|
||||
|
||||
|
||||
|
||||
Latitude - Longitude
|
||||
45.430925 - 38.190931
|
||||
|
||||
Latitude - Longitude
|
||||
44.372643 - 38.190931
|
||||
|
||||
Latitude - Longitude
|
||||
44.372643 - 39.919681
|
||||
|
||||
Latitude - Longitude
|
||||
45.430925 - 39.919681
|
||||
Loading…
Reference in New Issue
Block a user