// ==UserScript== // @name 京东评论合并工具 // @namespace https://github.com/ClericPy/somethings // @version 2.2 // @description try to take over the world! // @author Clericpy // @match https://item.jd.com/* // @grant GM_setClipboard // @downloadURL https://update.greasyfork.icu/scripts/402415/%E4%BA%AC%E4%B8%9C%E8%AF%84%E8%AE%BA%E5%90%88%E5%B9%B6%E5%B7%A5%E5%85%B7.user.js // @updateURL https://update.greasyfork.icu/scripts/402415/%E4%BA%AC%E4%B8%9C%E8%AF%84%E8%AE%BA%E5%90%88%E5%B9%B6%E5%B7%A5%E5%85%B7.meta.js // ==/UserScript== (function () { 'use strict'; var pages = {} window.auto_pager_running = false var css_to_hidden = {} window.backup_mc_innerHTML = '' var custom_css_to_hidden = '' var button_style = `font: inherit; margin: 3px; overflow: visible; text-transform: none; -webkit-appearance: button; letter-spacing: 0.01em; zoom: 1; line-height: normal; white-space: nowrap; vertical-align: middle; text-align: center; cursor: pointer; -webkit-user-drag: none; user-select: none; box-sizing: border-box; font-size: 100%; padding: .5em 1em; color: rgba(0,0,0,.8); border: none transparent; background-color: #e6e6e6; text-decoration: none; border-radius: 2px; font-family: inherit;` var new_style = document.createElement("style"); new_style.setAttribute('type', 'text/css') new_style.setAttribute('id', 'new_style') document.getElementsByTagName('body')[0].appendChild(new_style) function alert_doc() { var doc = ` 主要用途: 1. 京东的评论每次点翻页太麻烦了, 需要找关键词的时候又不能搜索, 只好全复制出来了 2. 偶尔需要语料 使用方法: 1. 加载网页以后, 在商品介绍 tab 位置会出现 [收集评论] 按钮, 点击 2. 可以手动点 [手动翻页], 一页页收集, 也可以配置好间隔秒数(默认2秒)点右边 checkbox 自动翻页 3. 采集结束(或自行停止)后, 点击 [展示全部] 按钮, 则评论会在原来位置对多页合并 4. 自行去噪过滤(可以通过选项, 也可以自己指定 css), 然后点击 [复制 TEXT] 即可复制到剪贴板 5. emoji [文本] 点击可以打开 Ubuntu 的 pastebin 来粘贴刚才复制了的文本 ` alert(doc) } function check_missing_pages() { var exist_page_nums = Object.keys(pages).sort() var max_num = exist_page_nums[exist_page_nums.length - 1] var missing_page_nums = [] var i = 1 while (i < max_num) { if (!(i in exist_page_nums)) { missing_page_nums.push(i) } i++; } if (missing_page_nums.length > 0) { var span = document.getElementById('commenter_state') span.innerText = '页码缺失: ' + missing_page_nums } else { var span = document.getElementById('commenter_state') span.innerText = '' } } function add_class_for_filter() { document.querySelectorAll('#comment [style="display: block;"][data-tab="item"] a.comment-plus-icon').forEach(item => { item.parentElement.parentElement.parentElement.classList.add('commenter_plus_vip_item') }); document.querySelectorAll('.comment-op').forEach(item => { if (item && !/\s*举报\s*\d+\s*0\s*/.test(item.innerText)) { item.parentElement.parentElement.parentElement.classList.add('commenter_with_reply') } if (item && !/\s*举报\s*0\s*\d+\s*/.test(item.innerText)) { item.parentElement.parentElement.parentElement.classList.add('commenter_with_like') } }); } function collect_dom_to_pages() { var curr_page = document.querySelector('#comment [style="display: block;"][data-tab="item"] [class="ui-page-curr"]') let commenter_crawl_button = document.getElementById('commenter_crawl_button') if (!curr_page) { return } if (!commenter_crawl_button) { return } var page = curr_page.innerText console.log(Object.keys(pages).length + ' pages: ' + Object.keys(pages)) commenter_crawl_button.innerText = '手动翻页 ' + page var node = document.querySelectorAll('#comment [style="display: block;"][data-tab="item"]>div.comment-item') if (node.length > 0) { let num = 0 let page_num = pages.length for (const items of Object.values(pages)) { num += items.length } document.getElementById('commenter_status_bar').innerText = ' 已采集 ' + Object.keys(pages).length + ' 页 ' + num pages[page] = node } if (Object.keys(pages).length == 1) { let show_button = document.getElementById('commenter_show_button') show_button.disabled = false show_button.style.color = 'black' } check_missing_pages() // 反爬导致崩溃, 放上备用页面 if (document.querySelector('#comment [style="display: block;"][data-tab="item"]')) { window.backup_mc_innerHTML = document.querySelector('#comment .mc').innerHTML } else { document.getElementById('commenter_status_bar').innerText = '没有评论了, 点击[展示全部]进行复制' } add_class_for_filter() } function filt_by_text() { let commenter_text_filter = document.getElementById('commenter_text_filter') let text_filters = [] if (commenter_text_filter) { text_filters = commenter_text_filter.value.split(' ') if (text_filters == ['']) { text_filters = [] } } for (const item of document.querySelectorAll('#comment [style="display: block;"][data-tab="item"]>.comment-item')) { var item_html = item.innerHTML if (!text_filters) { item.classList.remove('commenter_filt_by_text') } for (const text of text_filters) { if (text[0] == '-') { if (item_html.includes(text.slice(1, text.length))) { item.classList.add('commenter_filt_by_text') break } } else if (!item_html.includes(text)) { item.classList.add('commenter_filt_by_text') break } else { item.classList.remove('commenter_filt_by_text') } } } } function show_pages() { var container = document.querySelector('#comment [style="display: block;"][data-tab="item"]') if (!container) { // 备用 container var mc_node = document.querySelector('#comment .mc') if (window.backup_mc_innerHTML) { mc_node.innerHTML = window.backup_mc_innerHTML } } var backup_np_node = document.getElementsByClassName('com-table-footer')[0] container.innerHTML = '' Object.keys(pages).sort().forEach(function (key) { let items = pages[key] items.forEach(item => { container.appendChild(item) }); }); document.getElementById('commenter_copy_button').style.display = 'inline-block' document.getElementById('commenter_copy_text_button').style.display = 'inline-block' if (backup_np_node) { container.appendChild(backup_np_node) } add_class_for_filter() filt_by_text() } function copy_html() { let items = document.querySelectorAll('#comment [style="display: block;"][data-tab="item"]>.comment-item') let text = '' let filt_plus = document.getElementById('commenter_non_plus_vip').checked let filt_reply = document.getElementById('commenter_non_reply').checked let filt_like = document.getElementById('commenter_non_like').checked items.forEach(item => { if (filt_plus && !item.classList.contains('commenter_plus_vip_item')) { return } if (filt_reply && !item.classList.contains('commenter_with_reply')) { return } if (filt_like && !item.classList.contains('commenter_with_like')) { return } if (item.classList.contains('commenter_filt_by_text')) { return } text += item.outerHTML }); GM_setClipboard(text, 'text') } function copy_text() { let items = document.querySelectorAll('#comment [style="display: block;"][data-tab="item"]>.comment-item') let text = '' let filt_plus = document.getElementById('commenter_non_plus_vip').checked let filt_reply = document.getElementById('commenter_non_reply').checked let filt_like = document.getElementById('commenter_non_like').checked items.forEach(item => { if (filt_plus && !item.classList.contains('commenter_plus_vip_item')) { return } if (filt_reply && !item.classList.contains('commenter_with_reply')) { return } if (filt_like && !item.classList.contains('commenter_with_like')) { return } if (item.classList.contains('commenter_filt_by_text')) { return } text += item.innerText.replace('\n', ' ') + '\n' }); GM_setClipboard(text, 'text') } function auto_pager_with_interval() { collect_next_page() } function shutdown_auto_pager() { if (window.auto_pager_running) { window.clearInterval(window.current_autopager) window.auto_pager_running = false } } function auto_next_page() { shutdown_auto_pager() var commenter_auto_np_node = document.getElementById('commenter_auto_np') if (commenter_auto_np_node.checked) { window.auto_pager_running = true var interval = document.getElementById('commenter_auto_np_interval').value window.current_autopager = setInterval(() => { auto_pager_with_interval() }, interval * 1000); } else { shutdown_auto_pager() return } } function update_new_style() { let hidden_list = ['.commenter_filt_by_text'] Object.keys(css_to_hidden).forEach(key => { let value = css_to_hidden[key] if (value) { hidden_list.push(key) } }); if (custom_css_to_hidden) { hidden_list.push(custom_css_to_hidden) } document.getElementById('new_style').innerHTML = hidden_list.join(',') + '{display: none;}\n' } function commenter_clear(checked, css_value) { css_to_hidden[css_value] = checked update_new_style() } function commenter_collect_layouts() { var head = document.getElementById('comment') var mc_node = document.querySelector('#comment .mc') var hr = document.createElement("hr"); head.insertBefore(hr, mc_node) var show_button = document.createElement("button"); show_button.innerText = '展示全部' show_button.setAttribute('id', 'commenter_show_button') show_button.setAttribute('style', button_style) show_button.disabled = true show_button.style.color = 'grey' show_button.addEventListener('click', show_pages) head.insertBefore(show_button, mc_node) var copy_button = document.createElement("button"); copy_button.innerText = '复制 HTML' copy_button.setAttribute('id', 'commenter_copy_button') copy_button.setAttribute('style', button_style) copy_button.style.display = 'none' copy_button.addEventListener('click', copy_html) head.insertBefore(copy_button, mc_node) var copy_text_button = document.createElement("button"); copy_text_button.innerText = '复制 TEXT' copy_text_button.setAttribute('id', 'commenter_copy_text_button') copy_text_button.setAttribute('style', button_style) copy_text_button.style.display = 'none' copy_text_button.addEventListener('click', copy_text) head.insertBefore(copy_text_button, mc_node) var pastebin = document.createElement("a"); pastebin.innerText = '📋' pastebin.href = 'https://paste.ubuntu.com/' pastebin.target = '_blank' pastebin.style.margin = '2px' head.insertBefore(pastebin, mc_node) var commenter_state = document.createElement("span"); commenter_state.setAttribute('id', 'commenter_state') commenter_state.setAttribute('style', 'padding: 0.5em;') head.insertBefore(commenter_state, mc_node) var commenter_auto_np_interval = document.createElement("input"); commenter_auto_np_interval.setAttribute('id', 'commenter_auto_np_interval') commenter_auto_np_interval.setAttribute('value', '2') commenter_auto_np_interval.setAttribute('size', 1) commenter_auto_np_interval.setAttribute('style', 'text-align: center;') head.insertBefore(commenter_auto_np_interval, mc_node) var filter_node = document.createElement("div") filter_node.setAttribute('id', 'commenter_filter') filter_node.style.display = 'inline' filter_node.innerHTML = ` |