もくじ
リンク
ニコニコ動画のコメントを正規表現でNGするユーザースクリプト - AdC用にとりあえず用意したブログ
上記のスクリプトを使用して、正規表現によってより詳細に不快なコメントをブロックする。
ユーザースクリプトは、Tampermonkeyのような拡張機能を使用することで追加できる。
コード
上記のコードを、自分用に使いやすいように編集した。
- ショートカットをCtrl + Bに変更。
- フォントサイズを0.8倍に変更。
- 文字色を無色に強制。
// ==UserScript==
// @name nicovideo_regexp_comment_ng
// @version 0.1
// @description ニコニコ動画のコメントを正規表現でNGするスクリプト。EscキーでNGパターンを変更して保存できます。
// @match https://www.nicovideo.jp/watch/*
// @match https://www.nicovideo.jp/watch_tmp/*
// ==/UserScript==
(function() {
'use strict';
const storageKey = 'regexp_comment_ng';
const patDefault = 'うぽつ|荒らし|NG|んん~|にょ、';
let image_to_is_safe;
let patCurrent = null;
let regexp;
const updatePat = (pat) => {
if (pat !== patCurrent) {
try {
regexp = new RegExp(pat, 'i');
patCurrent = pat;
image_to_is_safe = new WeakMap();
localStorage.setItem(storageKey, pat);
console.log('NGパターンが更新された');
} catch(e) {
return false;
}
}
return true;
};
updatePat(localStorage.getItem(storageKey) ?? patDefault);
document.addEventListener('keyup', e => {
if (e.ctrlKey && e.code === 'KeyB') {
let pat = localStorage.getItem(storageKey);
while (true) {
pat = prompt('NGパターン設定', pat);
if (!pat || updatePat(pat)) {
break;
}
}
}
});
// createElementで生成されたcanvasのfillTextを監視
const canvas_to_text = new WeakMap();
const createElement = document.createElement;
document.createElement = function(tagName, ...args) {
const elem = createElement.call(this, tagName, ...args);
if (tagName === 'canvas') {
const ctx = elem.getContext('2d');
const fillText = ctx.fillText;
ctx.fillText = function(text, ...args) {
canvas_to_text.set(elem, text);
return fillText.call(this, text, ...args);
};
// サイズ調整用の設定
const scaleFactor = 0.8; // ★縮小倍率(0.8倍、20%縮小)
const targetFillColor = "#e8e8e8"; // ★文字色(例:白)
const targetStrokeColor = "#414141"; // ★輪郭色(例:黒)
// サイズ調整を行う共通処理
const applyScaling = (context) => {
const originalFont = context.font;
const originalLineWidth = context.lineWidth;
// フォントサイズの調整(小数点も考慮)
context.font = originalFont.replace(/(\d+(\.\d+)?)px/, (match, size) => {
const newSize = parseFloat(size) * scaleFactor;
return newSize + "px";
});
// 色の調整
context.fillStyle = targetFillColor;
context.strokeStyle = targetStrokeColor;
// 輪郭の太さの調整(デフォルトは1px)
// lineWidthが設定されている場合のみ縮小
if (originalLineWidth > 0) {
context.lineWidth = originalLineWidth * scaleFactor;
}
return { originalFont, originalLineWidth };
};
const originalFillText = ctx.fillText;
const originalStrokeText = ctx.strokeText;
// 1. fillText(塗りつぶし)のフック
ctx.fillText = function(text, x, y, maxWidth) {
const originals = applyScaling(this);
canvas_to_text.set(elem, text); // NG判定用にテキストを保持
const result = originalFillText.call(this, text, x, y, maxWidth);
// 元の状態に戻す
this.font = originals.originalFont;
this.lineWidth = originals.originalLineWidth;
return result;
};
// 2. strokeText(輪郭)のフック(修正点)
ctx.strokeText = function(text, x, y, maxWidth) {
const originals = applyScaling(this);
// ここではテキスト保持は不要(fillTextで行っているため)
const result = originalStrokeText.call(this, text, x, y, maxWidth);
// 元の状態に戻す
this.font = originals.originalFont;
this.lineWidth = originals.originalLineWidth;
return result;
};
}
return elem;
};
// コメント描画canvasのdrawImageを監視
const modifyCommentCanvas = () => {
const commentCanvas = document.querySelector('.CommentRenderer > canvas') || document.querySelector('[data-name=comment]>canvas');
console.log('cvs', commentCanvas);
if (!commentCanvas) {
setTimeout(modifyCommentCanvas, 100);
return;
}
const commentCtx = commentCanvas.getContext('2d');
const drawImage = commentCtx.drawImage;
commentCtx.drawImage = function(image, ...args) {
let is_safe = image_to_is_safe.get(image);
if (is_safe === undefined) {
const text = canvas_to_text.get(image);
if (text === undefined) {
is_safe = true;
} else {
const m = text.match(regexp);
if (m) {
console.log('NG', m[0]);
is_safe = false;
} else {
is_safe = true;
}
}
image_to_is_safe.set(image, is_safe);
}
if (is_safe) {
drawImage.call(this, image, ...args);
}
};
console.log('コメント描画のCanvasを書き換えた');
};
modifyCommentCanvas();
// 3. ページの変更を監視して、新しいCanvasが現れたら即座にパッチを当てる
const observer = new MutationObserver(() => {
// ニコニコのプレイヤー構成に合わせてセレクタを指定
const canvas = document.querySelector('.CommentRenderer > canvas') ||
document.querySelector('[data-name=comment] > canvas');
if (canvas) {
modifyCommentCanvas(canvas);
}
});
// 監視開始(body全体を監視してCanvasの登場を待つ)
observer.observe(document.body, { childList: true, subtree: true });
})();
正規表現について
何個でもNGワードを登録できる
「〇〇|✕✕|△△」のように、「 | 」で単語を囲うことで、 好きなだけブロックすることができる。
注意点
「|〇〇|✕✕|△△|」のように、行頭・行末にまで「 | 」を付けてしまうと、全てのコメントが非表示になってしまうので注意。
正規表現の使い方
- (.)\1{20}
- 20回以上同じ文字を繰り返し使用したコメントがヒットする。
- 「いけええええ」とか「飛んだああああ」とか「wwww」とかの文字をやたら長くしている邪魔なコメを消せる。
- ^なるほど$
- 特定の文字列の完全一致コメのみを消す。
標準のNG機能ではできない正規表現の強み。 - 行頭「^」から、文字列を挟んで、行末「$」までが同じコメントだけを消す。
- やたら「なるほど」が連投されている動画があるので、それだけを消して、「なるほど、〇〇ですね」など人間が打ってそうなコメントはNGしないようにする。
- 特定の文字列の完全一致コメのみを消す。
- \(汗\)
- 半角の記号は正規表現用の特殊なコマンドとして判定されてしまう。
- そのため、半角の記号をそのまま文字として認識したい場合は、「\」を左に付ける。
- その他
- 特定|原作勢|歌詞|過去タグ|逆再生|空耳|再走|中の人|批判|伏線|死ね|成仏|見納め|ゴーウィ|パチパチw|何がまずい|なにがまずい|過去タグ|ご友人|TE勢|TE勢|アンチ|ノルマ|(意味深|(意味深|貧乳|まな板|^壁$|コロナ
- 使い古されたコメや動画から逸れた話題を消す。
正規表現が実際に効いているかテストする
【コマンドテスト】コメントテスト用動画【練習用動画】 - ニコニコ動画
上記のようなテスト用の動画に消したいコメントを打って、正規表現がうまく効いているか試してみるとよい。
確認したら打ったコメントは消すこと。