Webブラウザのブックマークレット機能でニュース記事のテキストを抽出してみる

岩手県立大学とか、岩手の人たち Advent Calendar 2022 23日目の記事です。今日はニュース記事をテキストとして抽出する話をしようと思います。

ニュース記事のブックマーク

ネット上で見かけて気になったり、後から参照しそうな記事をブックマークしておくことは良くあるかと思います。しかし、記事によっては掲載期間が過ぎると閲覧できなくなるものもあり、時間が経ってからブックマークを開くと「記事が見つかりません」という表示がされて残念な気持ちになることがあります。

その都度、Webページを保存したりテキストで手元にコピペしておけばよいのですが、数が多くなるとこれも面倒です…。Webスクレイピングでテキスト抽出、という方法もありますが、昨今のニュース記事のWebサイトはJavaScriptで表示制御されていることも多く、いつでも適用できる方法ではありません。

Webブラウザブックマークレット機能

ところで、Webブラウザでは「ブックマークレット」という機能があり、ブックマークから小さなJavaScriptプログラムを動かすことが可能です。この機能の嬉しい(面白い?)点として、ブックマークレットを走らせると、ユーザが現在閲覧しているWebサイトでJavaScriptを動かせるというものがあります。これを応用して、ニュース記事のWebサイトから記事のテキストを抽出することもできそうです。

ブックマークレットの作り方

ブックマークレットの作り方は簡単で、ブックマーク作成時にURLの部分に javascript:<任意のJavaScript> を設定するだけです。エディタ等でスクリプトを作成しておいたコードをコピペするのがお手軽な作成方法です。

ニュース記事からテキストを抽出するブックマークレットスクリプト

今回は例として、Yahoo! Japan ニュースからニュース記事をテキストで抽出するサンプルを作成してみます。

サンプルコードは以下になります。ポイントとしては、 window.location で現在閲覧しているURLを取得し、それが対象のURLかどうかを判定することで、関係のないWebページでこのスクリプトの処理が走ってしまうことを防止しています。それ以外は単にWebページ内のHTML構造を document.getElement*() 系の関数でアクセスし、タグ内のテキストを取得しているだけです。

/* Yahooニュース(https://news.yahoo.co.jp/)の記事をテキスト形式で取得するブックマークレットです */
javascript:(function() {
    /* 現在のWebページのURLを取得する */
    let url = window.decodeURI(window.location.toString());

    /* 現在のWebページがYahoo!ニュースの記事ページかどうか判定する */
    if (url.match(/^https:\/\/news.yahoo.co.jp\/articles\//) != null) {
        /* Yahoo!ニュースの記事ページなら、記事の内容をHTMLタグから抜き出す
         * HTMLタグについているclass名を用いてタグを絞り込む */
        let title = document.getElementsByClassName('sc-gpHHfC')[0].innerText;
        let date_time = document.getElementsByClassName('sc-kQsIoO')[0].innerText;
        let body = document.getElementsByClassName('sc-jtggT');
        let chapter = document.getElementsByClassName('sc-gmeYpB');

        /* 抜き出したニュース記事をテキスト形式に整形する */
        let text = `${title}\n`;
        text += `${date_time}\n\n`;
        for (let i in body) {
            if (body[i].innerText == undefined) {
                continue;
            }
            if (i > 0 && i < chapter.length) {
                /* 記事の小見出しを含む場合は「■」で小見出し部分を強調する */
                text += `■ ${chapter[i-1].innerText}\n${body[i].innerText}\n`
            } else {
                /* 記事本文のみの場合 */
                text += `${body[i].innerText}\n\n`
            }
        }
        alert(text);
  }
})()

実際にこのブックマークレットを動かしてみると、以下のようにニュース記事のテキストが抽出できます。このテキストをHTTP POSTで受け取って保存するようなWebAPIを作成しておくとさらに便利でしょう。 (ただし、あくまでも個人用途での利用のみに留めるのが良いかと思います)

まとめ

ブックマークレット機能を利用して、ニュース記事のテキストを抽出する例を紹介しました。Webページの情報を抽出するというケースにおいては、Webスクレイピングがお手軽ですが、JavaScriptで表示内容が制御されているような場合は、そのWebサイトのみで動作する形のブックマークレットを作成し、JavaScriptでHTML構造にアクセスするのが手段としては適切ということもあったりします。