您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
抓取Appstorrent游戏页面信息并下载图片
// ==UserScript== // @name Appstorrent游戏信息抓取器 // @namespace http://tampermonkey.net/ // @version 1.8 // @description 抓取Appstorrent游戏页面信息并下载图片 // @author You // @match https://appstorrent.ru/* // @grant none // ==/UserScript== (function() { 'use strict'; // 添加抓取按钮 function addScrapeButton() { const button = document.createElement('button'); button.innerHTML = '🎮 抓取游戏信息'; button.style.cssText = ` position: fixed; top: 20px; right: 20px; z-index: 9999; padding: 10px 15px; background: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 14px; `; button.onclick = scrapeGameInfo; document.body.appendChild(button); } // 将webp转换为jpg function convertWebpToJpg(blob) { return new Promise((resolve) => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const img = new Image(); img.onload = function() { canvas.width = img.width; canvas.height = img.height; // 设置白色背景(jpg不支持透明) ctx.fillStyle = '#FFFFFF'; ctx.fillRect(0, 0, canvas.width, canvas.height); // 绘制图片 ctx.drawImage(img, 0, 0); // 转换为jpg blob canvas.toBlob((jpgBlob) => { resolve(jpgBlob); }, 'image/jpeg', 0.9); // 90%质量 }; img.onerror = function() { console.log('图片转换失败,使用原格式'); resolve(blob); }; img.src = URL.createObjectURL(blob); }); } // 下载单张图片 async function downloadImage(url, filename) { try { const response = await fetch(url); let blob = await response.blob(); // 如果是webp格式,转换为jpg if (url.toLowerCase().includes('.webp')) { console.log(`转换webp为jpg: ${filename}`); blob = await convertWebpToJpg(blob); // 修改文件名扩展名 filename = filename.replace(/\.webp$/i, '.jpg'); } const downloadUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = downloadUrl; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(downloadUrl); console.log(`✓ 下载完成: ${filename}`); return true; } catch (error) { console.log(`✗ 下载失败: ${filename} - ${error}`); return false; } } // 批量下载图片 async function downloadAllImages(imageUrls, gameName) { const safeName = gameName.replace(/[<>:"/\\|?*]/g, '_'); let successCount = 0; for (let i = 0; i < imageUrls.length; i++) { const url = imageUrls[i]; let extension = url.split('.').pop().toLowerCase(); // 如果是webp,转换为jpg if (extension === 'webp') { extension = 'jpg'; } const filename = `${safeName}_screenshot_${i + 1}.${extension}`; const success = await downloadImage(url, filename); if (success) successCount++; // 添加延迟避免请求过快 await new Promise(resolve => setTimeout(resolve, 800)); } return successCount; } // 抓取游戏信息 async function scrapeGameInfo() { console.log('开始抓取游戏信息...'); const gameInfo = { name: '', description: '', dlc_content: '', publish_date: '', image_urls: [], source_url: window.location.href }; // 提取游戏名称 const titleElem = document.querySelector('h1'); if (titleElem) { gameInfo.name = titleElem.textContent.trim(); console.log(`✓ 找到标题: ${gameInfo.name}`); } // 提取发布时间 const allText = document.body.textContent; const dateMatch = allText.match(/Опубликовано[^:]*:\s*([^\n]+)/); if (dateMatch) { let rawDate = dateMatch[1].trim(); // 转换俄语日期格式 const monthMap = { 'января': '01', 'февраля': '02', 'марта': '03', 'апреля': '04', 'мая': '05', 'июня': '06', 'июля': '07', 'августа': '08', 'сентября': '09', 'октября': '10', 'ноября': '11', 'декабря': '12' }; // 匹配格式:日 月 年 const ruDateMatch = rawDate.match(/(\d{1,2})\s+(\w+)\s+(\d{4})/); if (ruDateMatch) { const day = ruDateMatch[1].padStart(2, '0'); const month = monthMap[ruDateMatch[2]] || '01'; const year = ruDateMatch[3]; gameInfo.publish_date = `${year}年${month}月${day}日`; } else { gameInfo.publish_date = rawDate; } console.log(`✓ 找到发布时间: ${gameInfo.publish_date}`); } // 提取完整内容 const contentArea = document.querySelector('.body-content'); if (contentArea) { const textContent = contentArea.textContent || ''; gameInfo.description = textContent.trim(); console.log(`✓ 找到描述: ${gameInfo.description.length} 字符`); } // 提取图片 - 专门从截图区域抓取 const screenshotsArea = document.querySelector('.screenshots'); if (screenshotsArea) { console.log('找到截图区域,开始提取图片...'); // 从swiper-slide中提取图片链接 const slides = screenshotsArea.querySelectorAll('.swiper-slide a.highslide'); console.log(`截图区域找到 ${slides.length} 个图片链接`); slides.forEach((link, index) => { const href = link.href; if (href && href.match(/\.(jpg|jpeg|png|webp)$/i)) { gameInfo.image_urls.push(href); console.log(` ✓ 添加截图 ${index + 1}: ${href}`); } }); // 如果没有找到href链接,尝试从img标签获取src if (gameInfo.image_urls.length === 0) { const images = screenshotsArea.querySelectorAll('.swiper-slide img'); console.log(`尝试从img标签获取,找到 ${images.length} 个图片`); images.forEach((img, index) => { let src = img.src; // 如果是相对路径,转换为绝对路径 if (src.startsWith('/')) { src = window.location.origin + src; } if (src && src.match(/\.(jpg|jpeg|png|webp)$/i)) { gameInfo.image_urls.push(src); console.log(` ✓ 添加图片 ${index + 1}: ${src}`); } }); } } else { console.log('未找到截图区域,使用备用方案...'); // 备用方案:从整个页面抓取 const images = document.querySelectorAll('img'); images.forEach((img) => { const src = img.src; if (src && src.includes('/uploads/posts/') && !src.includes('/thumbs/') && src.match(/\.(jpg|jpeg|png|webp)$/i)) { if (!gameInfo.image_urls.includes(src)) { gameInfo.image_urls.push(src); } } }); } console.log(`最终提取到 ${gameInfo.image_urls.length} 张图片`); // 显示结果 displayResults(gameInfo); } // 显示结果 function displayResults(gameInfo) { console.log('=== displayResults 开始 ==='); // 构建结果文本 const name = gameInfo.name || '未知游戏'; const date = gameInfo.publish_date || '未知日期'; const desc = gameInfo.description || '暂无描述'; const imageCount = gameInfo.image_urls.length; let resultText = `游戏名称: ${name}\n\n`; resultText += `发布时间: ${date}\n\n`; resultText += `游戏介绍:\n${desc}\n\n`; resultText += `图片链接 (${imageCount}张):\n`; resultText += gameInfo.image_urls.join('\n') + '\n\n'; resultText += `来源: ${gameInfo.source_url}`; // 创建弹窗 const modal = document.createElement('div'); modal.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 10000; display: flex; justify-content: center; align-items: center; `; const content = document.createElement('div'); content.style.cssText = ` background: white; padding: 20px; border-radius: 10px; width: 80%; height: 80%; display: flex; flex-direction: column; overflow: hidden; `; const title = document.createElement('h3'); title.textContent = '游戏信息抓取结果'; title.style.cssText = ` margin: 0 0 15px 0; color: black; text-align: center; `; const textarea = document.createElement('textarea'); textarea.style.cssText = ` flex: 1; width: 100%; font-family: monospace; font-size: 12px; border: 1px solid #ccc; padding: 10px; background: white; color: black; resize: none; overflow-y: auto; box-sizing: border-box; `; textarea.value = resultText; const buttonContainer = document.createElement('div'); buttonContainer.style.cssText = ` margin-top: 15px; display: flex; justify-content: space-between; align-items: center; gap: 10px; `; const downloadTextBtn = document.createElement('button'); downloadTextBtn.textContent = '下载文本文件'; downloadTextBtn.style.cssText = ` flex: 1; padding: 10px 20px; background: #2196F3; color: white; border: none; border-radius: 5px; cursor: pointer; `; const downloadImagesBtn = document.createElement('button'); downloadImagesBtn.textContent = `下载图片 (${imageCount}张)`; downloadImagesBtn.style.cssText = ` flex: 1; padding: 10px 20px; background: #FF9800; color: white; border: none; border-radius: 5px; cursor: pointer; `; const closeBtn = document.createElement('button'); closeBtn.textContent = '关闭'; closeBtn.style.cssText = ` flex: 1; padding: 10px 20px; background: #f44336; color: white; border: none; border-radius: 5px; cursor: pointer; `; // 事件处理 downloadTextBtn.onclick = () => { const blob = new Blob([resultText], { type: 'text/plain;charset=utf-8' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `${name.replace(/[<>:"/\\|?*]/g, '_')}.txt`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }; downloadImagesBtn.onclick = async () => { if (gameInfo.image_urls.length === 0) { alert('没有找到图片可下载'); return; } downloadImagesBtn.textContent = '下载中...'; downloadImagesBtn.disabled = true; const successCount = await downloadAllImages(gameInfo.image_urls, name); downloadImagesBtn.textContent = `下载完成 (${successCount}/${imageCount})`; downloadImagesBtn.style.background = '#4CAF50'; setTimeout(() => { downloadImagesBtn.textContent = `下载图片 (${imageCount}张)`; downloadImagesBtn.style.background = '#FF9800'; downloadImagesBtn.disabled = false; }, 3000); }; closeBtn.onclick = () => { document.body.removeChild(modal); }; // 组装弹窗 buttonContainer.appendChild(downloadTextBtn); buttonContainer.appendChild(downloadImagesBtn); buttonContainer.appendChild(closeBtn); content.appendChild(title); content.appendChild(textarea); content.appendChild(buttonContainer); modal.appendChild(content); document.body.appendChild(modal); console.log('弹窗已添加到页面'); } // 页面加载完成后添加按钮 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', addScrapeButton); } else { addScrapeButton(); } })();