「6÷2(1+2)」問題は100年前にも議論されていた

明示されない乗算と除算記号の演算順序について、記事『「6÷2(1+2)」問題について教育委員会に問い合わせてみた』『6÷2(1+2)問題あらため2a÷2a=1問題 — はてなブックマークのコメントに反応してみる』を書いたのは2015年3月でした。そのときですら既に周回遅れで、検索してみるとその2,3年前にも話題になっていたようです。そして年に数回ほど、突然ばっとこの記事へのアクセスが増えることがあります。どこかで話題になり、検索してたどり着くのでしょう。

私はこの問題に特に興味を持っているわけでもなく、その後を追っているわけでもないのですが、今年(2019年)に入ってまた急にアクセスが上昇したので、思い出したように自分でも検索してみたところ、興味深い例を見つけました。

Lennes, N. J. “Discussions: Relating to the Order of Operations in Algebra.” The American Mathematical Monthly 24.2 (1917): 93-95. Web. https://www.jstor.org/stable/2972726

です。内容をかいつまんでみると、

  • 理論的には、演算順序は左から右なので、9a2÷3a = 3a3 であって 3a ではない。
  • しかし実際には、9a2÷3a = 3a のような例ばかりが見られる。
  • 当時の Chrystal の代数の教科書では、これを避けるため、乗算記号のない積を除算記号の直後に置かないよう注意深く書かれていた。
  • それに続くいろいろな人による教科書ではその注意が足りず、10bc\div 12a = \frac{(10bc)}{(12a)} などと書かれた。
  • 9a2÷3a は 3a を意味して 3a3 ではない、というのは「数学の慣用表現」である(英単語 drink の過去形が drank であって drinked でないように)。
  • これは論理的ではなく、歴史的な事柄である。

というものです。

以前の私の記事には、なんとか 9a2÷3a が 3a であることの理論的(?)根拠を示そうと、多くのコメントが付きました。私にはさっぱり響きませんでしたが。それが100年も前に「理論ではない、“慣用表現”だ」と喝破されていたのでした。古い文献に 9a2÷3a が 3a のような例があることをもって、それみろと言わんばかりにこれを主張する人がありましたが、むしろ逆で、古い文献にあるからこそ「歴史的遺物」とも言えるわけです。

以前の記事へのコメントに答えて私も「Smith の第33条で、(a÷b÷cは)「a÷bcと書くこともあるよ」と、ほんのおまけのように付け加えていることは、ただこの慣習に触れているにすぎないのではなかろうか、と思わされました。」(2015年3月18日のコメント)と書いています。今あらたにその思いを強くしています。

繰り返しますが、私はこの問題に特段の興味があるわけでもなく緻密に議論を追っているわけでもありません。その私は今、

  • ずっと昔は、乗算と除算の優先順位が同等でない考え方もあった。“If an arithmetical or algebraical term contains ÷ and ×, there is at present no agreement as to which sign shall be used first.” (Cajori ”A History of Mathematical Notations” 1928–29)
  • 「慣習的に」9a2÷3a が 3a であるような表記もしばしば行われた。
  • 既に100年前に、それは慣習的・歴史的なものであり、理論的ではないと指摘されていた。
  • 理論的でない表記は廃れるかと思われたが、いつしか「慣習的」であることが抜け落ちた。
  • 今日でも中学生にはこれが「慣習的・歴史的」とは告げずに教えられている。

のような流れではなかろうかと推測しています。

この Lennes (1917) の存在を教えてくれたのは、今回検索していて見つけた動画でした。

私の記事よりは後の2016年に公開され、現在(2019年)までに1千万回以上も視聴され、7万件以上のコメントが付いています。もちろんすべてのコメントを見ることはできていませんが、ざっとみたところ「1派」も「9派」もたくさんいます。このことからはっきりわかるのは、この問題は「あいまい」であるということです。

以前の記事へのコメントでも書きましたが、この問題についての私の考えは次のとおりです。それは上述の100年前の指摘を知った今も変わりません。

ab÷ab を ab÷(ab) と書きさえすれば誰もあいまいだとは思いません。中学校でもこの表記で教えて何か困ることがあるでしょうか。括弧を付けても単項式の除算の意味を教えるのに何の不都合もありません。現状のあえて括弧を付けない ab÷ab でしか表せない何かがありますか。ab÷ab と書かなければならない必然性がどこにもありません。(2016年3月7日のコメント)
「すべき」ことは、むしろ括弧を使うことです。別の解釈をさせたければ ab÷(ab) と、括弧をつかう「べき」です。単項式わる単項式の理解度を計測するのに、括弧を使っても何の不都合もありません。(2018年9月4日のコメント)

【この記事にコメントする際の注意】

この話題に関する以前の記事『「6÷2(1+2)」問題について教育委員会に問い合わせてみた』『6÷2(1+2)問題あらため2a÷2a=1問題 — はてなブックマークのコメントに反応してみる』には非常に多くのコメントが付けられ、後から読む人が苦労するほどになってしまいました。そのため、それらの記事へのコメントの受付を停止します。

この記事へのコメントは、それらの記事に既に付けられているコメントと同内容と私が判断するものは、原則として不掲載とし、削除することをあらかじめ宣言しておきます。自由に意見を述べることを封殺する意図はありません。後にここを目にする人たちに対しての配慮です。ご理解ください。

WordPress の新テーマ Twenty Nineteen での日本語フォント

2018年12月に WordPress 5.0 がリリースされ、それに含まれるデフォルトテーマは Twenty Nineteen という新しいものになりました。

WordPress 5.0 のリリース告知 に、Twenty Nineteen の特長として次の点が挙げられています[1]

Simple, type-driven layout

Featuring ample whitespace, and modern sans-serif headlines paired with classic serif body text, Twenty Nineteen is built to be beautiful on the go. It uses system fonts to increase loading speed. No more long waits on slow networks!

WordPress 5.0 “Bebo”

この部分が日本語では

シンプルなタイポグラフィ主導のレイアウト

たっぷりとった余白と、モダンなゴシック体の見出し、クラシックな明朝の本文テキストの組み合わせが特色の Twenty Nineteen は、出先でも美しくあるために造られました。システムフォントを使用して、読み込みスピードを向上させました。もう、遅いネットワークで長時間待つ必要はありません !

WordPress 5.0 “ベボ”

と、「ゴシック体」「明朝」と訳されています。

バージョン 1.0 での日本語への対応

確かに、元々の Twenty Nineteen では sans-serif と serif を使い分けるようにスタイルシートで設定されています。しかし WordPress 5.0 の最初のリリース時点 (Twenty Nineteen バージョン 1.0) では、日本語 (など非ラテン文字言語) の場合の議論が十分に間に合わず、非常に乱暴な対処がなされました。スタイルシート style.css を見ると、

/* Japanese */
html[lang="ja"] .site * {
  font-family: -apple-system, BlinkMacSystemFont, "Hiragino Sans", Meiryo, "Helvetica Neue", sans-serif !important;
}

と、すべてのタグに同一の sans-serif 系の font-family が指定されています (しかも !important 付きで)。これはもう本文テキストと見出しが同じどころか、<pre><code> も monospace ですらなく何もかもが一緒くたという指定です。はっきり言って「看板に偽りあり」です。

バージョン 1.3 での改善点

さすがに全称セレクターと !important だと思わぬところにも影響が及ぶということもあり、最初のリリースには間に合いませんでしたが、WordPress 5.1 とともに配布される Twenty Nineteen (バージョンはおそらく 1.3) では、根本的な対応がなされることになりました。

Twenty Nineteen のスタイルシートは Sass で開発されています。@each@mixin を使うことで既存部分の変更は最小限で書き足す部分もほんのわずかで済み、さらに @extend (と placeholder) を使って、生成される style.css のサイズ増加をできるだけ抑えるという変更案が出されました。

これにより Twenty Nineteen バージョン 1.3 では、元々あった font-family の一つ一つに対して、非ラテン文字言語ごとのバリエーションが設定されました。1.0 とは対極の、実に丁寧な対処です。

改善されなかった点

スタイルシート内にたくさんある font-family に埋め込む値は、sass/variables-site/_fonts.scss に記述されているのですが、元々、ラテン文字言語に対して

$font__body: "NonBreakingSpaceOverride", "Hoefler Text", "Baskerville Old Face", Garamond, "Times New Roman", serif;
$font__heading: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans"
$font__code: Menlo, monaco, Consolas, Lucida Console, monospace;
$font__pre: "Courier 10 Pitch", Courier, monospace;

のように、4つに分けて設定されています。非ラテン文字言語に対しては、下2つ ($font__code, $font__pre) のそれぞれは手を付けずそのままとなったのはいいとして、上2つ ($font__body, $font__heading) は区別せずに合わせて同じフォントとされてしまいました。

私は、本文用と見出し用のそれぞれ別のフォントが設定できてしかるべきと考えています (各言語ごとに合意を形成する段階で、本文用と見出し用のフォントを同一にするという結果に達すればそれはそれでいいことです)。しかしこの時点では、既にリリースしたものからの大幅な変更は避けたい、非ラテン文字言語での serif 系と sans-serif 系の使い分けの合意はない、まとめられるものはまとめようということで、別々の実装は退けられました。

もうひとつの問題は、style.css のサイズがかなり大きくなってしまうことです。ラテン文字言語しか使わない人たちにとっては無用の記述が大量に追加されたことになります。今回の追加部分は別ファイルにして、不要な人たちは読み込まずにすむようにできればよりいいでしょう。

WordPress のデフォルトテーマは、そのまま使われるだけでなく、「標準」としてしばしば参照されます。非ラテン文字言語フォントの扱いの例としてきちんとした形に残してほしかったのですが、リリース時期の制約などもあってそれが叶いませんでした。次の機会には何とかしてほしいものです。GitHub でのやりとり (それに、それが回送された Trac でのやりとり) はそのうち埋もれて忘れられそうなので、こうしてここにメモしておくことにしました。

  1. WordPress 5.0 をお使いなら、管理画面の左上隅の「W」マークをクリックして「新着情報」でも見ることができます。

2001–2010年ころの日本語システムフォント

これまでにも何度か書いているように、私自身は個人的には「日本語のある程度の長さのまとまった文章には、ゴシック体より明朝体のほうが向いている」と考えています。Web ページにおいても、です。

一方で、「Web ページはゴシック体」という意見が数多く見られます。おそらく、単純に「明朝派」か「ゴシック派」かで言えば、「ゴシック派」のほうがかなり多数のような印象があります。

システムフォントの歴史

いろいろ思い出すために、2000年頃以降のシステムフォント—大きなシェアを占めていた Windows と Mac にデフォルトで装備されているフォント—について、ざっと調べてみました。

Windows

2001XPMS明朝ゴシック 2.30 MS明朝 2.31
2006Vistaメイリオ 5.00 MS明朝ゴシック 5.00 MS明朝 5.00 (JIS X 0213:2004)
20138.1游ゴシック 游明朝

Mac

MacOS 9.2.2までOsaka 平成明朝 リュウミンライト-KL
2001OS X 10.0ヒラギノ角ゴ Pro W4・ヒラギノ明朝 Pro W3
200710.5ヒラギノ角ゴ ProN W4・ヒラギノ明朝 ProN W3
201310.9游ゴシック体 游明朝体 M

フリーフォント

私自身はこの時代より前から今日に至るまでずっと Linux (Debian) を常用していて、それにはデフォルトとか標準という考えがなく好みのフォントを使います。もう記憶が確かでない部分もあるのですが、主流だったと思えるものを拾い出してみました。

1998-1999渡邊フォント
2000-2003Kochi
2003-2004Sazanami
2007IPAゴシック・IPA明朝 (単体配布)
2010IPAexゴシック・IPAex明朝
2010Takaoフォント
2014源ノ角ゴシック / Noto Sans CJK JP
2017源ノ明朝 / Noto Serif CJK JP

参考:ブラウザーの歴史

1992mozaic
1994Netscape Navigator
1996NN3, IE3
1997NN4
2001IE6
2003Safari (10.3から。それ以前(10.2)の標準ブラウザはIEforMac)
2004Firefox 0.8
2006IE7
2008Chrome

漠然とですが、

  • 2001–2010年ころ、Web ページにとって明朝体は、技術的に「使い物にならな」かった
  • そのため、その頃とそれ以降、日本語の Web ページは圧倒的にゴシック体を主体としたものが多い
  • その環境で育った人たちは、もう「Web ページはゴシック体」が当たり前であり、技術的な問題が既に解決されても、むしろ明朝体だと違和感がある

のようなことではなかろうかと考えています[1]

2001年のMacOS Xにヒラギノというのは本当に画期的だったとは思うのですが、何しろシェアが違いすぎ、それにあぐらをかいた Windows のために「暗黒の10年」だったと言っても過言ではありません。ブラウザーの IE6 天下と軌を一にしています。

話はややずれますが、ハードウェアとしてのディスプレイが CRT から LCD になっていったのものこの頃でした。私が切り換えたのはだいぶ遅めの2005年ころでしたが、CRT ではいい具合にボケていた文字の輪郭が LCD だとくっきりしすぎて、文字として美しくなくなったのを覚えています。それからアンチエイリアスとかヒンティングなどを意識することになりました。

  1. 翻って考えると、私の「日本語のある程度の長さのまとまった文章には、ゴシック体より明朝体のほうが向いている」という考えも、WWW 以前の、印刷物に接する時間が長かった(印刷物は言うまでもなく、本文は明朝系であることが圧倒的に多い)影響が強いのかもしれません。

IPv6 接続を確認する方法

LAN 側からインターネット側へ

「手元の端末からインターネットへ IPv6 で接続できているか」をチェックするサイトは、test-ipv6.comIPv6-test.com など、たくさんあります。こういうところをブラウザで閲覧すれば、サイト側で接続元の情報を表示するなどして教えてくれます。

ブラウザの拡張 IPvFoo を利用すると、任意のサイトに IPv4 か IPv6 のどちらで接続しているかを知ることができます。これを入れていろいろ見て回ったら、IPv6 に対応していないサイトは案外とまだ多いのだと思いました。

インターネット側から LAN 側へ

今どきは少ないのかもしれませんが、自宅サーバーを設置しようという場合など、逆向きの情報を知りたいときがあります。インターネット側からこのサーバーに IPv6 で到達できるか、を調べるにはどうすればいいでしょう。

IPv6 でインターネットに接続できている別の環境からアクセスできるか試せればいいのですが、にわかにはそれが用意できません。自分でスマートフォンを使って、Wi-Fi を切って電話回線経由でと思ったら、現時点ではほとんどの MVNO は IPv6 に未対応でした。

そこで、自動化されているサイトはないものかと探してみました。【以下、この記事の執筆時点 (2018年12月) の状況です。おそらく数年で大きく状況は変わると思います。】

一般に、ブラウザテストのサービス (たとえば browserling とか WebPagetest など[1]) を利用すれば、そのサイトに到達できてどのように閲覧されるかを知ることができます。しかし、ここで例に挙げたサービスでも「IPv6 で」かどうかはわかりません。現時点ではおそらく IPv4 経由と思われます。また、ポート番号が80か443以外でそれを指定しなければならない URL は受け付けなかったり、トップではないページを指定できなかったりします。

さんざん探し回った挙げ句に見つけたのが、まずは外部から IPv6 でポートスキャンをやってくれるところ。自宅サーバーのターミナルで w3m を動かして、この3番か4番でチェックします。これで少なくとも外から到達できているかどうかが確認できます。

もう一つが CA App Synthetic Monitor の Web サイト チェック。「IPv6 がサポートされるようになりました 」と謳っています。チェック対象サイトの IP アドレスが表示されるので、その形式で IPv4 か IPv6 のどちらで接続しているかわかります。スクリーンショットまではありませんが、「ダウンロードサイズ」からおそらくちゃんと到達できているだろうと推測できます。このサービスでは、ポート番号指定の URL やトップでないページでも大丈夫でした。

「サーバー」と言っても WWW だけではありません。しかし上の2つで IPv6 での接続が確認できたので、WWW 以外のサービスもおそらく無事に IPv6 で開放できていると考えることにしました。

  1. もうひとつの例、WAVE は単にスクリーンショットを取ってくれるのではなく、いろいろアドバイスしてくれるので何かと便利です。

Emacs 風キーバインド

先日、久しぶりに勉強会のようなところへ出かけてみました。そこで会の主要なテーマとは直接関係のない Mac のキーバインドの話を聞きました。私は Mac にはほとんど触れたことがないので知りませんでしたが、おやこれは「Emacs風キーバインド」ではないかと思いました。起源はもう忘れられているかもしれません。

さて、そこで Debian をデスクトップで使っているという自分の環境を思い返してみました。エディターは主に Emacs なので、いろいろなところを「Emacs風キーバインド」にしたいと思いながら、ウィンドウマネージャーを変更したりブラウザーがバージョンアップして拡張機能が効かなくなっていたり、と、いつの間にか不便な状態になっていて、まあそのうち、と思いながら過ごしていたのです。

これを機会に、ちょっと探してみました。ほとんど自分用メモですが、Mac から Linux に乗り換えたい人への情報になるかもしれません。

Xfce4

以前 Gnome を使っていた頃はどこかで設定していたのですが、数年前に Xfce4 に切り替えてから、どうすればいいのか調べてもおらず、そのままになっていました。

「設定」→「設定エディター」で、「チャネル」の一番下の xsettings を開き、Gtk のグループの中のプロパティ KeyThemeName の値に Emacs と入力します。

これで、Xfce4 上で開く多くのアプリケーションで、C-aC-eC-k などが有効になりました。ただし C-y で取り出せるバッファが C-k と連動していないところが Emacs や次の bash と違う挙動で、ときどき混乱してしまいます。

Bash

ターミナル内のシェル は bash です。これは元々「Emacs風キーバインド」のようで、入力行で C-aC-eC-k が使えて、C-k したものを C-y で貼り付けることができます。C-pC-n で履歴をたどれるなど、かなり多くのキーバインドが使えます

Firefox

以前は、拡張機能でそういうのがあったのですが、ブラウザー本体のバージョンアップで使えなくなっていました。

上述の Xfce4 の設定で、いくらかのキーが使えるようになりました。しかし、上下に動かしたいときについ C-pC-n と打って「印刷」「新しいウィンドウを開く」になってしまったり、ページ内検索のつもりでつい C-s と打って「ファイルに保存」になってしまうことがしょっちゅうなので、この辺りを補ってくれるものはないかなあと思っています。

GhostText

Firefox の入力欄 (textarea) で、好きな外部エディターを使えます。以前は別の拡張機能を使っていたのですが、やはりブラウザー本体のバージョンアップで使えなくなってしまい、また別の拡張機能も WordPress の新しい入力画面 Gutenberg との相性が悪そうなので、現在は GhostText を使っています[1]

Emacs 側でも準備が必要で、atomic-chrome パッケージをインストールして、設定しておきます。

  1. GhostText という拡張機能は Firefox にも Chrome にもあり、元々 Emacs 以外のエディターを使うものだったので、それらのどの組み合わせでも使えます。

HTML の <ruby> に思うこと

ニュースサイトから記事本文を抜き出して利用しようという作業をやってみて、<ruby> 要素がほかの要素に比べてかなり異質なものあることに気がつきました。

ニュースの本文は

...<p><span class="colorC"><ruby>気象庁<rt>きしょうちょう</rt></ruby></span>は「もっと<a href="javascript:void(0)" class="dicWin" id="id-0000"><ruby><span class="under">二酸化炭素</span><rt>にさんかたんそ</rt></ruby></a>を<ruby>出<rt>だ</rt></ruby>さないようにしなければなりません」と<ruby>話<rt>はな</rt></ruby>しています。</p>...

のようになっています。BeautifulSoup の .text で単純にタグを削除するだけでは

気象庁きしょうちょうは「もっと二酸化炭素にさんかたんそを出ださないようにしなければなりません」と話はなしています。

と、ルビが本文に混じってしまい、まともな文になりません。事前に rt 要素を削除しておく必要があります。

実際に行った作業は「HTML からタグを除去して本文を取り出す」なのですが、単純に行って得られるものは上記のとおりで、それを「本文」とは呼べないと思うのです。

マークアップ言語

はじめに、

気象庁は「もっと二酸化炭素を出さないようにしなければなりません」と話しています。

という“内容”そのものがあります。これに“意味”をつけるために、たとえば「気象庁」は固有名詞という意味をつけるためにこれを <span> で囲み、それからこの文ひとつでひとつの段落という意味をつけるためにこれを <p> で囲みます。これがマークアップであり、そのためのタグであるはずです。

次の段階で、これをどう表示するか、たとえば固有名詞は文字を赤色にし、段落はそのはじめに改行する、というものはさらに分離してスタイルシートで記述することになっています。

逆向きに考えてみます。ブラウザで表示されるもののソースから表現のスタイルを取り除き、“意味”づけのタグを取り除いたら、残るのは“内容”そのものでなければならないはずです。

ところが今回の例では上述のように、余計なものが残ったままになります。

ルビは“内容”か

私は「ふりがなは内容そのものではなく、それに付け加えているもの」と考えますので、「余計なもの」と書きました。たとえば、ここの言葉は重要と思って下線を付ける、固有名詞ははっきり分かるように文字の色を他と違える、というのと同じで、内容に対して何らか助けのために付け加えているものだと思います。ですから、そういったものを剥ぎ取ったときには残っていてはならないと考えます。

そう考えたときに、現在の仕様の <rt> はかなり異質です。下線や色付けがタグ内の属性 (attribute) とそれに紐付けられるスタイルで表現されるように、ふりがなもタグではなく属性で示されるのが適当だと思います。

仮に <span>ruby という属性が定義されているとして

...<p><span class="colorC" ruby="きしょうちょう">気象庁</span>は「...」と<span ruby="はな">話</span>しています。</p>...

と書くのがもっとも自然のように感じます。

既存の仕様である <a> を逆に考えてみましょう。<a> にとって属性 href は、それがなければほとんど意味がないくらい重要なものです。

もっと<a href="example.html>二酸化炭素</a>を出さないようにしなければなりません

だからと言ってもしそれがタグになっていて

もっと<a>二酸化炭素<href>example.html</href></a>を出さないようにしなければなりません

と書かれるものだとしたら、その違和感がわかろうというものです。

<rt> のあり方

前節に書いたように、ルビは属性で指定されるのが自然だと思います。ではどうすればいいのか。

<ruby>関連要素って駄目駄目」に、この問題の歴史 (なんと不幸な!) から対案まで解説されていました。この記事をぜひじっくり読んでいただきたい。

この記事の「脱法ルビ」が、当面の対応策です。仕様に反せず、仕様内でできる策です。現状ここまでできるのですから、ここに示されているスタイルをレンダリングエンジン側で装備し、属性名を data-ruby ではなく ruby とできるよう仕様のほうが改訂されたら、当分は現在の <ruby>, <rt> との共存期間があったとしても、もうほとんど解決ではないですか。

……と思ったら、このスタイル、すなわち display: ruby-text を実装しているのは Gecko (Firefox) だけで、Webkit (Safari) も Blink (Chrome) も未対応でした (2018年6月現在)。ひどい状況です。

ルビを実際に使う人やデザイナのほとんどは、ほんの少し首をかしげるくらいはあっても、仕様に従って使うだけで、その仕様がどうあるべきかまで問い返したりはしません。そもそも世界のうちでごく限られた言語だけでしか知られておらず、その中でも使う人はごく少数ですから、問題にする人も滅多にいなければ対応もぜんぜん進まないのでしょう。ほんとうに不幸です。

ニュースのスクレイピングでタイピング練習

ひらがな数文字を打ち返すだけのタイピング練習は案の定すぐに飽きてしまったので、何か別のネタを考えなくてはならなくなりました。飽きないためには膨大かまたは頻繁に更新される元データがあればいい、青空文庫かな、でも小学生に向いているものがどれほどあるかしらん、頻繁に更新されるといえばニュース、でもこれまた小学生向きではなさそう……と思ったら実にぴったりのものがありました。NHK NENS WEB EASY です。ひとつの記事で50字ほどの文が10ほど。意味もわかりやすくて量もちょうどいい。かなり手間をかけて作られているようです。

さて、これをなんとか持ってきてタイピング練習の材料にしようと思ったのですが、何しろ本業でも何でもないので情報を集めるところからスタートでした。今回やっていることは実は「スクレイピング」という程のこともないのですが、そのとっかかりということで、せっかくなのでここに記録しておきます。

環境の準備

NHK NENS WEB EASY のページの肝心な部分は JavaScript で生成されているようで、Python で単純に requests.get(url) とやっても、ブラウザで見ている HTML ソースとは別のものしか得ることができません。そこでまず、ブラウザが実際に表示するページを取得できるようにします。

Debian パッケージ chromium-driver をインストールします。

sudo apt-get install chromium-driver

これを Python から使うためにライブラリ Selenium をインストールします。

pip install selenium

取得した HTML から必要な箇所を切り出すのには BeautifulSoup4 を使います[1]

pip install beautifulsoup4

でインストールします。

ニュースサイトの構造

ニュースサイトによくあることですが、各記事の URL は数字の羅列のような名前で、先頭ページではそれが日々更新されます。

ブラウザのデベロッパーツールで NHK NENS WEB EASY の先頭ページ https://www3.nhk.or.jp/news/easy/ の構造を見てみます。

<div class="top-news-list__pickup news-list-item" id="js-news-pickup">
  ...
  <h1 class="news-list-item__title is-pickup">
  <a href="./k10011463631000/k10011463631000.html"><em class="title"><ruby>日本<rt>にっぽん</rt></ruby>の<ruby>二酸化炭素<rt>にさんかたんそ</rt></ruby>の<ruby>濃度<rt>のうど</rt></ruby>が<ruby>今<rt>いま</rt></ruby>まででいちばん<ruby>高<rt>たか</rt></ruby>くなる</em><time class="time">6月5日 11時30分</time></a>
  </h1>
</div>

最初に大きく取り上げられている記事は <div id="js-news-pickup"> で、その中の <h1> の中の <a> から記事個別ページの URL が得られます。

その記事個別ページを同様にブラウザのデベロッパーツールで見てみると、記事本文は <div id="#js-article-body"> にあることがわかります。これを切り出してくればいい訳です。

スクレイピング

参考にした (というか、ほぼそのままコピーさせてもらった) コードは「Python Webスクレイピング テクニック集」の「JavaScriptによる描画に対応する」です。

ソース中のコメント「ブラウザを起動する」の箇所で、ブラウザのパスを指定する必要がありました。Debian のパッケージを使っている場合

driver = webdriver.Chrome(executable_path='/usr/bin/chromedriver', chrome_options=options)

です。

切り出し

1回めの

        # ブラウザでアクセスする
        siteurl = "https://www3.nhk.or.jp/news/easy/"
        driver.get(siteurl)

        ...

        # BeautifulSoupで扱えるようにパースします
        soup = BeautifulSoup(html, "html.parser")

        # id で特定の要素を切り出す
        href = soup.select_one("#js-news-pickup h1 a").get('href')

で記事個別ニュースの URL が得られるので、2回めは

        driver.get(newsurl)
        html = driver.page_source.encode('utf-8')
        soup = BeautifulSoup(html, "html.parser")
        # ルビを削除
        for s in soup(['rt']):
            s.decompose()

        ...

        # ニュースの本文
        text = soup.select_one("#js-article-body").text

で、記事本文を切り出します。

ルビを削除

ニュースの本文は

...<p><span class="colorC"><ruby>気象庁<rt>きしょうちょう</rt></ruby></span>は「もっと<a href="javascript:void(0)" class="dicWin" id="id-0000"><ruby><span class="under">二酸化炭素</span><rt>にさんかたんそ</rt></ruby></a>を<ruby>出<rt>だ</rt></ruby>さないようにしなければなりません」と<ruby>話<rt>はな</rt></ruby>しています。</p>...

のようになっています。BeautifulSoup の .text で単純にタグを削除するだけでは

気象庁きしょうちょうは「もっと二酸化炭素にさんかたんそを出ださないようにしなければなりません」と話はなしています。

と、ルビが本文に混じってしまい、まともな文になりません。事前に rt 要素を削除しておく必要があります。

この作業をやってみて、rt がほかとは異質なタグ(要素)であることを実感しました。これについてはまた別の記事に書こうと思います。

1文ずつに分解

記事を「。」で区切り、リストにします。「。」自身も含めたいので split が使えません。NHK のニュース記事で全体の最後に「。」がないことはまさかないだろうと仮定して、

        lines = re.findall(".*?。", text)

とします。あとは Errnot がこれを1文ずつ表示するようにするだけです。これでこの bot を相手に XMPP のチャットでオウム返しにタイピングの練習をすることができるようになりました。

それにしても、いろいろ寄せ集めるだけでこれだけできるのですから、便利な世の中になったものだとつくづく思いました。

  1. Python にはじめからある html.parser でもある程度できます。また Selenium にも同様の機能があるようです。