您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Profi-Analysator mit detaillierter JSON-Ausgabe als Standard und Multi-Auswahl (STRG).
当前为
// ==UserScript== // @name Der ultimative Element-Analysator für Kleinanzeigen 🛠️ // @namespace http://tampermonkey.net/ // @version 14.2 // @description Profi-Analysator mit detaillierter JSON-Ausgabe als Standard und Multi-Auswahl (STRG). // @author Assistant & User // @license MIT // @match https://www.kleinanzeigen.de/* // @icon https://t1.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://kleinanzeigen.de&size=64 // @grant GM_addStyle // @grant GM_setClipboard // ==/UserScript== (function() { 'use strict'; // Globale Variablen & Cache für Performance let pickerMode = false, pickerButton = null, lastHoveredElement = null, selectedElements = []; let isDragging = false, wasDragging = false, offsetX, offsetY; const defaultStylesCache = new Map(); // CSS-Stile für das Skript GM_addStyle(` #element-picker-btn { position: fixed; right: 20px; top: 50%; transform: translateY(-50%); width: 50px; height: 50px; background: #007185; border: none; border-radius: 50%; cursor: grab; z-index: 9999; box-shadow: 0 2px 10px rgba(0,0,0,0.3); display: flex; align-items: center; justify-content: center; transition: background-color 0.3s ease; } #element-picker-btn:hover { background-color: #005a6b; } body.picker-dragging, body.picker-dragging * { cursor: grabbing !important; } #element-picker-btn.active { background: #dc3545; animation: pulse 1s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(220, 53, 69, 0); } 100% { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0); } } .picker-cursor, .picker-cursor * { cursor: crosshair !important; } .picker-highlight { outline: 2px solid red !important; outline-offset: 1px !important; background-color: rgba(255, 0, 0, 0.1) !important; } .picker-selected { outline: 2px solid #007bff !important; outline-offset: 1px !important; background-color: rgba(0, 123, 255, 0.15) !important; } .picker-notification { position: fixed; top: 20px; right: 20px; background: #28a745; color: white; padding: 10px 20px; border-radius: 5px; z-index: 10000; font-family: Arial, sans-serif; font-size: 14px; animation: slideIn 0.3s ease-out; } @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .picker-status { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); background: #dc3545; color: white; padding: 8px 16px; border-radius: 5px; z-index: 10000; font-family: Arial, sans-serif; font-size: 12px; font-weight: bold; } `); // --- PARSING-FUNKTIONEN --- function parseLocation(locationString) { if (!locationString) return { plz: null, stadt: null, entfernung_km: null }; const cleanString = locationString.replace(/\s+/g, ' ').trim(); const plzMatch = cleanString.match(/^(\d{5})/); const cityMatch = cleanString.match(/^\d{5}\s(.+?)(?:\s\()/); const distanceMatch = cleanString.match(/\((\d+)\s*km\)/); return { plz: plzMatch ? plzMatch[1] : null, stadt: cityMatch ? cityMatch[1].trim() : cleanString.split('(')[0].trim(), entfernung_km: distanceMatch ? parseInt(distanceMatch[1], 10) : null }; } function parsePrice(priceString) { if (!priceString) return { betrag: null, zusatz: null }; const cleanString = priceString.replace(/\s+/g, ' ').trim(); const betragMatch = cleanString.match(/(\d+)/); const zusatzMatch = cleanString.match(/VB/i); return { betrag: betragMatch ? parseInt(betragMatch[1], 10) : null, zusatz: zusatzMatch ? 'VB' : null }; } // --- DATENEXTRAKTION (immer mit allen Details) --- function getCompressedCss(element) { const hadHighlight = element.classList.contains('picker-highlight'); if (hadHighlight) element.classList.remove('picker-highlight'); const tagName = element.tagName; if (!defaultStylesCache.has(tagName)) { const dummy = document.createElement(tagName); document.body.appendChild(dummy); defaultStylesCache.set(tagName, window.getComputedStyle(dummy)); document.body.removeChild(dummy); } const styles = window.getComputedStyle(element); const defaultStyles = defaultStylesCache.get(tagName); const cssProps = []; const relevantProperties = [ 'display', 'position', 'flex-direction', 'justify-content', 'align-items', 'width', 'height', 'margin', 'padding', 'border', 'border-radius', 'font-weight', 'color' ]; for (const prop of relevantProperties) { const value = styles.getPropertyValue(prop); if (value !== defaultStyles.getPropertyValue(prop)) { cssProps.push(`${prop}: ${value}`); } } if (hadHighlight) element.classList.add('picker-highlight'); return cssProps.length > 0 ? `{ ${cssProps.join('; ')} }` : ''; } function buildChildTree(element, level = 0) { let treeText = ''; const indentation = ' '.repeat(level); for (const child of element.children) { if (child.tagName === 'SCRIPT') continue; const childCss = getCompressedCss(child); const classAttr = child.className.replace(/picker-highlight|picker-selected/g, '').trim(); treeText += `${indentation}└─ <${child.tagName.toLowerCase()}${classAttr ? ` class="${classAttr}"` : ''}> ${childCss}\n`; if (child.children.length > 0) { treeText += buildChildTree(child, level + 1); } } return treeText; } function extractElementData(adListItem) { const classList = adListItem.className.replace(/picker-highlight|picker-selected/g, '').trim(); const keyData = {}; const titleElement = adListItem.querySelector('h2.text-module-begin a.ellipsis, h2.text-module-begin span.ellipsis'); if (titleElement) keyData.title = titleElement.textContent.trim(); const descElement = adListItem.querySelector('.aditem-main--middle--description'); if (descElement) keyData.description = descElement.textContent.trim().replace(/\s+/g, ' '); const priceElement = adListItem.querySelector('.aditem-main--middle--price-shipping--price'); if (priceElement) keyData.price = parsePrice(priceElement.textContent); const locationElement = adListItem.querySelector('.aditem-main--top--left'); if (locationElement) keyData.location = parseLocation(locationElement.textContent); const dateElement = adListItem.querySelector('.aditem-main--top--right'); if (dateElement) keyData.date = dateElement.textContent.trim(); const linkElement = adListItem.querySelector('a[href^="/s-anzeige/"]'); if(linkElement) keyData.link = `https://www.kleinanzeigen.de${linkElement.getAttribute('href')}`; // Die Debug-Infos werden jetzt immer hinzugefügt const blueprintData = { source_url: window.location.href, container: { tag: adListItem.tagName.toLowerCase(), class: classList }, key_data: keyData, structure_and_styles: buildChildTree(adListItem) || "(No child elements found)", raw_html: compactHTML(adListItem.outerHTML) }; return blueprintData; } // --- HAUPTFUNKTION mit vereinfachter Logik --- function onElementClick(e) { if (!pickerMode || e.target.closest('#element-picker-btn')) return; e.preventDefault(); e.stopPropagation(); const adListItem = findAdListItem(e.target); if (!adListItem) { showNotification('Kein ad-listitem Element gefunden!'); return; } if (e.ctrlKey) { const index = selectedElements.indexOf(adListItem); if (index > -1) { adListItem.classList.remove('picker-selected'); selectedElements.splice(index, 1); } else { adListItem.classList.add('picker-selected'); selectedElements.push(adListItem); } showStatus(`${selectedElements.length} Element(e) ausgewählt. Klick ohne STRG zum Kopieren.`); } else { let elementsToCopy = selectedElements.length > 0 ? selectedElements : [adListItem]; if (!elementsToCopy.includes(adListItem)) elementsToCopy.push(adListItem); // Shift-Logik entfernt, es werden immer alle Daten extrahiert const allData = elementsToCopy.map(element => extractElementData(element)); const outputData = allData.length === 1 ? allData[0] : allData; const jsonOutput = JSON.stringify(outputData, null, 2); GM_setClipboard(jsonOutput, 'text'); showNotification(`${elementsToCopy.length} Blaupause(n) als JSON kopiert!`); deactivatePickerMode(); } } // (Restliche Hilfsfunktionen unverändert) function makeButtonDraggable(button) { button.addEventListener('mousedown', (e) => { if (e.button !== 0 || pickerMode) return; isDragging = true; wasDragging = false; document.body.classList.add('picker-dragging'); button.style.cursor = 'grabbing'; button.style.transition = 'none'; const rect = button.getBoundingClientRect(); button.style.left = `${rect.left}px`; button.style.top = `${rect.top}px`; button.style.right = 'auto'; button.style.transform = 'none'; offsetX = e.clientX - rect.left; offsetY = e.clientY - rect.top; document.addEventListener('mousemove', onDragMove); document.addEventListener('mouseup', onDragEnd); }); function onDragMove(e) { if (!isDragging) return; e.preventDefault(); wasDragging = true; let newX = e.clientX - offsetX; let newY = e.clientY - offsetY; newX = Math.max(0, Math.min(newX, window.innerWidth - button.offsetWidth)); newY = Math.max(0, Math.min(newY, window.innerHeight - button.offsetHeight)); button.style.left = `${newX}px`; button.style.top = `${newY}px`; } function onDragEnd() { if (!isDragging) return; isDragging = false; document.body.classList.remove('picker-dragging'); button.style.cursor = 'grab'; button.style.transition = 'background-color 0.3s ease'; document.removeEventListener('mousemove', onDragMove); document.removeEventListener('mouseup', onDragEnd); if (wasDragging) { const position = { x: button.style.left, y: button.style.top }; localStorage.setItem('pickerButtonPosition', JSON.stringify(position)); } } } function togglePickerMode() { if (wasDragging) { wasDragging = false; return; } pickerMode = !pickerMode; if (pickerMode) { activatePickerMode(); } else { deactivatePickerMode(); } } function activatePickerMode() { pickerButton.classList.add('active'); document.body.classList.add('picker-cursor'); showStatus('Picker aktiv. STRG+Klick für Mehrfachauswahl. ESC zum Beenden.'); document.addEventListener('mouseover', onMouseOver, true); document.addEventListener('mouseout', onMouseOut, true); document.addEventListener('click', onElementClick, true); document.addEventListener('keydown', onKeyDown, true); } function deactivatePickerMode() { pickerMode = false; pickerButton.classList.remove('active'); document.body.classList.remove('picker-cursor'); if (lastHoveredElement) { lastHoveredElement.classList.remove('picker-highlight'); } selectedElements.forEach(el => el.classList.remove('picker-selected')); selectedElements = []; lastHoveredElement = null; removeStatus(); document.removeEventListener('mouseover', onMouseOver, true); document.removeEventListener('mouseout', onMouseOut, true); document.removeEventListener('click', onElementClick, true); document.removeEventListener('keydown', onKeyDown, true); } function onMouseOver(e) { if (!pickerMode || e.target.closest('#element-picker-btn')) return; const adListItem = findAdListItem(e.target); if (!adListItem) return; if (lastHoveredElement && lastHoveredElement !== adListItem) { lastHoveredElement.classList.remove('picker-highlight'); } if (lastHoveredElement !== adListItem) { lastHoveredElement = adListItem; lastHoveredElement.classList.add('picker-highlight'); } e.stopPropagation(); } function onMouseOut(e) { if (pickerMode) e.stopPropagation(); } function onKeyDown(e) { if (pickerMode && e.key === 'Escape') { e.preventDefault(); deactivatePickerMode(); } } function createPipetteIcon() { const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("width", "24"); svg.setAttribute("height", "24"); svg.setAttribute("viewBox", "0 0 24 24"); svg.setAttribute("fill", "white"); const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); path.setAttribute("d", "M20.71 5.63l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-3.12 3.12-1.93-1.91-1.41 1.41 1.42 1.42L3 16.25V21h4.75l8.92-8.92 1.42 1.42 1.41-1.41-1.91-1.93 3.12-3.12c.4-.4.4-1.03 0-1.41zM6.92 19L5 17.08l8.06-8.06 1.92 1.92L6.92 19z"); svg.appendChild(path); return svg; } function createPickerButton() { const button = document.createElement('button'); button.id = 'element-picker-btn'; button.title = 'Komponenten-Analysator starten'; button.appendChild(createPipetteIcon()); button.addEventListener('click', togglePickerMode); document.body.appendChild(button); return button; } function findAdListItem(element) { return element.closest('.ad-listitem'); } function loadButtonPosition() { const savedPosition = localStorage.getItem('pickerButtonPosition'); if (savedPosition) { const pos = JSON.parse(savedPosition); pickerButton.style.top = pos.y; pickerButton.style.left = pos.x; pickerButton.style.right = 'auto'; pickerButton.style.transform = 'none'; } } function compactHTML(html) { return html.replace(/\s+/g, ' ').replace(/\s*<\s*/g, '<').replace(/\s*>\s*/g, '>').trim(); } function showNotification(message) { const n=document.createElement('div');n.className='picker-notification';n.textContent=message;document.body.appendChild(n);setTimeout(()=>{if(n.parentNode)n.parentNode.removeChild(n)},3000); } function showStatus(message) { removeStatus();const s=document.createElement('div');s.id='picker-status';s.className='picker-status';s.textContent=message;document.body.appendChild(s); } function removeStatus() { const e=document.getElementById('picker-status');if(e)e.parentNode.removeChild(e); } // Initialisierung function init() { pickerButton = createPickerButton(); makeButtonDraggable(pickerButton); loadButtonPosition(); console.log('Komponenten-Analysator (Power-Modus v14.0) wurde geladen.'); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址