diff --git a/parce.js b/parce.js index 21545fd..cc9daad 100644 --- a/parce.js +++ b/parce.js @@ -1,25 +1,29 @@ // Настройки скрипта -const settings = { +const SETTINGS = { + scrollDelay: 1000, // Задержка между прокрутками (в миллисекундах) + scrollStep: 72, // Шаг прокрутки (в пикселях) + enableLogs: true, // Включить логирование scrollContainerSelector: '.x1n2onr6.x1n2onr6.xyw6214.x78zum5.x1r8uery.x1iyjqo2.xdt5ytf.x6ikm8r.x1odjw0f.x1hc1fzr.x1tkvqr7', // Селектор контейнера для прокрутки participantSelector: '.x10l6tqk.xh8yej3.x1g42fcv', // Селектор элементов участников nameSelector: '.x1iyjqo2.x6ikm8r.x10wlt62.x1n2onr6.xlyipyv.xuxw1ft.x1rg5ohu._ao3e', // Селектор имени участника numberSelector: 'span._ajzr span._ao3e', // Селектор номера телефона statusSelector: '.x13faqbe._ao3e.selectable-text.copyable-text', // Селектор статуса участника - scrollStep: 72, // Высота прокрутки за один шаг (в пикселях) - scrollDelay: 1000, // Задержка между шагами прокрутки (в миллисекундах) - enableLogs: true, // Включить логирование }; +// Глобальные переменные +let allParticipants = []; // Массив для хранения всех участников +let previousParticipants = []; // Массив для хранения участников на предыдущем шаге + // Функция для прокрутки списка участников function scrollParticipants() { - const scrollContainer = document.querySelector(settings.scrollContainerSelector); // Контейнер для прокрутки + const scrollContainer = document.querySelector(SETTINGS.scrollContainerSelector); // Контейнер для прокрутки if (scrollContainer) { // Симулируем фокус на контейнере scrollContainer.focus(); - // Прокручиваем на высоту одного блока (scrollStep) - scrollContainer.scrollTop += settings.scrollStep; - if (settings.enableLogs) { + // Прокручиваем на заданный шаг + scrollContainer.scrollTop += SETTINGS.scrollStep; + if (SETTINGS.enableLogs) { console.log(`Прокрутка выполнена: scrollTop = ${scrollContainer.scrollTop}px`); } return scrollContainer.scrollTop; // Возвращаем текущее значение scrollTop @@ -29,30 +33,87 @@ function scrollParticipants() { } } +// Функция для проверки, является ли строка номером телефона +function isPhoneNumber(text) { + // Простая проверка на наличие цифр и символов, характерных для номеров + return /[\d\s\+\-()]{6,}/.test(text); +} + // Функция для парсинга данных function parseParticipants() { const participants = []; - const participantElements = document.querySelectorAll(settings.participantSelector); // Элементы участников + const participantElements = document.querySelectorAll(SETTINGS.participantSelector); // Элементы участников participantElements.forEach(participant => { - const nameElement = participant.querySelector(settings.nameSelector); - const numberElement = participant.querySelector(settings.numberSelector); // Номер телефона - const statusElement = participant.querySelector(settings.statusSelector); + const nameElement = participant.querySelector(SETTINGS.nameSelector); + const numberElement = participant.querySelector(SETTINGS.numberSelector); // Номер телефона + const statusElement = participant.querySelector(SETTINGS.statusSelector); - const name = nameElement ? nameElement.innerText : 'N/A'; - const number = numberElement ? numberElement.innerText : 'N/A'; + let name = nameElement ? nameElement.innerText : 'N/A'; + let number = numberElement ? numberElement.innerText : 'N/A'; const status = statusElement ? statusElement.innerText : 'N/A'; + // Если в поле "имя" находится номер, переносим его в поле "номер" + if (isPhoneNumber(name) && !isPhoneNumber(number)) { + number = name; + name = 'N/A'; + } + participants.push({ name, number, status }); }); return participants; } +// Функция для удаления дубликатов +function removeDuplicates(participants) { + const uniqueParticipants = []; + const seen = new Set(); + + participants.forEach(participant => { + const participantKey = `${participant.name}-${participant.number}`; // Уникальный ключ + if (!seen.has(participantKey)) { + seen.add(participantKey); + uniqueParticipants.push(participant); + } + }); + + return uniqueParticipants; +} + +// Функция для поиска новых контактов +function findNewParticipants(currentParticipants, previousParticipants) { + const newParticipants = []; + const previousKeys = new Set(previousParticipants.map(p => `${p.name}-${p.number}`)); + + currentParticipants.forEach(participant => { + const participantKey = `${participant.name}-${participant.number}`; + if (!previousKeys.has(participantKey)) { + newParticipants.push(participant); + } + }); + + return newParticipants; +} + +// Функция для создания и скачивания CSV-файла +function downloadCSV(data) { + const csvContent = "data:text/csv;charset=utf-8," + + "Имя,Номер,Статус\n" // Заголовки столбцов + + data.map(p => `"${p.name}","${p.number}","${p.status}"`).join("\n"); // Данные + + const encodedUri = encodeURI(csvContent); + const link = document.createElement("a"); + link.setAttribute("href", encodedUri); + link.setAttribute("download", "contacts.csv"); + document.body.appendChild(link); + link.click(); // Автоматически скачиваем файл + document.body.removeChild(link); +} + // Функция для автоматической прокрутки и сбора данных function collectData() { - const allParticipants = []; - const scrollContainer = document.querySelector(settings.scrollContainerSelector); + const scrollContainer = document.querySelector(SETTINGS.scrollContainerSelector); if (!scrollContainer) { console.error('Контейнер для прокрутки не найден'); @@ -61,26 +122,43 @@ function collectData() { // Получаем общую высоту контента const totalHeight = parseInt(scrollContainer.scrollHeight, 10); - if (settings.enableLogs) { + if (SETTINGS.enableLogs) { console.log(`Общая высота контента: ${totalHeight}px`); } // Функция для выполнения прокрутки и сбора данных const scrollAndCollect = () => { const currentScrollTop = scrollParticipants(); // Прокручиваем - const participants = parseParticipants(); // Собираем данные - allParticipants.push(...participants); + const currentParticipants = parseParticipants(); // Собираем данные + + // Находим новые контакты + const newParticipants = findNewParticipants(currentParticipants, previousParticipants); + if (newParticipants.length > 0 && SETTINGS.enableLogs) { + console.log(`Добавлено новых контактов: +${newParticipants.length}`); + console.log('Новые контакты:', newParticipants.map(p => `${p.name} (${p.number})`).join(', ')); + } + + // Обновляем предыдущий список участников + previousParticipants = currentParticipants; + + // Добавляем новые данные в общий массив + allParticipants.push(...newParticipants); + + // Удаляем дубликаты + allParticipants = removeDuplicates(allParticipants); // Проверяем, достигли ли мы конца списка if (currentScrollTop + scrollContainer.clientHeight >= totalHeight) { - if (settings.enableLogs) { + if (SETTINGS.enableLogs) { console.log('Достигнут нижний предел. Все данные собраны:'); console.table(allParticipants); // Вывод данных в виде таблицы } - // Здесь можно сохранить данные, например, отправить на сервер или сохранить в файл + + // Создаем и скачиваем CSV-файл + downloadCSV(allParticipants); } else { - // Продолжаем прокрутку через указанную задержку - setTimeout(scrollAndCollect, settings.scrollDelay); + // Продолжаем прокрутку через заданную задержку + setTimeout(scrollAndCollect, SETTINGS.scrollDelay); } };