utils/parse/collect_promo_links.js

207 lines
9.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ==UserScript==
// @name Yandex Promo Links Collector (Multi-Query Console Version)
// @namespace yandex.console.collector.promo.multi
// @version 1.2
// @description Собирает промо ссылки из выдачи Яндекса для нескольких запросов — версия для Tampermonkey (единый вывод)
// @match https://yandex.ru/search/*
// @match https://www.yandex.ru/search/*
// @match https://yandex.com/search/*
// @grant GM_xmlhttpRequest
// @connect yandex.ru
// @connect yandex.com
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
// === НАСТРОЙКИ ===
const QUERIES = [
'купить Great Wall в Краснодаре',
'купить BYD в Краснодаре',
'купить SAIC в Краснодаре',
'купить BAIC в Краснодаре',
'купить Lifan в Краснодаре',
'купить Zotye в Краснодаре',
'купить Brilliance в Краснодаре',
'купить Hongqi в Краснодаре',
'купить Tank в Краснодаре',
'купить Lynk & Co в Краснодаре',
'купить Zeekr в Краснодаре',
'купить Nio в Краснодаре',
'купить Xpeng в Краснодаре',
'купить Li Auto в Краснодаре',
'купить Seres в Краснодаре',
'купить Aion в Краснодаре',
'купить Forthing в Краснодаре',
'купить Dayun в Краснодаре',
'купить авто с пробегом в Краснодаре',
'купить б/у автомобиль в Краснодаре',
'подержанные машины в Краснодаре',
'автосалоны с пробегом в Краснодаре',
'купить подержанный авто в Краснодаре',
'б/у Haval в Краснодаре',
'б/у Chery в Краснодаре',
'б/у Geely в Краснодаре',
'б/у Changan в Краснодаре',
'б/у Exeed в Краснодаре',
'б/у Jetour в Краснодаре',
'б/у GAC в Краснодаре',
'б/у Jaecoo в Краснодаре',
'б/у FAW в Краснодаре',
'б/у DongFeng в Краснодаре',
'б/у JAC в Краснодаре',
'б/у Kaiyi в Краснодаре',
'б/у BAIC в Краснодаре',
'б/у Lifan в Краснодаре',
'б/у Hongqi в Краснодаре',
'б/у Tank в Краснодаре',
'б/у Nio в Краснодаре',
'б/у Xpeng в Краснодаре',
'автосалоны подержанных авто в Краснодаре',
'купить машину с пробегом от дилера в Краснодаре',
'trade-in авто в Краснодаре',
'обмен авто с пробегом в Краснодаре',
'сертифицированные б/у автомобили в Краснодаре'
];
const MAX_PAGES_PER_QUERY = 3;// Макс. страниц на запрос
const PAGE_DELAY_MS = 500;// Задержка между страницами
const QUERY_DELAY_MS = 1000;// Задержка между запросами (чтобы не блочить)
// =================
var allLinks = [];
var uniqueLinks = new Set();
var baseUrl = window.location.origin;
// === ФУНКЦИИ ===
function cleanUrl(url) {
try {
var urlObj = new URL(url);
urlObj.searchParams.delete('primary_reqid');
urlObj.searchParams.delete('rnd');
urlObj.searchParams.delete('reqid');
return urlObj.toString();
} catch (e) {
return url;
}
}
function processPage(doc, queryLinks) {
var nodes = doc.querySelectorAll('li.serp-item a[href]');
var pageLinks = [];
for (var i = 0; i < nodes.length; i++) {
var href = nodes[i].getAttribute('href');
if (href && href.startsWith('https://yabs.yandex.ru')) {
var fullUrl = href.startsWith('http') ? href : baseUrl + href;
var cleanedUrl = cleanUrl(fullUrl);
if (!uniqueLinks.has(cleanedUrl)) {
uniqueLinks.add(cleanedUrl);
pageLinks.push(cleanedUrl);
queryLinks.push(cleanedUrl);
}
}
}
return pageLinks.length;
}
function getNextPageUrl(doc) {
var nextBtn = doc.querySelector('a.Pager-Item_type_next');
if (!nextBtn) {
nextBtn = doc.querySelector('a[aria-label="Следующая страница"]');
}
if (nextBtn) {
var href = nextBtn.getAttribute('href');
if (href) {
return href.startsWith('http') ? href : baseUrl + href;
}
}
return null;
}
async function processQuery(query) {
var queryLinks = [];
var pagesProcessed = 0;
var searchUrl = `${baseUrl}/search/?text=${encodeURIComponent(query)}`;
try {
var html = await gmFetch(searchUrl);
var parser = new DOMParser();
var doc = parser.parseFromString(html, 'text/html');
processPage(doc, queryLinks);
pagesProcessed++;
var nextUrl = getNextPageUrl(doc);
while (nextUrl && pagesProcessed < MAX_PAGES_PER_QUERY) {
await new Promise(r => setTimeout(r, PAGE_DELAY_MS));
html = await gmFetch(nextUrl);
doc = parser.parseFromString(html, 'text/html');
processPage(doc, queryLinks);
pagesProcessed++;
nextUrl = getNextPageUrl(doc);
}
console.log(`[Запрос: "${query}"] Обработано страниц: ${pagesProcessed}, промо ссылок: ${queryLinks.length}`);
allLinks.push(queryLinks.join('\n'));
} catch (error) {
console.error(`❌ Ошибка для запроса "${query}":`, error);
}
return queryLinks.length;
}
// === TAMPERMONKEY-ОБЁРТКИ ===
function gmFetch(url) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: url,
headers: {
'User-Agent': navigator.userAgent,
'Referer': baseUrl
},
onload: (response) => {
if (response.status >= 200 && response.status < 300) {
resolve(response.responseText);
} else {
reject(new Error(`HTTP ${response.status}`));
}
},
onerror: (err) => reject(err),
ontimeout: (err) => reject(new Error('Timeout'))
});
});
}
function copyToClipboard(text) {
if (navigator.clipboard && window.isSecureContext) {
return navigator.clipboard.writeText(text);
}
return new Promise((resolve, reject) => {
try {
var textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
document.body.appendChild(textarea);
textarea.focus();
textarea.select();
var success = document.execCommand('copy');
document.body.removeChild(textarea);
success ? resolve() : reject();
} catch (e) {
reject(e);
}
});
}
// === ЗАПУСК ===
console.log(`🚀 Запуск сбора промо ссылок для ${QUERIES.length} запросов (макс. страниц на запрос: ${MAX_PAGES_PER_QUERY})...`);
(async function run() {
var totalLinks = 0;
for (let i = 0; i < QUERIES.length; i++) {
if (i > 0) await new Promise(r => setTimeout(r, QUERY_DELAY_MS));
totalLinks += await processQuery(QUERIES[i]);
}
// === ФИНАЛЬНЫЙ ВЫВОД ===
console.log('\n' + '='.repeat(50));
console.log(`✅ СБОР ЗАВЕРШЁН`);
console.log(`📄 Запросов обработано: ${QUERIES.length}`);
console.log(`🔗 Промо ссылок собрано всего: ${totalLinks}`);
console.log('='.repeat(50) + '\n');
if (totalLinks > 0) {
var outputText = allLinks.join('\n');
console.log(outputText);
await copyToClipboard(outputText);
console.log('\n✅ Все промо ссылки (с разделителями по запросам) скопированы в буфер обмена!');
console.log('💡 Нажмите Ctrl+V в любом месте для вставки');
} else {
console.log('⚠️ Промо ссылки не найдены');
}
})();
})();