您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
毎日日本語を勉強しましょう
当前为
// ==UserScript== // @name nihongo_dict // @namespace http://tampermonkey.net/ // @version 0.2 // @description 毎日日本語を勉強しましょう // @author Ch4p1 // @match * // @icon https://www.google.com/s2/favicons?sz=64&domain=tv-asahi.co.jp // @grant GM_xmlhttpRequest // @grant GM.xmlHttpRequest // @grant GM_getResourceText // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @resource IMPORTED_CSS https://li1862-245.members.linode.com/audio/audio/tampermonkey.css // @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js // ==/UserScript== (function () { 'use strict'; const my_css = GM_getResourceText("IMPORTED_CSS"); GM_addStyle(my_css); var player; var t = 0; var speed = 1; var touchL = false; var loopT = []; //next page const splitArr = window.location.href.split(/[\/,.=?]+/); var lastNumber = splitArr.findLast(v => parseInt(v) > 0); const selInd = window.location.href.lastIndexOf(lastNumber); //init ui let menu = document.createElement("div"); menu.classList = "menu"; let menuBtns = document.createElement("div"); menuBtns.classList = "btns"; menu.appendChild(menuBtns); createBtn('ㄆ', () => { oepnHelp() }); createBtn('X', (e) => { e.target.parentElement.remove() }); document.body.appendChild(menu); //get serifu var gotSerifu = false; //get serifu for kktv var serifuArr = {}; if (window.location.hostname == "kktv.me" || window.location.hostname == "www.kktv.me") { XMLHttpRequest.prototype.realSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function (value) { this.addEventListener("progress", function (e) { //zh-Hant.vtt ja.vtt var filename = e.target.responseURL.split('/').pop() if (filename == "zh-Hant.vtt" || filename == "ja.vtt") { var matchArr = e.target.response.match(/\d+:\d+:\d+.\d+ --> \d+:\d+:\d+.\d+\n.+/gm, ""); matchArr.map(v => { var tarr = v.split("-->"); var serifu = tarr[1].split("\n"); if (filename == "ja.vtt") { if (!serifuArr[tarr[0].trim()]) serifuArr[tarr[0].trim()] = {} serifuArr[tarr[0].trim()].endT = serifu[0].trim(); serifuArr[tarr[0].trim()].jp = serifu[1].trim(); } else { if (!serifuArr[tarr[0].trim()]) serifuArr[tarr[0].trim()] = {} serifuArr[tarr[0].trim()].endT = serifu[0].trim(); serifuArr[tarr[0].trim()].tw = serifu[1].trim(); } }); if (gotSerifu == false) { tempAlert("字幕loading...", 2000); createBtn('字幕', () => { copyKktv() }); gotSerifu = true; } } }, false); this.realSend(value); }; } /* function time2sec(s) { const sec = s.split(":").reduce((a, c, ind) => { var s = 1; if (ind == 0) s = 3600; else if (ind == 1) s = 60; return a + (parseFloat(c) * s) }, 0); return sec; } var responseTextArr = {}; var temp_serifuArr = []; if (window.location.hostname == "www.netflix.com") { XMLHttpRequest.prototype.realSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function (value) { this.addEventListener("progress", function (e) { //1 下載字幕 區分出中日 try { if ( e.target.responseText.substring(0, 6) == "WEBVTT") { var lang = e.target.responseText.includes("c.japanese") ? "jp" : "tw"; console.log(">>>>",lang) responseTextArr[lang] = e.target.responseText; if (responseTextArr.jp && responseTextArr.tw) { //process jp var matchArr = responseTextArr.jp.match(/\d+:.+\n.+/gm, ""); matchArr.map(v => { var teimArr = v.match(/\d+:\d+:\d+.\d+/gm, ""); var serifu = v.match(/(?<=bg_transparent>)(.+)(?=<\/c.bg)/gm); if (serifu && serifu.length > 0) temp_serifuArr.push({ start: time2sec(teimArr[0]), end: time2sec(teimArr[1]), jp: serifu[0].trim(), tw: "" }) else console.log("~~~~~~~~~~", serifu, v); }); console.log("~~~~") //process tw matchArr = responseTextArr.tw.match(/\d+:.+\n.+/gm, ""); matchArr.map(v => { var teimArr = v.match(/\d+:\d+:\d+.\d+/gm, ""); var serifu = v.match(/(?<=bg_transparent>)(.+)(?=<\/c.bg)/gm); if (serifu && serifu.length > 0) { var startSec = time2sec(teimArr[0]); var findObj = temp_serifuArr.find(vv => (startSec >= vv.start && startSec <= vv.end)); if (findObj) { findObj.tw += serifu[0].trim(); } } else { console.log("~~~~~~~~~~", serifu, v); } }); console.log("---------", temp_serifuArr); tempAlert("字幕loading...", 2000); createBtn('字幕', () => { copyKktv() }); gotSerifu = true; } } } catch (err) { console.log(err); } }, false); this.realSend(value); }; } */ if (window.location.hostname == "ncode.syosetu.com") { var matchArr = document.querySelector(".novel_view").innerText.match(/.+\n/gm, ""); if (matchArr.length > 0) { matchArr.map((v, k) => { serifuArr["f_" + k] = { jp: v.trim() }; }); tempAlert("字幕loading...", 2000); createBtn('字幕', () => { copyKktv() }); gotSerifu = true; } } function getPlayer() { return document.querySelector("video") ? document.querySelector("video") : document.querySelector("audio"); } setInterval(() => { if (!player) { player = getPlayer(); if (player && (window.location.hostname == "kktv.me" || window.location.hostname == "www.kktv.me")) { const observer = new MutationObserver(function (mutations) { const targetDiv = document.querySelector(".main-subtitle"); if (targetDiv) { targetDiv.style.userSelect = "text"; } }); const div = document.querySelector(".kktv-player"); observer.observe(div, { childList: true, attributes: true, characterData: true, }); } } if (loopT.length == 2 && player.currentTime > loopT[1]) { player.currentTime = loopT[0]; player.play(); } }, 200); function createBtn(title, fn) { let btn = document.createElement("div"); btn.classList = "menuBtn"; btn.innerHTML = title; btn.onclick = fn menuBtns.appendChild(btn); } var hotkeyList = [ { cmd: "mediaPlayStart", hotkey: "O", tip: "標記影片返回點" }, { cmd: "mediaPlayEnd", hotkey: "P", tip: "按住回到O點並播放,放開停止" }, { cmd: "mediaPause", hotkey: "SPACE", tip: "暫/播放" }, { cmd: "mediaSetLoop", hotkey: "Q", tip: "設定循環播放範圍,連按2次清除" }, { cmd: "mediaRepaet", hotkey: "‰", tip: "設定repeat" }, { cmd: "nihongoHira", hotkey: "⁄", tip: "日文單字(若找的)顯示拼音" }, { cmd: "nihongoDict", hotkey: "€", tip: "中日字典" }, { cmd: "nihongoSakura", hotkey: "‹", tip: "日日字典sakura" }, { cmd: "nihongoGoo", hotkey: "Í", tip: "日日字典goo" }, { cmd: "nihongoSpeak", hotkey: "Å", tip: "日文發音" }, { cmd: "enTranslate", hotkey: "Œ", tip: "英文字典google" }, { cmd: "google", hotkey: "¸", tip: "google" }, { cmd: "nextPage", hotkey: "˘", tip: "下一頁" }, { cmd: "prevPage", hotkey: "¯", tip: "上一頁" }, { cmd: "comm", hotkey: "-", tip: "↑↓速度←→前後" }, ]; hotkeyList.map(v => { const _key = GM_getValue(v.cmd); if (_key && _key != "") v.hotkey = _key; }); function createInfo(obj) { let div = document.createElement("div"); let hotkey = document.createElement("input"); let tip = document.createElement("span"); div.classList = "memo"; if (obj.cmd != "comm") { hotkey.type = "text"; hotkey.maxLength = "1"; hotkey.value = obj.hotkey; hotkey.style = "width: 18px;"; hotkey.onkeyup = (e) => { console.log("e.target.value", e.target.value, obj); obj.hotkey = e.target.value; GM_setValue(obj.cmd, obj.hotkey); }; div.appendChild(hotkey); } tip.innerHTML = obj.tip; div.appendChild(tip); return div; } function tempAlert(msg, duration) { document.querySelectorAll(".tempAlert").forEach(el => { el.style.bottom = (parseInt(el.style.bottom) + 24) + "px"; }); var el = document.createElement("div"); el.className = "tempAlert"; el.setAttribute("style", "position:absolute;bottom:5px;left:1%;padding: 0 1rem;background-color:black;color: white;font-size: 20px;"); el.innerHTML = msg; setTimeout(function () { el.parentNode.removeChild(el); }, duration); document.body.appendChild(el); } function copyKktv() { try { document.querySelector(".modalxx").remove(); } catch (e) { /* var data = []; document.querySelectorAll(".kktv-player>div>:nth-child(2)>:nth-child(2)>button").forEach(button => { const divs = button.querySelectorAll("div"); data.push({ id: button.id, jp: divs[0].innerText, tw: divs[1].innerText }); }); */ let headers = { "Content-Type": "application/json", "Accept": "application/json", } fetch('https://li1862-245.members.linode.com:3006/serifu', { method: "POST", headers: headers, body: JSON.stringify({ str: serifuArr }) }) .then((response) => { return response.json(); }).then((ret) => { let canvas = document.createElement("div"); canvas.classList = "modalxx"; let img = document.createElement("img"); img.src = 'https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl=https://li1862-245.members.linode.com/kktvreader/build/?key=' + ret.key + '&choe=UTF-8'; img.onclick = (e) => { window.open( 'https://li1862-245.members.linode.com/kktvreader/build/?key=' + ret.key, "_blank"); } img.target = "_blank"; canvas.appendChild(img); menu.appendChild(canvas); }).catch((err) => { console.log('錯誤:', err); }); } } function oepnHelp() { try { document.querySelector(".modalxx").remove(); } catch (e) { let canvas = document.createElement("div"); canvas.classList = "modalxx"; hotkeyList.map(v => { canvas.appendChild(createInfo(v)); }); menu.appendChild(canvas); } } function addLoop() { if (loopT.length === 1) { loopT.push(player.currentTime); tempAlert("add loop end", 2000); } else if (loopT.length === 0) { loopT.push(player.currentTime); tempAlert("add loop start", 2000); } } function isRepeatKey(event) { return (event.key == lastKey.key && (performance.now() - lastKey.t) < 1000) } function clearAllLoop() { loopT = []; } function padLeft(str, len) { str = '' + str; if (str.length >= len) { return str; } else { return padLeft("0" + str, len); } } var lastKey = { key: "", t: 0 }; document.body.addEventListener("keyup", function (event) { const hotkeyObj = hotkeyList.find(v => { return v.hotkey.toLowerCase() == event.key.toLowerCase() }); if (player) { if (hotkeyObj.cmd === "mediaPlayEnd") {//L roolback console.log("keyup mediaPlayEnd") touchL = false; player.pause(); } } }); document.body.addEventListener("keydown", function (event) { var selectTxt = ""; const hotkeyObj = hotkeyList.find(v => { return v.hotkey.toLowerCase() == event.key.toLowerCase() }); if (player) { if (hotkeyObj.cmd === "mediaPlayEnd" && touchL == false) {//L roolback console.log("mediaPlayStart") touchL = true; player.currentTime = t; player.play(); } else if ((hotkeyObj.cmd === "mediaPlayStart")) {//k set point if (isRepeatKey(event)) { t -= 0.5; player.currentTime = t; player.play(); } else { t = player.currentTime; } } else if (hotkeyObj.cmd === "mediaSetLoop") { if (isRepeatKey(event)) { clearAllLoop(); tempAlert("clear loop", 2000); } else { addLoop(); } } else if (hotkeyObj.cmd === "mediaRepaet") {//L roolback player.loop = !player.loop; tempAlert("repeat " + player.loop, 2000); } else if (event.key === "ArrowRight") {//back player.currentTime += 1; } else if (event.key === "ArrowLeft") {//font player.currentTime -= 1; } else if (event.key === "ArrowUp") {//up speed up speed += 0.1; if (speed >= 1) { speed = 1; } player.playbackRate = speed; } else if (event.key === "ArrowDown") {//down speed down speed -= 0.1; if (speed <= 0.1) { speed = 0.1; } player.playbackRate = speed; } } if (hotkeyObj.cmd === "nihongoHira") { //日文拼音 if (window.getSelection) { selectTxt = window.getSelection(); } else if (window.document.getSelection) { selectTxt = window.document.getSelection(); } else if (window.document.selection) { selectTxt = window.document.selection.createRange().text; } GM.xmlHttpRequest({ method: "GET", url: "https://dict.asia/jc/" + selectTxt.toString(), headers: { "User-Agent": "Mozilla/5.0", // If not specified, navigator.userAgent will be used. "Accept": "text/xml" // If not specified, browser defaults will be used. }, onload: function (ret) { console.log(ret); let parser = new DOMParser(); const document = parser.parseFromString(ret.responseText, "text/html"); var kijis = document.querySelectorAll("#jp_comment"); if (kijis != null && kijis.length > 0) { const kiji = kijis[0]; var kana = kiji.querySelector(".trs_jp"); var kanaStr = ""; if (kana != null) { kanaStr = kana.textContent.replaceAll(/【|】/g, ''); selectTxt.anchorNode.parentElement.innerHTML = selectTxt.anchorNode.parentElement.innerHTML.replaceAll(selectTxt.toString(), "<ruby>" + selectTxt.toString() + "<rt>" + kanaStr + "</rt></ruby>") } } else { tempAlert("can't find", 2000); } } }); } else if (hotkeyObj.cmd === "nihongoDict") { //日文字典 2 if (window.getSelection) { selectTxt = window.getSelection(); } else if (window.document.getSelection) { selectTxt = window.document.getSelection(); } else if (window.document.selection) { selectTxt = window.document.selection.createRange().text; } window.open( "https://dict.asia/jc/" + selectTxt.toString(), "_blank"); } else if (hotkeyObj.cmd === "nihongoSakura") { //日文字典 3 if (window.getSelection) { selectTxt = window.getSelection(); } else if (window.document.getSelection) { selectTxt = window.document.getSelection(); } else if (window.document.selection) { selectTxt = window.document.selection.createRange().text; } window.open( "https://sakura-paris.org/dict/%E5%BA%83%E8%BE%9E%E8%8B%91/prefix/" + selectTxt.toString(), "_blank"); } else if (hotkeyObj.cmd === "nihongoGoo") { //日文字典goo找前面一致 s if (window.getSelection) { selectTxt = window.getSelection(); } else if (window.document.getSelection) { selectTxt = window.document.getSelection(); } else if (window.document.selection) { selectTxt = window.document.selection.createRange().text; } window.open( "https://dictionary.goo.ne.jp/srch/jn/" + selectTxt.toString() + "/m0u/", "_blank"); } else if (hotkeyObj.cmd === "nihongoSpeak") { //發音 a if (window.getSelection) { selectTxt = window.getSelection(); } else if (window.document.getSelection) { selectTxt = window.document.getSelection(); } else if (window.document.selection) { selectTxt = window.document.selection.createRange().text; } window.open( "https://ja.forvo.com/word/" + selectTxt.toString() + "/#ja", "_blank"); } else if (hotkeyObj.cmd === "enTranslate") { //google translate q if (window.getSelection) { selectTxt = window.getSelection(); } else if (window.document.getSelection) { selectTxt = window.document.getSelection(); } else if (window.document.selection) { selectTxt = window.document.selection.createRange().text; } window.open( "https://translate.google.com.tw/?hl=zh-TW&tab=rT&sl=en&tl=zh-TW&text=" + selectTxt.toString() + "&op=translate", "_blank"); } else if (hotkeyObj.cmd === "google") { //google Z if (window.getSelection) { selectTxt = window.getSelection(); } else if (window.document.getSelection) { selectTxt = window.document.getSelection(); } else if (window.document.selection) { selectTxt = window.document.selection.createRange().text; } window.open( "https://www.google.com/search?q=" + selectTxt.toString(), "_blank"); } else if (hotkeyObj.cmd === "nextPage") { //next page > lastNumber = padLeft(Number(lastNumber) + 1, lastNumber.length); window.location.href = window.location.href.substring(0, selInd) + lastNumber + window.location.href.substring(selInd + lastNumber.length); } else if (hotkeyObj.cmd === "prevPage") { //prev page > lastNumber = padLeft(Number(lastNumber) - 1, lastNumber.length); window.location.href = window.location.href.substring(0, selInd) + lastNumber + window.location.href.substring(selInd + lastNumber.length); } lastKey = { key: event.key, t: performance.now() }; }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址