您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
批量选择 fancaps 的图片并导出图片链接
// ==UserScript== // @name fancaps 图片批量导出 // @namespace http://tampermonkey.net/ // @version 0.2 // @description 批量选择 fancaps 的图片并导出图片链接 // @author ctrn43062 // @match https://fancaps.net/anime/episodeimages.php* // @icon https://www.google.com/s2/favicons?sz=64&domain=fancaps.net // @grant GM_addStyle // @license MIT // ==/UserScript== const constants = { checkboxClassName: 'fan-checkbox' } const states = { selectedCount: 0, } GM_addStyle(` .image-selected { position: relative; } .image-selected .${constants.checkboxClassName} { position: absolute; top:10px; left: 10px; width: 16px; height: 16px; line-height: 16px; text-align: center; } .side-operation { position: fixed; right: 2rem; top: 45%; font-size: 2rem; cursor: pointer; } `) function download(blob, name) { const url = URL.createObjectURL(blob) const a = document.createElement('a') a.download = name a.href = url a.click() URL.revokeObjectURL(url) // a.remove() //document.body.appendChild(a) } function addSelectionListener(img) { img.addEventListener('click', e => { e.preventDefault() const p = img.parentElement p.classList.toggle('image-selected') if(p.classList.contains('image-selected')) { states.selectedCount += 1 const checkbox = document.createElement('div') checkbox.className = constants.checkboxClassName checkbox.innerText = '☑️' checkbox.setAttribute('data-id', img.href.split('/').slice(-1)[0]) p.appendChild(checkbox) } else { states.selectedCount -= 1 p.removeChild(p.querySelector(`.${constants.checkboxClassName}`)) } document.querySelector('.selected-count').innerText = ` (${states.selectedCount})` }) } function addDownloadButton() { const sideEl = document.createElement('div') sideEl.className = 'side-operation' sideEl.innerHTML = ` <span class="download-btn">🔽<span class="selected-count"></span></span> ` sideEl.querySelector('.download-btn').addEventListener('click', e => { const selectedImageEls = document.querySelectorAll(`.${constants.checkboxClassName}`) if(!selectedImageEls) { return } // el.href like: https://fancaps.net/anime/picture.php?/3335084 // urlslike: https://cdni.fancaps.net/file/fancaps-animeimages/3335084.jpg const oriURL = 'https://cdni.fancaps.net/file/fancaps-animeimages' const urls = Array.from(selectedImageEls).map(el => `${oriURL}/${el.getAttribute('data-id')}.jpg`) let filename = document.title.replace(/[ |]/, '_') try { // href like: https://fancaps.net/anime/episodeimages.php?4963-Yuruyuri___Happy_Go_Lily/Episode_1&page=2 filename = location.href.split('?')[1].split('/') // [4963-Yuruyuri___Happy_Go_Lily, Episode_1&page=2] filename = filename[0] + '_' + filename[1].split('&')[0] // 963-Yuruyuri___Happy_Go_Lily_Episode_1 } catch (e) {} download(new Blob([urls.join('\n')], {type: 'text/plain'}), `${filename}.txt`) }) document.body.appendChild(sideEl) } (function() { 'use strict'; const contentBodyEl = document.querySelector('#contentbody') const obs = new MutationObserver((mutationList) => { const nodes = [] for(const mutation of mutationList) { let { addedNodes } = mutation if(!addedNodes || addedNodes.length != 1 || !addedNodes[0].classList.contains('single_post_area')) { continue } const post_area = addedNodes[0] const rows = post_area.querySelectorAll('.row:has( img)') nodes.push(...(rows || [])) console.log(rows) } // nodes'length should be always eq 2 nodes.forEach(node => { const imageEls = node.querySelectorAll('a') for(const img of imageEls) { addSelectionListener(img) } }) }) obs.observe(contentBodyEl, { childList: true, subtree: true }) contentBodyEl.querySelectorAll('.row a:has(>.imageFade)').forEach(img => { addSelectionListener(img) }) addDownloadButton() })();