Togetterの内容をGoogleChromeの検証機能でスクレイピングし、WordCloudで可視化してみる

会社での一山越えたのですが、まだまだいろいろと作業があるので微妙なところです。

【イベントページ】

www.ctv.co.jp

さてその山となったイベントがTogetterのまとめページにまとめられたので、今回のエントリーではそのまとめページスクレイピングして、 Wordcloudで処理してみようと考えました。簡単に考えてTogetterのデータはTitter経由で書き込まれているので、以前行ったのと同様に Twitterの書き込みを取得すればいいかなと思ったのですが、同じことをしても面白くないなと思ったのでTogetterのWebサイトをスクレイピングして データの取得を行おうと思います。

【Togetterのまとめページ

togetter.com

WordCloudに関しては下記のエントリーを参考にすればできるかと思います。

【関連】 uepon.hatenadiary.com

Togetterからのスクレイピング処理

基本的にはhttps://togetter.com/li/というURLの末尾にIDをつけることでそれぞれのまとめページに飛ぶことができるようになっています。 今回のターゲットのURIhttps://togetter.com/li/1317653となります。

WebのスクレイピングなのでpythonRequestsモジュールとBeautifulSoup4モジュールを使用して取得したあとにHTMLの解析を行うという形が一般的ですが、 今回は別の方法としてGoogle Chromeの検証機能を使用してスクレイピングを行うことにしました。これだとほとんどコードを書く必要がないのも魅力です。 ただページごとに取得処理を行う必要がある点は面倒ですが…。

【参考】

luuluuul.com

ページを右クリックして表示されるメニューの一番下にある【検証】を選択すると

f:id:ueponx:20190217230549p:plain

検証ツールがWindow内に表示されます。

f:id:ueponx:20190217231359p:plain

その中の【Elements】のタブのHTMLのDOMのツリー構造からTwitterの書き込み部分のものを探していきます。

f:id:ueponx:20190217233342p:plain

該当する部分が見つかったら【console】のタブに移動して出力をさせていきます。ツリー上の要素を表示させるには

$$("【CSSセレクタ】")

とすれば要素の表示が行われます。bodyタグの内容を表示させる場合には

$$("body")

とすればOKです。

f:id:ueponx:20190217233418p:plain

この仕組みを使用すれば、あとはループ処理を使うことで書き込みの文書をすべて取得することができます。 TogetterのTitterでの書き込みの本文だけを取得する場合には以下のようなスクリプトをコンソール上にコピーペーストすれば 出力をクリップボード上にコピーすることができます。

var result = "";
for (var i = 0; i < $$("div.tweet_box div.list_box.type_tweet div.tweet").length; i++) {
    result += $$("div.tweet_box div.list_box.type_tweet  div.tweet")[i].innerText + "\r";
}
//console.log(result);

//クリップボードにコピー
var ta = document.createElement('textarea');
ta.value = result;
document.body.appendChild(ta);
ta.select();
document.execCommand('copy');
ta.parentElement.removeChild(ta);

f:id:ueponx:20190217233549p:plain

このスクリプトの実行を行うと以下のようなデータが取得されます。(クリップボードにコピーされます。)

【hackchu2019_log.txt】

IBMは〇〇テレビハッカソン【HACK-CHU! 2019】を応援します
今週末土曜日は予選【アイデアソン】天気予報では雪マークが出ているようなので当日まで体調を整えて挑みましょう!
ctv.co.jp/hackathon2019/
#hackchu #中京テレビ #IBM #TryIBMDev pic.twitter.com/92WKLrA1Ip
都内は雪が降ってきました
今日は長い一日になりそうです。
#hackchu pic.twitter.com/GFhUn3lelJ
今日は〇〇テレビ主催のハッカソン「Hack-Chu(読み方:ハックチュウ)」のスポンサーメンターとして参加します。昨年の写真見てるとみんな良い笑顔でいらっしゃる今年はどんな感じになるか楽しみです
…(以下略)…

複数ページにまたがる場合にはこれをページ数ごとに行うことでまとめられたすべてを取得できます。

WordCloudでの処理

あとは文面を取得できたのでこれをWordCloudで処理させていけばOKです。 必要であれば以下のパッケージを事前にインストールしておいてください。

(venv) >pip install wordcloud
(venv) >pip install matplotlib
(venv) >pip install janome

WordCloudの事前処理

WordCloudで処理する前にJanome形態素解析を行います。 形態素解析をそのままやってしまうとノイズの多いデータになってしまうので、できるだけここでいらない語句は省くのがいい結果を得られるコツだと思います。

形態素解析の処理】

from janome.tokenizer import Tokenizer
import codecs

wakachi = ''

with codecs.open('./wakachi_log.txt', mode='w', encoding='utf-8') as fw:
    None

t = Tokenizer()
with open('hackchu2019_log.txt', 'r', encoding="utf-8") as f:
    for tweet in f:
        if tweet.startswith('#'):
            continue
        tweet = tweet.split('pic.twitter.com')[0].strip()
        tweet = tweet.split('ctv.co.jp')[0].strip()
        tweet = tweet.replace('#hackchu', '')
        # print(tweet)
        word_list = []
        tokens = t.tokenize(tweet)
        for token in tokens:
            word = token.surface
            word_base = token.base_form
            partOfSpeech = token.part_of_speech.split(',')[0]
            if token.base_form in ["ある", "なる", "こと", "よう", "そう",
                                   "これ", "それ", "する", "いる", "いい",
                                   "やる", "わかる","自分", "こちら","いう","サービス",
                                   "くる","いう","かける","行く","やつ","中京",
                                   "使える", "来る","ない","ww", "思う", "ハッカソン","予選",
                                   "見る", "持つ", "〇〇TV","チーム","TV"]:
                continue
            if partOfSpeech in ["形容詞", "動詞", "名詞", "代名詞", "副詞"]:
                if (partOfSpeech == "名詞"):
                    if (token.part_of_speech.split(',')[1] in ["数", "接尾", "助数詞", "非自立"]):
                        continue
                elif (partOfSpeech == "動詞"):
                    if (token.part_of_speech.split(',')[1] not in ["自立"]):
                        continue
                elif (partOfSpeech == "形容詞"):
                    if (token.part_of_speech.split(',')[1] not in ["自立"]):
                        continue
                elif (partOfSpeech == "副詞"):
                    if (token.part_of_speech.split(',')[1] in ["助詞類接続"]):
                        continue
                word_list.append(word_base)

        wakachi = " ".join(word_list)
        with codecs.open('./wakachi_log.txt', mode='a', encoding='utf-8') as fw:
            print(wakachi, file=fw)

この処理で以下のような形態素解析後の分かち書きされたテキストデータを得ることができます。

【wakachi_log.txt】

IBM テレビハッカソン HACK - CHU ! 応援
今週 土曜日 アイデアソン 天気 予報 雪 マーク 出る 当日 体調 整える 挑む
都内 雪 降る
今日 長い
今日 テレビ 主催 Hack - Chu ( 読み方 : ハックチュウ )」 スポンサーメンター 参加 昨年 写真 みんな 良い 笑顔 いらっしゃる 今年 感じ 楽しみ
テレビハッカソン HACK - CHU !」
…(以下略)…

あとはこの出力をWordCloudで処理させるだけです。

WordCloudでの処理

あとは、WordCloudで処理するだけです。 以下のコードで日本語のフォント指定をすれば無事に処理されます。

import os
from wordcloud import WordCloud
contents = open('wakachi_log.txt', encoding="utf-8").read()
fpath = 'C:\\Windows\\Fonts\\meiryo.ttc'
wordcloud = WordCloud(background_color="white", font_path=fpath, width=900, height=500).generate(contents)
wordcloud.to_file("./wordcloud.png")

処理後に以下のような画像データが表示されます。

f:id:ueponx:20190217022855p:plain

無事にデータが取得できました。

終わりに

Pythonを使ってスクレイピングするのもいいですが、Javascriptなどを実行しないと行けないような場合は単純な処理ではだめですが、 Google Chromeの検証機能を使えばあまり気にせずにスクレイピングを行い、該当のデータを取得することはできそうです。 どちらが手間かを考えて取捨選択していけばいいかなとは思いました。

ChromeOSにDockerをインストールしてみる

自分の中で旬になっているChromeOSネタです。 今回はChromeOSに折角入っているDebianがあるので、そこにDockerをインストールしてみたというものです。 Dockerがあれば、ある程度開発もできるかな?と。ただ、Dockerをあまり知らないのでこれからのお勉強になりますけどね。

Dockerのインストールを行う

ChromeOSにインストールされているのはDebianなので、Debianのインストールの手順を参考にしていきます。 Dockerのページに既にあるのでこれを参考にしてインストールをしていきます。

$ uname -a
Linux penguin 4.19.4-02480-gd44d301822f0 #1 SMP PREEMPT Thu Dec 6 17:45:27 PST 2018 x86_64 GNU/Linux

$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 9.7 (stretch)
Release:        9.7
Codename:       stretch

【参考】 docs.docker.com

手順としては

  1. 必要となるパッケージをインストール
  2. aptリポジトリへの追加の事前作業(apt-keyはパッケージを認証するのに使用するキーの一覧を管理するコマンドで、このキーで認証されたパッケージは信頼するできるものになります。)
  3. aptリポジトリへ追加
  4. aptリポジトリ更新(apt update
  5. aptリポジトリの追加
  6. dockerパッケージのインストール

公式ページの手順を参考にインストールを行っていきます。

$ sudo apt update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg2 \
    software-properties-common
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable"
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io

インストールができたか確認してみます。

$ sudo docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

f:id:ueponx:20190213223314p:plain

無事に動作しました!

インストールが終わったのでhttpサーバを起動してみる!

では、nginxのコンテナイメージを使ってhttpサーバーを起動してみます。 使用するコンテナは以下のものです。

hub.docker.com

では起動してみます。

$ docker run -d -p 8080:80 --name webserver nginx
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.39/containers/create?name=webserver: dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.

permissionエラーがでてしまいます。その他のコマンド(docker inforやdocker versionなど)でも同様のエラーがでてしまうので、一般ユーザーでもdockerを使用できるように設定をします。 permissionエラーの理由はDockerではUnixポートを使用していますが、このUNIXポートがrootユーザのみアクセスできるためというのが理由になります。 そのため、新たにdockerを使用するユーザーグループを作成し、そのグループに使用するユーザーを追加する必要があります。

公式ページにも一般ユーザーで使用するための設定方法が記述されています。

docs.docker.com

$ sudo groupadd docker
$ sudo usermod -aG docker $USER

公式ページにはコンソールのログアウトを行えばいいと記載されていましたが、実際にはログアウトした後再ログインする必要がありました。(コンソールからlogoutコマンドではだめでした) この部分は、ChromeOS固有の部分だと思います。

ログインしたあとにコンソールで先程エラーになっていたコマンドを実行してみると…

$ docker version
Client:
 Version:           18.09.1
 API version:       1.39
 Go version:        go1.10.6
 Git commit:        4c52b90
 Built:             Wed Jan  9 19:35:59 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.1
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       4c52b90
  Built:            Wed Jan  9 19:02:44 2019
  OS/Arch:          linux/amd64
  Experimental:     false

無事に動作するようになりました。

改めてnginxを使用してwebserverを起動します。その際、ポートフォワードをしてローカルからの8080へのアクセスをコンテナの80ポートにattachするようにしています。

$ docker run -d -p 8080:80 --name webserver nginx

オプション

  • --name 【使用したいイメージ名】 : 使用したいイメージ名を指定する
  • -d : コンテナ実行時にバックグラウンドで起動する
  • -p 【ホストのポート番号】:【コンテナのポート番号】 : ポートフォワード設定

イメージがない場合には自動的にダウンロードが行われます。

f:id:ueponx:20190213223644p:plain

docker psで確認するとコンテナの動作が確認できます。

f:id:ueponx:20190213223849p:plain

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

$ docker run -d -p 8080:80 --name webserver nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
6ae821421a7d: Pull complete 
da4474e5966c: Pull complete 
eb2aec2b9c9f: Pull complete 
Digest: sha256:dd2d0ac3fff2f007d99e033b64854be0941e19a2ad51f174d9240dda20d9f534
Status: Downloaded newer image for nginx:latest
59a28a1f0da119d574ecf910be18bbeebe32a5a0f86542d906b264e32ca40e26

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
59a28a1f0da1        nginx               "nginx -g 'daemon of…"   7 seconds ago       Up 3 seconds        0.0.0.0:8080->80/tcp   webserver

docker psコマンドで動作を確認できていますが、実際にこのコンテナへWebブラウザからアクセスを行います。ポートフォワードの設定を行っているのでローカルの8080ポートへアクセスします。

f:id:ueponx:20190213223914p:plain

問題なくアクセスできるようになりました。

おわりに

ChromeOSにもDockerは動作できました。今回は非力なPCなので重たい処理はさせられませんが、 Webのチェックなどでは使用できないこともなさそうです。

ここまでで、Chrome拡張でVNCの動作、Linuxのコンテナ内でのNode.js、Python、Docker、Visual Studio Codeまでインストール・動作確認できているので ライトな開発環境としてもわりと本格的に考えてもいいのかなと思いはじめています。あとはBonjour(Avahi)が使えると本当にいいのですけど…

【関連記事】

uepon.hatenadiary.com

uepon.hatenadiary.com

Word2vecで遊んでみた

今年の大きめの仕事が一段落ついた(本当は来月までやる)こともあり、時間があったのでちょっと触ってみましたというエントリーです。

年末ぐらいからWord2vecを使ってみたいなあとは思っていたのですが、なかなか手をつけられませんでしたがようやく手をつけることができました。

Word2vecとは…

en.wikipedia.org

ということです。よくわかっていない…

なんとなく大量のテキストデータを解析し、各単語の意味をベクトル表現化し、コーパス内の単語同士の意味の近さを求めたり、 単語同士の意味を演算ができるようにするものなのかなと思います。ここでいう意味というのは一般的な言葉で言う意味とは少し違う 概念(概念的な近さ?)だと思ったほうがいいのかもしれません。ちなみにコーパスはテキストや発話を大規模に集めてデータベース化した言語資料されたものをいうようです

とはいっても、まずは触ってみたほうがいいので

f:id:ueponx:20190210115552p:plain

って感じで使ってみることにします。以下にとてもよいエントリーがあったので参考にしました。

【参考】 qiita.com

参考にしたエントリーは青空文庫に入っているデータを取得しコーパスとして使用していますが、そんな高尚なことにあまり興味がないので、今回は平成仮面ライダー20周年というメモリアルイヤーでもあるので、Wikipediaにある平成仮面ライダーの情報をコーパスとして取得していろいろ遊んで見ようと思います。

Word2vecの使い方は以下のような手順になると思います。

  1. コーパスとなるデータの取得(大規模なテキストデータ)
  2. 取得されたテキストデータの形態素解析を行い単語単位で取得
  3. Word2vecの処理を行い、単語のベクトル化
  4. ベクトル化されたデータを元に行いたい演算を行う

これが簡単な手順になるかと思います。 単語のベクトル化はかなりの計算量があるのでRaspberryPiなどではかなり時間がかかる処理になります。可能であればPCやクラウドのマシンパワーで なんとかしたほうがいいかなと思います。参考にしたエントリーではIBM Cloudを使用しているのでかなり理にかなった感じの処理になっているかなと思います。 ただJupyter Notebook経由でのテキストデータの処理に関しては少し癖があるように感じたので、自分は手元にあるPCを使用しました。 (ベクトル化されたデータは保存して再利用可能なので別の処理系で演算することは可能です。)

では進めてみます。

今回は

  • テキストの取得処理に関しては…requestsBeautifulSoup
  • 形態素解析には…janome
  • ベクトル化には…word2vec

を使用しています。インストールされていない場合にはpipでモジュールのインストールを行いましょう。

$ pip install requests
$ pip install beautifulsoup4
$ pip install janome
$ pip install word2vec

Wikipediaからデータを取得する

ホントはこういうやり方はあまりオススメしないのですが(Wikipediaに不要なアクセスが増えるので本来であればDBをローカルに持ってくるのが望ましい) この処理は機械的にやるのではなく、ちょっと使う程度で控えましょう。

requestsモジュールでデータを引っ張ってきたHTMLファイル内にある

タグの中身をBeautifulSoupで取得します。

【getWikipedia.py】

import requests
from bs4 import BeautifulSoup

link = "https://ja.wikipedia.org/wiki/"
keyword = ["仮面ライダークウガ", "仮面ライダーアギト", "仮面ライダー龍騎", "仮面ライダー555", "仮面ライダー剣",
           "仮面ライダー響鬼", "仮面ライダーカブト", "仮面ライダー電王", "仮面ライダーキバ", "仮面ライダーディケイド",
           "仮面ライダーW", "仮面ライダーオーズ/OOO", "仮面ライダーフォーゼ", "仮面ライダーウィザード", "仮面ライダー鎧武/ガイム",
           "仮面ライダードライブ", "仮面ライダーゴースト", "仮面ライダーエグゼイド", "仮面ライダービルド", "仮面ライダージオウ"]

for word in keyword:
    with requests.get(link + word) as response:
        # responseはhtmlのformatになっている
        html = response.text
        soup = BeautifulSoup(html, "lxml")
        # <p>タグを取得
        p_tags = soup.find_all('p')
        print(p_tags)
        print('----')

以下のような感じデータが取得されます。

> python getWikipedia.py
[<p class="mw-empty-elt">
</p>, <p><b>仮面ライダークウガ</b>』(かめんライダークウガ)は、<a href="/wiki/2000%E5%B9%B4" title="2000年">2000</a><a href="/wiki/%E5%B9%B3%E6%88%90" title="平成">平成</a>12年)<a href="/wiki/1%E6%9C%8830%E6%97%A5" title="1月30日">130</a>から<a href="/wiki/2001%E5%B9%B4" title="2001年">2001</a>(平成13年)<a href="/wiki/1%E6%9C%8821%E6%97%A5" title="1月21日">121</a>まで、<a href="/wiki/%E3%83%86%E3%83%AC%E3%83%93%E6%9C%9D%E6%97%A5" title="テレビ朝日">テレビ朝日</a>系で毎週日曜8:00 - 8:30<a href="/wiki/%E6%97%A5%E6%9C%AC%E6%A8%99%E6%BA%96%E6%99%82" title="日本標準時">JST</a>)に全49話が放映された、<a href="/wiki/%E6%9D%B1%E6%98%A0" title="東映">東映</a>制作の<a href="/wiki/%E7%89%B9%E6%92%AE%E3%83%86%E3%83%AC%E3%83%93%E7%95%AA%E7%B5%84%E4%B8%80%E8%A6%A7" title="特撮テレビ番組一覧">特撮テレビドラマ</a>作品。

(中略)

</p>, <p>監督は本編チーフ助監督の大峯靖弘が、台本は東映プロデューサーの白倉伸一郎がそれぞれ担当した<sup class="reference" id="cite_ref-U16344_141-3"><a href="#cite_note-U16344-141">[84]</a></sup>。大峯はチーフ助監督としてスケジュール管理も行っていたことから、本編撮影の合間を縫って短時間で撮るという体制であった<sup class="reference" id="cite_ref-U16344_141-4"><a href="#cite_note-U16344-141">[84]</a></sup>。第4.5話の飯島寛騎と瀬戸利樹は別日に撮影しており、編集で共演しているように演出している<sup class="reference" id="cite_ref-U16344_141-5"><a href="#cite_note-U16344-141">[84]</a></sup>。第13.5話で使用しているユルセンのぬいぐるみは大峯の私物である<sup class="reference" id="cite_ref-U16344_141-6"><a href="#cite_note-U16344-141">[84]</a></sup></p>]
----

HTMLのタグが結構はいっているのでもう少しクレンジングをしたほうがいいのかなと思いますが今回はこのまま使用します。

続いては形態素解析を行います。

janomeによる形態素解析

取得されたデータをjanomeモジュールを使用して形態素解析を行います。

janomeに関しては以前のエントリーで触れているので参考にします。

【参考】 uepon.hatenadiary.com uepon.hatenadiary.com

先程、取得できたデータを形態素解析していきます。 形態素解析を行った結果はpwiki.txtというテキストファイルに入れて、以降はWebアクセスなしでも後続の処理ができるようにしています。

【getWiki2wakachi.py】

from janome.tokenizer import Tokenizer
import requests
from bs4 import BeautifulSoup
import codecs

link = "https://ja.wikipedia.org/wiki/"
keyword = ["仮面ライダークウガ", "仮面ライダーアギト", "仮面ライダー龍騎", "仮面ライダー555", "仮面ライダー剣",
           "仮面ライダー響鬼", "仮面ライダーカブト", "仮面ライダー電王", "仮面ライダーキバ", "仮面ライダーディケイド",
           "仮面ライダーW", "仮面ライダーオーズ/OOO", "仮面ライダーフォーゼ", "仮面ライダーウィザード", "仮面ライダー鎧武/ガイム",
           "仮面ライダードライブ", "仮面ライダーゴースト", "仮面ライダーエグゼイド", "仮面ライダービルド", "仮面ライダージオウ"]

corpus = []
wordslist = []
t = Tokenizer()
for word in keyword:
    with requests.get(link + word) as response:
        # responseはhtmlのformatになっている
        html = response.text
        soup = BeautifulSoup(html, "lxml")
        # <p>タグを取得
        p_tags = soup.find_all('p')
        for p in p_tags:
            tokens = t.tokenize(p.text)
            for token in tokens:
                # print("表層形:",token.surface,"\n"
                #       "品詞:",token.part_of_speech.split(',')[0],"\n"
                #       "品詞細分類1:",token.part_of_speech.split(',')[1],"\n"
                #       "品詞細分類2:",token.part_of_speech.split(',')[2],"\n"
                #       "品詞細分類3:",token.part_of_speech.split(',')[3],"\n"
                #       "活用型:",token.infl_type,"\n"
                #       "活用形:",token.infl_form,"\n"
                #       "原形:",token.base_form,"\n"
                #       "読み:",token.reading,"\n"
                #       "発音:",token.phonetic)
                word = ''
                if (token.part_of_speech.split(',')[0] in ['代名詞', '名詞', '固有名詞', '動詞', '形容詞', '形容動詞']) and \
                    (token.part_of_speech.split(',')[1] not in ['数','自立', 'サ変接続', '非自立', '接尾', '副詞可能']) and \
                    (token.base_form not in ['これら', 'せる', 'これ']):
                            word = token.base_form
                            wordslist.append(word)
        corpus.append(wordslist)
        # print(corpus)

with codecs.open("pwiki.txt", "w", "utf-8") as f:
    f.write(str(corpus))

プログラム内で以下のような処理を行っていますがが、明らかに不要(解析が難しい数詞や接尾などの単語)やで代名詞のこれなどの単語に関しては コーパスに入らないようにしています。

                word = ''
                if (token.part_of_speech.split(',')[0] in ['代名詞', '名詞', '固有名詞', '動詞', '形容詞', '形容動詞']) and \
                    (token.part_of_speech.split(',')[1] not in ['数','自立', 'サ変接続', '非自立', '接尾', '副詞可能']) and \
                    (token.base_form not in ['これら', 'せる', 'これ']):
                            word = token.base_form
                            wordslist.append(word)

テキストデータによってはこのような処理も必要かと思います。出来上がったファイルを見ると

【pwiki.txt】

仮面 ライダークウガ ライダークウガ 平成 月 平成 月 テレビ朝日 JST 東映 特撮 テレビ ドラマ 作品
A New Hero A New Legend 英雄 伝説 OP 最後 タイトル 左上 右
テレビ シリーズ 仮面ライダー BLACK RX テレビ シリーズ 仮面ライダー J 仮面ライダー 作品 平成 仮面ライダー シリーズ クウガ 漢字 空 我 名 漢字 名前 石森 プロ 社長 小野寺 章 クワガタ 語感
昭和 仮面ライダー シリーズ 昭和 ライダー 世界 昭和 ライダー オマージュ 台詞 随所 注 昭和 ライダー 違い 仮面ライダー 怪人 人間 世界 悪 秘密 結社 注 劇 仮面ライダー 名称 人間 医療 技術 臓器 人間 東映 人間 影 主人公 平成 ライダー シリーズ
作品 特撮 ヒーロー 番組 新た 試み 随所 身近 現実 特撮 ヒーロー 番組 グロンギ 独自 言語 文化 クウガ 警察 技 作 劇 スポット 回 周囲 人々 社会 ヒーロー 悪 過程 ヒーロー ドラマ 視点 一般 ドラマ 視点 エピソード 基本 エピソード スタイル スタイル 作品
商業 ベルト 人気 好成績 ドラマ 作 劇 シーン 回 月 クウガ 最終 形態 アルティメットフォーム 雄介 幻影 月 最終 直前 作中 注 出番 逆 スポンサー 玩具 会社 形態 アメイジングマイティ 商品 販促 番組 異例 め 最終 A パート B パート 間 CM ED 主役 ヒーロー シーン 主人公 五代 雄介 出番 注

(以下略)

いい感じで出力されています。

形態素解析を行ったあとのコーパスからWord2vecのモデルを生成する

pwiki.txtを使用してモデルを生成します。

モデルの生成はword2vecモジュールのgensim.modelsを使用します。 Word2vecを使用すると意外とたくさんWarningが発生するので、問題がなさそうだったら冒頭にwarningsモジュールをimportして抑止すると見やすくなります。

【wakachi2model.py】

import warnings
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')
warnings.filterwarnings(action='ignore', category=FutureWarning)
from gensim.models import word2vec
import codecs

corpus = word2vec.LineSentence("pwiki.txt")
model = word2vec.Word2Vec(corpus, size=100 ,min_count=5,window=5,iter=100)
print(model)
model.save("pwiki.model")

これでモデル(pwiki.model)が生成されました。このモデルファイルがあれば再度データの取得など行わず、すぐに演算を行うことができます。

モデルを使用して演算を行う

以下のようにすれば類似度のランキングや2つのキーワードの類似度を見ることができます。

【oprateWord2vec.py】

import warnings
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')
warnings.filterwarnings(action='ignore', category=FutureWarning)
from gensim.models import word2vec

model = word2vec.Word2Vec.load("pwiki.model")

# ドライバーと類似している単語を見る
print('ドライバーと関連する単語ベスト10')
similar_words = model.wv.most_similar(positive=[u"ドライバー"], topn=10)
for key,value in similar_words:
    print('{}\t\t{:.2f}'.format(key, value))

print('-----')
# 2つの単語の類似度を計算
similarity = model.wv.similarity(w1=u"クウガ", w2=u"アギト")
print('クウガとアギトの類似度=>' + str(similarity))

similarity = model.wv.similarity(w1=u"ショッカー", w2=u"ディケイド")
print('ショッカーとディケイドの類似度=>' + str(similarity))

similarity = model.wv.similarity(w1=u"ジオウ", w2=u"ディケイド")
print('ジオウとディケイドの類似度=>' + str(similarity))

このような演算を行うと以下の様な結果が得られます。

Word2Vec(vocab=1819, size=100, alpha=0.025)
ドライバーと関連する単語ベスト10
凌     0.98
ヘルヘイム     0.96
戒斗      0.96
ゲネシスドライバー     0.96
戦     0.96
アーマードライダー     0.95
森     0.95
紋     0.95
不能      0.94
果実      0.94
-----
クウガとアギトの類似度=>0.890038
ショッカーとディケイドの類似度=>0.70078796
ジオウとディケイドの類似度=>0.8640115

上記のような値がでました。

考察

  • ドライバーという単語に近い意味を持つ単語は鎧武ってこと?…人数が多くてドライバーの種類も多かったということなんでしょうか?
  • クウガとアギトの類似度は結構高いようです…ストーリーでもそういう雰囲気はありましたね~
  • ショッカーとディケイドは近いけどそこまでではない?…アポロガイストあたりの影響かな?
  • ジオウとディケイドの類似度はまあ高い…お祭りライダーだからかも?ディケイドがジオウにでているのもあるかな。

なんとなく面白いデータが取れたような気がします。こういうのを考えてみるのもわりと面白いですねえ。

今回のコードをまとめたものを以下においておきます。

import warnings
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')
warnings.filterwarnings(action='ignore', category=FutureWarning)
from gensim.models import word2vec
from janome.tokenizer import Tokenizer
import requests
from bs4 import BeautifulSoup
import codecs

# https://www.pytry3g.com/entry/gensim-word2vec-tutorial

link = "https://ja.wikipedia.org/wiki/"
keyword = ["仮面ライダークウガ", "仮面ライダーアギト", "仮面ライダー龍騎", "仮面ライダー555", "仮面ライダー剣",
           "仮面ライダー響鬼", "仮面ライダーカブト", "仮面ライダー電王", "仮面ライダーキバ", "仮面ライダーディケイド",
           "仮面ライダーW", "仮面ライダーオーズ/OOO", "仮面ライダーフォーゼ", "仮面ライダーウィザード", "仮面ライダー鎧武/ガイム",
           "仮面ライダードライブ", "仮面ライダーゴースト", "仮面ライダーエグゼイド", "仮面ライダービルド", "仮面ライダージオウ"]

corpus = []
t = Tokenizer()
for word in keyword:
    with requests.get(link + word) as response:
        print(link + word)
        # responseはhtmlのformatになっている
        html = response.text
        soup = BeautifulSoup(html, "lxml")
        # <p>タグを取得
        p_tags = soup.find_all('p')
        for p in p_tags:
            r = []
            tokens = t.tokenize(p.text)
            for token in tokens:
                # print("表層形:",token.surface,"\n"
                #       "品詞:",token.part_of_speech.split(',')[0],"\n"
                #       "品詞細分類1:",token.part_of_speech.split(',')[1],"\n"
                #       "品詞細分類2:",token.part_of_speech.split(',')[2],"\n"
                #       "品詞細分類3:",token.part_of_speech.split(',')[3],"\n"
                #       "活用型:",token.infl_type,"\n"
                #       "活用形:",token.infl_form,"\n"
                #       "原形:",token.base_form,"\n"
                #       "読み:",token.reading,"\n"
                #       "発音:",token.phonetic)
                word = ''
                if (token.part_of_speech.split(',')[0] in ['代名詞', '名詞', '固有名詞', '動詞', '形容詞', '形容動詞']) and \
                    (token.part_of_speech.split(',')[1] not in ['数','自立', 'サ変接続', '非自立', '接尾', '副詞可能']) and \
                    (token.base_form not in ['これら', 'せる', 'これ']):
                            r.append(token.base_form)
            rl = (' '.join(r)).strip()
            corpus.append(rl)
            # print(corpus)

with codecs.open("pwiki.txt", "w", "utf-8") as f:
    f.write("\n".join(corpus))

corpus = word2vec.LineSentence("pwiki.txt")
model = word2vec.Word2Vec(corpus, size=100 ,min_count=3,window=5,iter=30)
print(model)
model.save("pwiki.model")

model = word2vec.Word2Vec.load("pwiki.model")

# ドライバーと類似している単語を見る
print('ドライバーと関連する単語ベスト10')
similar_words = model.wv.most_similar(positive=[u"ドライバー"], topn=10)
for key,value in similar_words:
    print('{}\t\t{:.2f}'.format(key, value))

print('-----')
# 2つの単語の類似度を計算
similarity = model.wv.similarity(w1=u"クウガ", w2=u"アギト")
print('クウガとアギトの類似度=>' + str(similarity))

similarity = model.wv.similarity(w1=u"ショッカー", w2=u"ディケイド")
print('ショッカーとディケイドの類似度=>' + str(similarity))

similarity = model.wv.similarity(w1=u"ジオウ", w2=u"ディケイド")
print('ジオウとディケイドの類似度=>' + str(similarity))

RaspberryPiでNFCをトリガーにしてサーボモーターを駆動する

フェリーハッカソンでできなかったことをやってみる

以前参加した、フェリーハッカソンでは、QRコードを読み取ってサーボモーターの駆動をしていました。 今回はNFCのリーダーを使用してサーボモーターを駆動させてみたいと思います。時間が余っていればやりきりたかった。

【参考】 uepon.hatenadiary.com

若干異なる点としてはpythonnfcのモジュールが2.7系にまでにしか対応していない点が挙げられます。 とはいえ、今回使用しているRPiのモジュールは2系でも3系でも大きな差がなく使用することができるので 大丈夫ではないかなと。だめであればそれも含めて調査する方向でやっていこうと思います。

nfcモジュールに関して

pythonで使用できるnfcモジュールを使用してトリガーを取得していきたいと思います。

以前も使用しているので細かい部分はそちらをご参考にお願いします。

【参考】

uepon.hatenadiary.com

基本的にはnfcモジュールイベントハンドラを使用して、ループさせ、ReaderからIDmが取得できた場合にサーボ制御を行うものになります。 特に組み合わせれば難しくないかなと思います。こちらの処理は以下のような動きをします。

  1. nfcリーダーでFelicaに含まれたIDmの読み込み待ちをする。(ループ)
  2. IDmが認識できたら、サーボモーターを制御する(鍵を開ける)
  3. 鍵を開けた状態で10秒間ウエイトを行う
  4. サーボモータを再度制御する(鍵を閉める)

コード書いてみた

今回のコードではGPIO4でサーボモータを制御、GPIO17でLEDの制御を行っています。

f:id:ueponx:20190203232411j:plain

import nfc
import binascii
import RPi.GPIO as GPIO
import time

class NFCReader(object):
    def on_connect(self, tag):
        print("touched")
        self.idm = binascii.hexlify(tag.idm)
        return True

    def read_id(self):
        clf = nfc.ContactlessFrontend('usb')
        try:
            clf.connect(rdwr={'on-connect': self.on_connect})
        finally:
            clf.close()

if __name__ == '__main__':
    GPIO.setmode(GPIO.BCM)
    gp_out = 4
    gp_led = 17
    GPIO.setup(gp_out, GPIO.OUT)
    GPIO.setup(gp_led, GPIO.OUT, initial=GPIO.LOW)
    servo = GPIO.PWM(gp_out, 50)

    reader = NFCReader()
    while True:
        print("touch card:")
        reader.read_id()
        print("released")
        print(reader.idm)

        GPIO.output(gp_led, GPIO.HIGH)

        servo.start(0.0)
        servo.ChangeDutyCycle(2.5)
        time.sleep(0.5)
        servo.stop()

        time.sleep(10.0)

        servo.ChangeDutyCycle(7.5)
        time.sleep(0.5)
        servo.stop()

        GPIO.output(gp_led, GPIO.LOW)

        # GPIO.cleanup()

今回はnfcの処理の部分は汎用性をもたせるためにクラス化しています。 また、特定のIDmで開けるといった処理はしていません。リーダーで何らかのデータを読み込めた場合には判断なく処理をする形にしています。 割と簡単にできたなと思います。

おわりに

ある程度組み合わせればなんかできそうなことが増えてきました。今回も2時間もかからず出来上がった感じでした。

できれば、nfcモジュールがそろそろPython3に対応してもらえると…淡い希望でした。

Chrome OS(Chromium OS)にVisual Studio Codeをインストールしてみた

Chrome OSとはいってますけど、Chromium OSの話になります。まあ、純正のChromebookを持っている人にはあんまり関係ない話。

昨年の年末、以前までChromeOSを使用していたノートPCがある日突然電源が入らなくなり、突然のお別れということになってしまった。購入からすでにもう10年ぐらい経っているCeleronなPCなのでそろそろ動作しなくなってもおかしくないので、このときが来たかというレベルでしかなかったです。

Aspire one 753(2010年製) http://www2.acer.co.jp/catalog/1012/FIX_NBALL_0616.pdf

いよいよ廃棄するにあたって、最後に電源でもいれてみるかなと思ったら突然電源が復帰。あれーって感じ。ただ、Windows10Homeは立ち上がらず、シリアルも探さなければならないという状況。結論としてクリーンインストールが必要という状態でした。さすがにWindows10ではパワー不足というのはわかっていたので、別のOSをいれてもいいかなと。候補としてはUbuntuChrome OSを考えました。この2つのOSはUSBメモリでの起動であっても、実用面でも全然問題ないことはわかっていたので、もう好みでしかないかなと。

uepon.hatenadiary.com

前回、USBメモリ起動で設定したのエントリーを書いたときにChrome OSの最新ビルドではLinuxのコンソールが使用可能になったらしいという噂は聞いていたのですが、使用したイメージではちょっと古いもの(CloudReadyのイメージは追いかけるスタイルなので当然といえば当然)だったので、その設定項目はありませんでした。まあ、最新のビルドを追っていくほどの気合がなかっったのでこういうのは仕方ないですけど。

しかしあれから半年ぐらいたったのでそろそろChrome OSを改めてインストールするのもいいかなと。Windows10のHDD温存という意味でのUSBブートにそこまでこだわりがなくなったので、今回はSSDChrome OSをインストールすることにしました。 それだけではブラウジングしかできない感じなのでVisualStudio Code(以降VSCode)をインストールして文書をかけるようなPCへ設定していこうと思います。

USBでインストールメディアを作成する

まずはインストールをするメディアを作成します。

基本的には以前書いたエントリーと同じように作成すればOKです。

【参考】 uepon.hatenadiary.com

今回の手順としては

  1. イメージファイルをダウンロードし、USBメモリに書き込み
  2. USBメモリをPCに挿して、PCを起動する
  3. USBメモリから内蔵ディスクにインストール
  4. Chrome OSLinuxコンテナを有効化
  5. VScodeのインストール
  6. 日本語表示・入力の設定

イメージファイルをダウンロードし、USBメモリに書き込み

CloudReadyのイメージをダウンロード

今回も使用するのはNeverware社が製品化しているChromium OSとなります。個人利用は無料なのでビジネス用途、教育用途でなければ大丈夫です。

www.neverware.com

f:id:ueponx:20190202224037p:plain

USBメモリは以下のものを使用していますが、16GBぐらいの容量のものを使えば大丈夫だと思います。

今回使用するイメージは【GET THE FREE VERSION】ボタンを押した先にある

f:id:ueponx:20190202224344p:plain

【DOWNLOAD 64-BIT】ボタンをクリックするとダウンロードできるものを使用します。

f:id:ueponx:20190202224616p:plain

Zipファイルなので伸張してからUSBメモリに書き込みを行います。

USBメモリへの書き込み

書き込みアプリはNeverwareのホームページ内のStep2にあるUSBMakerを使用してもいいと思いますが、私は前回同様にEtcherを使用しました。

www.balena.io

最新のEtcherの見た目のイメージが結構かわっちゃいましたね。

【起動画面】 f:id:ueponx:20190202203235p:plain

【イメージファイルの指定とUSBドライブの選択】 f:id:ueponx:20190202203057p:plain

【書き込み中】 f:id:ueponx:20190202203117p:plain

【完了】 f:id:ueponx:20190202203125p:plain

これで準備完了です。

USBメモリをPCに挿して、PCを起動する

このあたりは問題はないと思います。

起動するとこんな画面になります。まずはここで言語とキーボードの選択をしていきます。【English(United States)】と書いてある左側のボタンをクリックします。

f:id:ueponx:20190202215519j:plain

言語、キーボードを日本語に設定します。設定が終わったら【OK】ボタンをクリックします。

f:id:ueponx:20190202215535j:plain

画面が戻ると選択した言語で表示されるようになります。【続行】ボタンをクリックします。

f:id:ueponx:20190202215610j:plain

次はネットワークの設定になります。ここで接続するネットワークを指定します。WiFiの場合にはSSIDとパスワードを入力していくことになります。

f:id:ueponx:20190202215903j:plain

ネットワーク設定が終わるとデータ取得の許諾画面になりますが、チェックするかどうかは個人のポリシーでってところでしょうか。【Continue】ボタンをクリックします。

f:id:ueponx:20190202215933j:plain

最後はChromeOSでログインするGoogleのアカウントの登録をします。メールアドレス、パスワードなどを使ってログインをします。(2段階認証の方はその処理もここで行われます)

f:id:ueponx:20190202215937j:plain

これが終わると設定が完了となります。

f:id:ueponx:20190202215941j:plain

SSDであればイメージのダウンロードを含めても1時間以内で終わるかなという印象です。

USBメモリから内蔵ディスクにインストール

USBから起動すると起動後のメニューに内蔵ディスクへのインストールが表示されるので、それを選択してインストールを行っていきます。

画面の右下のバーをクリックするととその中にInstallOSというボタンがあるのでクリックします。

f:id:ueponx:20190202215946j:plain

いろいろと確認がでるので画面に従っていきます。

f:id:ueponx:20190202215952j:plain

少し時間がかかりますが終了すると電源がOFFされるので頬っておきましょう。 これでインストール開始となります。

インストールしたPCの起動

USBをコネクタから抜いてPCを起動します。 起動するとUSB起動と同様の設定を行うことになります。ここまでくると説明はなくてもいいかなと。

すべて終わると作業はほぼ終了になります。

f:id:ueponx:20190202234548p:plain

起動したらタイムゾーンだけは直しておいたほうがいいかなと思います。 【設定】の画面で日時を選択すればタイムゾーンを変更できます。

f:id:ueponx:20190202234411p:plain

インストール後の設定

Linuxのコンテナ機能を使えるようにする

続いてはLinuxのコンテナが使えるように設定を行って行きます。 この機能はまだベータ版らしいのですが特に問題はなさそうです。

【設定】の画面のなかからLinuxの項目までスクロールさせて、

f:id:ueponx:20190202234438p:plain

【オンにする】ボタンで機能を有効にすることができます。

f:id:ueponx:20190202234457p:plain

再度インストール確認のダイアログが表示されるので【インストール】ボタンをクリックします。

f:id:ueponx:20190203165608p:plain

これでChromeOSのLinuxコンテナがインストールされます。

f:id:ueponx:20190202235643p:plain

インストールが終わるとコンソールが開きます。

f:id:ueponx:20190202235701p:plain

これで使用できるようにはなりますが、念の為パッケージなどのアップデートは行っておいたほうがいいかなと思います。

Linuxコンテナのバージョンなどを見てみると…

hoge@penguin:~$ uname -a
Linux penguin 4.19.4-02480-gd44d301822f0 #1 SMP PREEMPT Thu Dec 6 17:45:27 PST 2018 x86_64 GNU/Linux

hoge@penguin:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 9.7 (stretch)
Release:        9.7
Codename:       stretch

Debianであることがわかるので、念の為にaptのアプデートやパッケージのアップグレードはしておいたほうがよいでしょう。

hoge@penguin:~$ sudo apt update
hoge@penguin:~$ sudo apt upgrade

pythonのバージョンは3.5ぐらいが入っていますが、あとはvimなどが入っているかなっと言う程度のレベルでしかありません。 node.jsぐらいはインストールしておいてもいいかなという感じでしょうか。(図らずもnode.jsのインストールを行うと、python2.7もインストールされます)

Visual Studio Codeをインストールし、日本が入力ができるようにする

大きくわけて2つの設定が必要になります。まずはVisual Studio Codeをインストールし設定を行う部分。もう一点は日本語入力を行う設定。 Linuxコンテナでも日本語入力を行うことができるのに、なぜ日本語設定が必要になるかというと、Linuxコンテナ上で起動したアプリケーションでは 日本語の入力がサポートされていないので、そのために別途、入力メソッドと日本語変換システムの橋渡しが必要になります。

Visual Studio Codeをインストールする

基本的には以下のリンク先の操作を行えば問題なくインストールができました。

code.visualstudio.com

まずはこちらからdeb形式のパッケージをダウンロードしaptコマンドでインストールを行います。deb形式だからdpkgかなとも思いますが、 aptで大丈夫です。aptを使用すればパッケージの依存関係も解決してくれます。

code.visualstudio.com

今回ダウンロードしたファイルはcode_1.30.2-1546901646_amd64.debだったので以下のようにインストールを行います。(2019.02.01現在)

f:id:ueponx:20190203161604p:plain

hoge@penguin:~$ sudo apt install ./code_1.30.2-1546901646_amd64.deb

インストールが終わるとコンソール上からはcodeコマンドで実行することができます。

f:id:ueponx:20190203161451p:plain

ランチャーにも登録されています。

f:id:ueponx:20190203161408p:plain

一応、起動はしますが、日本語の表示などに関しては完全にアウトです。日本語が含まれた文字列をペーストすると、フォントがないよんみたいな表示で残念な気持ちになります。

f:id:ueponx:20190203162001p:plain

日本語関連の設定

以下を参考にさせていただきました。

www.taneyats.com

qiita.com

大変助かりましたありがとうございました。

日本語の表示

先程の日本語が表示されていない問題は単に日本語フォントがないというだけの問題です。フォントをインストールさえすれば問題なく表示されます。 Chrome OS側は日本語表示されるのに?というのはありますが、Linuxコンテナから起動されるものは別の扱いがされるということなので諦めるしかないかなと。 ファイルシステムも別れてはいますが、シームレスではないもののマイファイルを表示するとLinuxファイルという形で共有ができるようになっているので、 そのうちシームレスな連携ができるようになるのかなと思います。(Windows Subsystem for Linuxって今どうなってるんでしたっけ?最近使ってないのでよくわからない)

この状態が

f:id:ueponx:20190203162001p:plain

フォントのインストールを行うと表示は解決します。フォントのインストール後にVSCodeを再起動すればOKです。

hoge@penguin:~$ sudo apt install fonts-noto

f:id:ueponx:20190203162315p:plain

一応表示に関してはこれで問題なくなりましたが、やっぱり入力できないとあんまりうれしくない。(この状態でペーストには対応しています。)

日本語入力の設定をする

今回は、入力メソッドにはfcitxを、日本語入力システムにはmozcを使用します。

hoge@penguin:~$ sudo apt install -y fcitx-mozc

インストールしたら動作確認してみます。

hoge@penguin:~$ fcitx -v
fcitx version: 4.2.9.1

正常にインストールできているようです。あとはfcitxmozcとの連携の設定になります。

設定するときによく忘れるのですが、まずランチャーからfcitxを起動します。起動してるぜーってくるくる回るアイコン表示してますが、そのまま次の作業にはいって大丈夫です。

f:id:ueponx:20190203162946p:plain

起動したら設定ツールを起動します。このツールでfcitxmozcを連携させていくことになります。

hoge@penguin:~$ fcitx-configtool

設定ツールが起動したらウインドウの下にある【+(プラス)】ボタンをクリックします。

f:id:ueponx:20190203170716p:plain

すると追加設定のダイアログが表示されるので

f:id:ueponx:20190203170846p:plain

検索の入力ボックスにmozcと入力し、【Only Show Current Page】チェックボックスを外すと【Mozc-Japanese】という候補が現れます。

f:id:ueponx:20190203171121p:plain

リストからそれを選択して【OK】ボタンをクリックします。

f:id:ueponx:20190203174134p:plain

リストが以下のようになればOKです。

f:id:ueponx:20190203174911p:plain

続いてフォントの設定になります。ウインドウの上の方にある【Appearance】タブをクリックします。 この画面ではフォントの設定や起動キーの設定ができます。

f:id:ueponx:20190203191711p:plain

この中から【Font】と【Menu Font】をクリックしてフォントの選択を行います。 フォント選択のダイアログが表示されたらサーチの入力ボックスにNoto Sans CJK JPといれると絞り込みができます。

f:id:ueponx:20190203191922p:plain

これでOKです。

最後に~/.profilefcitxの起動の設定行います。

hoge@penguin:~$ vim ~/.profile 

以下を追加します。

fcitx > /dev/null 2>&1

これで設定は完了です。

ではVSCodeを起動して確認をしてみます。日本語変換の起動は【Ctrl + Space】となります。 無事に起動すると以下のような画面で変換候補が表示されます。

f:id:ueponx:20190203192509p:plain

ただ、これにも問題があってLinuxコンテナでのアプリケーションの設定は起動時に反映されないので、 Linuxコンテナの起動(シェルの起動)に合わせて設定が行われます。(VSCodeは直接起動できるにもかかわらず) なので、VSCodeを起動直後に起動しても日本語入力はできません。シェルを起動すると(.profileに設定を記載しているので当然ですが) fcitxが起動して日本語変換行えるようになります。そのうち、こういう部分も直っていくような気がしますけどね。

おわりに

ChromeOSVSCodeをつかって日本語入力までできるようになりました。Pythonの開発やnode.jsぐらいであれば10年落ちのPCでもいけるかもしれませんね。 Chrome拡張も割と快適に動くものが多いので文書書きの機能であればわりといい感じです。(このエントリーは画像以外の部分はChromeOSyoutubeを見ながら書いています。) 以前のエントリーでもべた褒めだったのですが、今回も非常にいい印象を受けました。(まだまだという部分ももちろんありますが。)

/* -----codeの行番号----- */