はてなキーワード: ブックマークレットとは
https://chromewebstore.google.com/detail/hatebu-comments-sorted-by/fnkcdmbjapomjpilfeekjofbndmdobib
機能としては、新着コメントの横に人気コメントのタブを用意して、そこをクリックするとスター数が多い順でコメントを表示するというシンプルなものだ。
建設的コメントアルゴリズムに弾かれても星を取りに行くブクマカとしての生き様を追い求めたいという増田についていたブコメを見て作成した。
半分くらい作ったところで、似たような機能を持つブックマークレットが存在することを知ってショックを受けたが、とりあえず完成はさせた。
記事についたコメント数が数百を超えるような場合には、上手く動作しないことがある。
同期処理が上手くいってないことが原因だと思われるが、Javascriptはよくわかっていないのでそこは諦めた。
ありがとう。ChatGPTに作ってもらった。数値文字参照でないといけないというのは素人には教えてもらわないとたどり着けないので感謝です。
ハイライトされた文字列を <pre> タグで囲み、特殊文字を数値文字参照に変換し、改行を <br> タグに置き換えて、元の文章をその場で置き換えるブックマークレットを作成
javascript:(function() {
function escapeHtml(text) {
return text.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/\n/g, '<br>');
}
var s = window.getSelection().toString();
if (s) {
var escapedText = escapeHtml(s);
var wrappedText = '<pre>' + escapedText + '</pre>';
prompt('以下のコードをコピーしてください:', wrappedText);
} else {
alert("文字列をハイライトしてください。");
}
})();
FANZAの検索結果から熟女を除外するブックマークレット がうまく動いたので、気を良くしてはてなブックマークのコメント欄をスター数順にソートするブックマークレットを作りました。
作った動機は、「注目コメントに入りきれなかったちょっといいコメント」をサクサク探したいから。結果として建設的コメント順位付けモデルを無効化していますが、あのアルゴリズムには特に不満は特にありません。
javascript: (async () => {
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
document.querySelector('.js-bookmarks-sort-tab[data-sort="recent"]').click();
window.scrollTo(0, document.body.scrollHeight);
await wait(1000);
window.scrollTo(0, 0);
await wait(1000);
const p = document.querySelector('.js-bookmarks-recent');
let l = Array.from(p.querySelectorAll('.entry-comment-contents'));
const g = e => {
let n = e.querySelectorAll('.hatena-star-star').length;
const c = e.querySelector('.hatena-star-inner-count');
return c ? n + Number(c.textContent) : n
};
l = l.filter(e => g(e) > 0);
l.sort((a, b) => g(b) - g(a));
p.replaceChildren(...l);
})();
ミニファイしたもの ※コードに一部誤りがありましたので訂正しました(2024-08-16 11:47)
javascript:(async()=>{const wait=ms=>new Promise(resolve=>setTimeout(resolve,ms));document.querySelector('.js-bookmarks-sort-tab[data-sort="recent"]').click();window.scrollTo(0,document.body.scrollHeight);await wait(1000);window.scrollTo(0,0);await wait(1000);const p=document.querySelector('.js-bookmarks-recent');let l=Array.from(p.querySelectorAll('.entry-comment-contents'));const g=e=>{let n=e.querySelectorAll('.hatena-star-star').length;const c=e.querySelector('.hatena-star-inner-count');return c?n+Number(c.textContent):n};l=l.filter(e=>g(e)>0);l.sort((a,b)=>g(b)-g(a));p.replaceChildren(...l)})()
FANZAの検索結果から熟女を除外するブックマークレット 参照
javascript:
ブックマークレットに必要な、URLの種類を示すスキーム名です。
(async () => {
// 処理
})();
ページに元々ある変数たちとバッティングしないように、まず無名関数でラップします。処理の中で await を使いたいので async 宣言しています。
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
document.querySelector('.js-bookmarks-sort-tab[data-sort="recent"]').click();
window.scrollTo(0, document.body.scrollHeight);
await wait(1000);
「新着コメント」タブをクリックし、ページの一番下までスクロールダウンしてから少し待つ動作です。新着コメントの後半部分(スクロールきっかけの遅延読み込みになっているところ)の読み込みをうながしています。
window.scrollTo(0, 0);
await wait(1000);
ページの先頭に戻ってまた少し待ちます。合計2秒の待ち時間は雰囲気で決めていますので、これでなければならない・これで過不足ないという値ではありません。単にコメントの読み込み完了を判定する処理を書くのがめんどうだっただけです。
const p = document.querySelector('.js-bookmarks-recent');
新着ブコメの親要素です。繰り返し呼び出すので名前をつけています。
let l = Array.from(p.querySelectorAll('.entry-comment-contents'));
const g = e => {
let n = e.querySelectorAll('.hatena-star-star').length;
const c = e.querySelector('.hatena-star-inner-count');
return c ? n + Number(c.textContent) : n
};
コメントのはてなスター数をカウントして返す関数です。たくさんスターがついてる ★256★ みたいなやつの数字も足します。
l = l.filter(e => g(e) > 0);
ソートする前に、無スターのコメントを消去しています。してもしなくてもいいことですが。
l.sort((a, b) => g(b) - g(a));
残ったコメントをスター数で降順ソートします。.querySelectorAll() で収集した要素を配列に入れ直したのは、この .sort() メソッドを使いたいからです(.querySelectorAll() が返す配列風の NodeList オブジェクトは、配列と共通のメソッドもいくつかあるものの、大半は使えないのです)。
p.replaceChildren(...l);
親要素の内容を、並び替えの終わったコメントでそっくり入れ替えて、処理完了です。画面を見ると新着コメントの中身が「スターのついたコメントのみ・スターの多い順」に並んでいます。元に戻す方法はないので、原状回復にはリロードします。ソート状態を示すフラグを立てておいてスター数ソート⇔日付ソートをかわりばんこに行うようにすればできそうだなと思ったけど実装はしません。連打スターを省く処理を追加してUU数でソートできればもっと厳正なランキングになるなーと今思いつきましたがそれも実装はしません。
私は熟女モノとか人妻モノは眼中にないのですが、なぜだか最近そっち系の作品が多くて閉口しています。
しかしFANZA側の検索システムはNOT検索できるようになっていません。そこで、検索結果から除外できそうなものを除外するブックマークレットを作ることにしました。
さいわい近年は内容の概要文をそのままタイトルにしたような作品ばかりなので、タイトルに含まれるキーワードで除外が簡単にできそうです。
「熟女」とか「五十路」のような単語を含む作品を非表示にしてしまえばよいのです。
javascript: (() => {
const r = /熟女|完熟|熟れ|四十路|五十路|六十路|人妻|奥様|妻|夫|母|ママ|おばさん|BBA|姑|嫁/;
const q = '#list>li';
document.querySelectorAll(q).forEach(l => {
if (r.test(l.textContent)) {
l.remove();
}
});
})();
javascript:(()=>{const r=/熟女|完熟|熟れ|四十路|五十路|六十路|人妻|奥様|妻|夫|母|ママ|おばさん|BBA|姑|嫁/;const q='#list>li';document.querySelectorAll(q).forEach(l=>{if(r.test(l.textContent)){l.remove()}})})()
このブックマークレットで、検索結果に含まれる熟女系作品の数を1/3くらいにまで減らすことができます。
ブックマークレットとは、ブックマークにURLではなくJavaScriptを登録して、閲覧中のページ上で自分(やほかの誰か)が作ったプログラムを実行できるしくみのことです。普通のブックマークと同じようにブックマークバーなどに並べておいて、クリックひとつで呼び出すことができて便利です。
①まず、どこのページでもいいので(今読んでいるこのページでもよい)ブックマークをひとつ作り、ブックマークバーなどの呼び出しやすいところに置きます。
②できたブックマークを右クリックして「編集...」を選びます。
③「名前」欄は、自分にわかりやすい名前に変更します。でも「FANZAフィルター」などあけすけな名前をつけると、誰かに画面を覗かれた時に困りますよ。
④「URL」欄に、上記したプログラムコードを入力します。ただし上記のコードは私向けのキーワード選定になっていますので、ご自身の好みに合わせたキーワード選定をしていただければよいかと思います。/単語1|単語2|単語3/
のように記述してください。
ふつうのソースコードと、改行・インデントなどを省いてミニファイ(最小化)したもの、どちらをコピペしても大丈夫です。
⑦このブックマークレットを起動します。すると、瞬時に検索結果が減ります。
キーワードだけが異なる複数のブックマークレットを登録しておいて、場面に応じて使い分けるなどの工夫もできるでしょう。
上記のスクリプトが何か悪さをするようなものではないことを説明するために、また、JavaScript を学習し始めたばかりの人のために、このシンプルなスクリプトの解説をします。
javascript:
URLの種類を示すスキーム名です。一般的なURLは https:
や mailto:
などで始まりますが、javascript:
と書くと、これに続くコードがプログラムとして実行されます。
(() => {
// 処理
})();
ここからが JavaScript です。まず処理全体をくるむ大きなカッコと最後に付け足された () は、自己実行無名関数という形式です。今回のブックマークレットは変数を含みますので、実行するページに元々ある変数たちとバッティングしないようこのようなかたちにします。
const r = /熟女|完熟|熟れ|四十路|五十路|六十路|人妻|奥様|妻|夫|母|ママ|おばさん|BBA|姑|嫁/;
除外したい単語を羅列した正規表現です。個人個人で設定が変わる部分なので、編集しやすいように切り出しておきました。
const q = '#list>li';
フィルター対象とするHTML要素群のクエリーセレクター文字列です。検索結果に一覧表示される、個々の作品要素を選択します。FANZAがシステム改修を行うと変わってしまう可能性がある部分なので、メンテしやすいようにここだけ切り出しておきました。
document.querySelectorAll(q).forEach(l => {
// 処理
});
クエリーセレクター q
に一致する要素 l
ひとつひとつについて反復して処理を行います。
if (r.test(l.textContent)) {
l.remove();
}
もし要素 l
内のテキストが正規表現 r
と一致していたら、要素 l
を取り除く、という処理です。正規表現 r
はキーワードの羅列ですので、テキストの一部にキーワードのどれかが含まれていたら一致したことになります。
はてブで流れてくるニュース記事でも「~とAP通信が伝えた」「~とCNNが伝えた」みたいなストレートニュースをよく見る。こういう外信記事は元の外国記事だと詳細な解説がついていたりする。それを読むために元の記事を探すのに便利。
国際ニュースを読んでて「何か情報が省かれ過ぎじゃないか?」という記事でも、リード文を適当に選択して翻訳検索すれば現地で発信されてる詳細記事が結果に出る(英語圏じゃないメディアでもだいたい英語発信してるし)。
日本語の記事では、カタカナに翻訳されて伝えられる外国人の名前。気になる人物だったら元の言語で検索して調べたいのだが、カタカナで書かれている名前を英語でどう綴ればいいか、なかなか正確に分からない。そんな時にも選択するだけで英語に自動翻訳して検索してくれて便利。日本語版Wikipediaに項目がなくても英語版にはあったりするから簡単に検索できると人物の背景が掴みやすい。
自分では作れないので今までは誰かが作って公開していたGoogleキャッシュの取得やTwitter検索や魚拓検索くらいしか利用できていなかったが、ChatGTPに頼めば簡単に作ってくれるので、いくらでも細かい指示を出して量産できる。Twitterで今見てるアカウント内で検索、ハイライトした文字を国会図書館デジタルで検索、青空文庫で検索、Fanzaで検索、その他◯◯で検索ってのを普段調べで使うサイトで作って他に、増田で太字タグをつける、URLタグをつける、引用タグをつける、といったはてな記法を使いやすくするブックマークレットも作った。Webアーカイブで開いたページの元ページのはてブのコメントページを開く、だったり、朝日新聞のURLを変換してTwitterで検索するなんて「葬送のフリーレン」に出てくる魔法みたいに特定用途でしか使わない自分用のブックマークレットも作れて満悦。
無料会員のタダ読み3本機能の代わりに導入された有料会員によるプレゼント機能が導入されてもう1年(?)。増田が初めて知ったのはwattoさんのブコメでプレゼントURLを貼ってくれた時だが、最近になってTwitterでスーパーインフルエンサーの暇空アノンのいちゃもんのおかげで一気に機能が周知された。その結果なのかTwitterでもプレゼントURLの貼り付けが増えた感。
面白いのは、いわゆるリベラル系のアカウントの利用のみならず、反リベラル系の有名アカウントもちらほらとプレゼント機能を利用してるってことな。閲覧数は反リベラル系が圧倒的。まあそれなりにコンサル系や研究者系なら思想の左右問わず朝日読売日経辺りを読まないわけにはいかないし、中立アピールのためにあえて朝日ソースを使うってことかな
そして我ながらとんでもなくみみっちいブックマークレットをChatGPTに頼んで作ってもらった
朝日デジタルの有料記事ページを開いている時にクリックするとTwitterで有料記事プレゼント機能を使ってる(と思われる)ツイートを検索するブックマークレット。
javascript: (() => { const currentUrl = window.location.href; const digitalUrl = `digital${currentUrl.match(/\.asahi\.com\/articles\/.+\.html/i)[0]}`; const searchUrl = `https://twitter.com/search?q=${encodeURIComponent(digitalUrl)}&f=live`; window.open(searchUrl, %27_blank%27);})();
このChatGPTのJavaScriptの説明がどうしても分からない。解説あってる?
var idx は、現在開いているWebページのURL文字列に ? が含まれている場合に、その位置を取得するために使用されます。これは、クエリ文字列の開始位置を特定するために必要な処理です。
たとえば、以下のようなURLが現在開いているWebページのURLであった場合、
https://example.com/search?q=keyword&page=1
var idx = url.indexOf('?'); というコードを実行することで、変数 idx には 8 という値が代入されます。これは、? の位置がURL文字列の8文字目にあることを示しています。
var idx はURLの文字列の何番目に?があるかって意味だとは分かった。でも例文のURLだと?の位置はhから数えて27番目だよね。聞いてみた
おっしゃる通り、指定されたURL https://example.com/search?q=keyword&page=1 において ? の位置は h から数えて 27 番目の文字です。
しかし、ブックマークレットのコード中では idx の初期値として url.indexOf('?') を設定しています。この indexOf() メソッドは、指定された文字列が最初に現れる位置を返します。もし文字列が見つからなかった場合は -1 を返します。
したがって、ブックマークレットのコード中で url.indexOf('?') を実行すると、? の位置が返されます。指定されたURLにおいて ? は https:// の直後に出現するため、url.indexOf('?') の実行結果は 8 になります。
つまり、ブックマークレットのコード中では ? の位置ではなく、? の次の文字(q)の位置が idx として設定されていることになります。
なんか意味がわからない。その後もどっから数えた数字がidxになるのかいくつか聞いてみたが堂々巡りになってしまって明確な答えが分からない
今開いているWebページのURLから、?以降を削除して、代わりに .jpg と付け足したURLを、同じブラウザのタブで開き直すブックマークレット
javascript: (function () {
var url = window.location.href;
var newUrl = url.substring(0, url.indexOf("?")) + ".jpg";
})();
javascript: (function () {
var url = window.location.href;
if (url.startsWith("https://pbs.twimg.com/")) {
var newUrl = url.substring(0, url.indexOf("?")) + ".jpg";
} else {
alert("このブックマークレットは Twitter の画像限定でのみ使用できます。");
}
})();
やったー!プログラムとか全然分からんけどChatGPTに頼んで「開いてるページのURLから#以下を消してURLを開くブックマークレット」を作ってもらったぜ
javascript:(function() {
var currentUrl = window.location.href;
var urlWithoutHash = currentUrl.split('#')[0];
})();
やったー!プログラムとか全くわからんけどChatGPTに聞いたら前から欲しかったブックマークレットの機能を簡単に作ってくれたぜ
JavaScriptで今見ているサイトのタイトルをクリップボードにコピーするブックマークレットのコードは、以下のようになります。
javascript:(function(){
let input = document.createElement("input");
document.body.appendChild(input);
input.select();
document.execCommand("copy");
document.body.removeChild(input);
alert("クリップボードに「" + title + "」をコピーしました。");
})();
ブックマークレットでjavascriptをどうぞ。 例えば↓だったら、増田の「言及先エントリを開く」や「ツリーの言及」を全部開くことが出来る。
javascript:document.querySelectorAll(".optimize-get-reference-button,.trackback-header a[onclick]").forEach(function(e){e.click();});
んでブックマークレットに慣れてきたら、Greasemonkey(Tempermonkey)やstylusのような拡張をどうぞ。
→ 言及が全部開かれる