您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A new userscript
// ==UserScript== // @name mydealz Comment Scraper & Markdown Exporter // @description A new userscript // @version 1.0.1 // @match https://*.mydealz.de/* // @icon https://www.mydealz.de/favicon.ico // @namespace https://greasyfork.org/users/1462137 // ==/UserScript== (function() { 'use strict'; let isProcessing = false; let allComments = []; let currentPage = 1; let totalPages = 1; function createScrapeButton() { const button = document.createElement('button'); button.style.position = 'fixed'; button.style.top = '20px'; button.style.right = '20px'; button.style.zIndex = '10000'; button.style.backgroundColor = '#007bff'; button.style.color = 'white'; button.style.border = 'none'; button.style.padding = '10px 15px'; button.style.borderRadius = '5px'; button.style.cursor = 'pointer'; button.style.fontSize = '14px'; button.style.fontWeight = 'bold'; button.textContent = 'Scrape Comments'; button.id = 'scrape-comments-btn'; document.body.appendChild(button); } function showProgress(message) { const button = document.getElementById('scrape-comments-btn'); if (button) { button.textContent = message; } else { console.log(message); } } async function expandAllReplies() { const replyButtons = document.querySelectorAll('button[data-t="moreReplies"]'); for (const button of replyButtons) { button.click(); console.log('Expanded replies for button: ' + button.textContent.trim()); await new Promise(resolve => setTimeout(resolve, 1000)); } } function extractCommentData(commentElement) { const username = commentElement.querySelector('.user button')?.textContent?.trim() || ''; const timestamp = commentElement.querySelector('time')?.textContent?.trim() || ''; const text = commentElement.querySelector('.comment-body .userHtml-content')?.textContent?.trim() || ''; const likes = commentElement.querySelector('.comment-like')?.textContent?.trim() || '0'; const helpful = commentElement.querySelector('.comment-helpful')?.textContent?.trim() || '0'; const funny = commentElement.querySelector('.comment-funny')?.textContent?.trim() || '0'; return { username, timestamp, text, likes, helpful, funny }; } function extractAllCommentsFromPage() { const commentItems = document.querySelectorAll('.commentList-item'); const comments = []; commentItems.forEach(item => { const mainCommentData = extractCommentData(item); const replyElements = item.querySelectorAll('.comment-replies-item'); const replies = []; replyElements.forEach(replyElement => { const replyData = extractCommentData(replyElement); replies.push(replyData); }); const commentObject = { ...mainCommentData, replies: replies }; comments.push(commentObject); }); allComments.push(...comments); console.log('Extracted ' + comments.length + ' comments from current page'); } async function navigateToNextPage() { const nextButton = document.querySelector('button[aria-label="Nächste Seite"]:not(.button--disabled)'); if (nextButton) { nextButton.click(); await new Promise(resolve => setTimeout(resolve, 3000)); return true; } return false; } function getTotalPages() { const lastPageButton = document.querySelector('button[aria-label="Letzte Seite"]'); if (lastPageButton && lastPageButton.textContent) { const pageNumber = parseInt(lastPageButton.textContent.trim()); return isNaN(pageNumber) ? 1 : pageNumber; } return 1; } function generateMarkdown() { let markdown = '# mydealz Comments\n\n'; const dealTitle = document.querySelector('h1').textContent; markdown += `**Deal:** ${dealTitle}\n\n`; markdown += `**URL:** ${window.location.href}\n\n`; markdown += `**Total Comments:** ${allComments.length}\n\n`; allComments.forEach((comment, index) => { markdown += `## Comment by ${comment.username} (${comment.timestamp})\n\n`; markdown += `${comment.text}\n\n`; markdown += `**Reactions:** 👍 ${comment.likes} | 🔥 ${comment.helpful} | 😄 ${comment.funny}\n\n`; if (comment.replies && comment.replies.length > 0) { comment.replies.forEach(reply => { markdown += `### Reply by ${reply.username} (${reply.timestamp})\n\n`; markdown += `${reply.text}\n\n`; markdown += `**Reactions:** 👍 ${reply.likes} | 🔥 ${reply.helpful} | 😄 ${reply.funny}\n\n`; }); } if (index < allComments.length - 1) { markdown += '---\n\n'; } }); return markdown; } function downloadMarkdown(content) { const blob = new Blob([content], {type: 'text/markdown'}); const url = URL.createObjectURL(blob); const anchor = document.createElement('a'); anchor.href = url; anchor.download = 'mydealz-comments-' + Date.now() + '.md'; document.body.appendChild(anchor); anchor.click(); document.body.removeChild(anchor); URL.revokeObjectURL(url); } async function scrapeAllComments() { if (isProcessing) { alert('Scraping already in progress'); return; } isProcessing = true; showProgress('Starting scrape...'); totalPages = getTotalPages(); currentPage = 1; allComments = []; while (currentPage <= totalPages) { showProgress('Processing page ' + currentPage + ' of ' + totalPages); await expandAllReplies(); await new Promise(resolve => setTimeout(resolve, 2000)); extractAllCommentsFromPage(); if (currentPage < totalPages) { await navigateToNextPage(); await new Promise(resolve => setTimeout(resolve, 3000)); } currentPage++; } showProgress('Generating markdown...'); const content = generateMarkdown(); downloadMarkdown(content); showProgress('Download complete!'); await new Promise(resolve => setTimeout(resolve, 2000)); showProgress('Scrape Comments'); isProcessing = false; } function init() { if (!window.location.href.includes('/deals/')) { console.log('Not on a deal page'); return; } createScrapeButton(); const button = document.getElementById('scrape-comments-btn'); if (button) { button.addEventListener('click', scrapeAllComments); } console.log('mydealz Comment Scraper initialized'); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();