Windows7環境なのにdocker入れて開発することになった話【システム構成編】
Windows7環境なのにdocker入れて開発することになった話【システム構成編】:
技術バリバリの人「さて、環境の構築も終わったし、何やろうか」
わたし「全くイメージ沸きません」
技術バリバリの人「もうちょっと考えてみてくれよ...」
わたし「...」
わたし「あ、そういえば最近変えたスマホに、『今日あなたが見るべきホームページトップ10!』みたいな機能があるんです。しかも結構興味がある内容で、ついつい見ちゃうんですよね。どういう仕組みなんでしょうか」
技術ばりばりの人「ちなみにどんなサイトが上がってくるの?」
わたし「好きなアーティストとか、最近の技術系のニュース記事とかですね」
技術ばりばりの人「なるほどね。それはターゲティング広告の一種だね。ホームページの閲覧履歴から分析をして、『おそらく関連がありそうだ』というサイトを検索しているんだね」
技術バリバリの人「おもしろそうだね、僕らも似たようなことをやってみようか。社内や仲間内に展開できる、『今日見るべきニューストップ10!』なんてのはどうかな」
わたし「確かに、これだけ多くのニュース媒体がある中で、読みたいニュースを教えてくれると助かりますね。全部読むのは無理だし」
技術バリバリの人「よし分かった。じゃぁシステム構成はこんな感じかな」
わたし「また分からないことばかりだ...」
本文章(第2章)を読む上で頭に入れておいたほうが良い文言をピックアップ。文中分からない文言が出たら見返してください。(不足あれば、コメントいただけたら追記していきます)
第2章では必要なライブラリをインストールしていきます。また、当章以降は以下を前提としてシステム構築を行っていきます。
※管理ユーザ、パーミッションの都合上sudoをつける必要がある場面もあるかと思いますが、当記事ではsudoは全て省いています
今回必要なライブラリは、以下の通り。全て
MeCabを利用するためのライブラリはPython側で導入したが、MeCabそのものがインストールされていないため、順次インストールを行います。MeCabは、「ツール本体+設定ファイル+システム辞書+(ユーザ辞書)」から成り、それぞれインストールが必要。通常ネオロード等の用意されている辞書(システム辞書)を使うが、うまく形態素解析ができない場合、欲しいワードがネオロード上では違う品詞と解釈されていた場合、またワードへのタグ付けを行いたい場合等のために、ユーザ辞書を作成することができます。
※自己の環境で各インストール先のファイルパスが分からなかった場合は、トップのフォルダから
<ユーザ辞書の例>
※必須項目は、最初から4項目、「表層形, 左連接状態番号, 右連接状態番号, コスト」であり、残りの項目は自由に設定可能。タグ以外の項目については、一般的なシステム辞書で管理されている項目となる。
※最初の表層形(単語そのもの)及び最後のタグさえ正しい値が入っていれば、今回のシステムは動きます。必須項目である「左連接状態番号, 右連接状態番号, コスト」の数値はいくつでも問題ありません。詳しくは参考:日本テレビ東京で学ぶMeCabのコスト計算を参照ください。
DynamoDBにローカルからアクセスするために、AWS CLIをインストールします。(なくても、コンソール上でGUIでTableを作成もできます)
ソフトウェアのインストールが終わったので、「スクレイピング」、「MeCab」、「AWS CLI」の順で動作確認を行います。
とあるニュースサイトより、情報を取得します。必要な情報は、今のところはニュースタイトルと、タイトルからリンクする際のURLのみとします。スクレイピングの基本は、以下の順序でコードを記載します。
対象のニュースが取得できていることが分かります。
※「3.DOMツリーの解析」について、以下に汎用的なソースコードを書いたとしても、ホームページによってDOMツリーの構造は大きく異なります。今回対象としたサイトはh2,aタグのネストされた構造が全てニュースタイトルであったため簡単に取得できてますが、div,spanタグや、各タグのクラス定義によっては、複雑なコードを各必要が有ります。対象のホームページの数だけ、最初のコスト及び保守コストがかかるため、実装前に、どのホームページを対象とするかは吟味することをおすすめします。
※今回はh2,aタグのみ取得するだけなので簡単に解析を行えていますが、実際はBeautifulSoupのメソッドを駆使して、どうにか必要な情報を取得できる場合がほとんどです。そういった際に参考にできるサイトはこちらです。参考:BeautifulSoup4のチートシート(セレクターなど)
ニュースタイトルの中にあるワードが見つかった場合、MeCabのユーザ定義の辞書に引っ掛けて取得するような仕組みを実現します。(実際は、MeCabは日本語の形態素解析器であるため、スクレイピング対象が英語のサイトであった場合は、AWS Translateにて翻訳した上で辞書に掛けています)
当記事のMeCab環境構築の中で、ユーザ辞書に以下の定義が追加されています。この状態で、次のワードを形態素解析してみたいと思います。
実行結果を確認すると、「量子」というワードに辞書がヒットしている様子が分かります。「量子コンピューター」については、辞書に登録されていたワードが「量子コンピュータ」であったため、ヒットしないところも正確に実現できています。
上記の結果から、ユーザ辞書に登録してあるワードについて、ピックアップしてくることが可能なことが分かりました。ユーザ辞書の自動更新(追加、削除)、単語ごとの重み付け(文中に現れてくる回数等、注目度から算出)が実現できれば、より必要なニュースが抽出できそうな気がしてきました。
以下の順序で、DynamoDBにテーブルを構築して、データを出し入れします。
KeySchemaによって、ハッシュキーとソートキーを設定します。主キーが1つである場合は、ハッシュキーのみでよい。RDB形式とは異なり、TBL作成をする際にカラム名を指定する必要がある項目はキー項目のみである。今回の例では、一意になる項目としてニュース単位にIDを付与するため、ハッシュキーのみでも問題ない。
AttributeNameはカラム名、AttributeTypeは型指定で、SはStringをあらわす。一覧についてはサポートされているデータの種類を参照ください。
ファイルの置いてあるフォルダに移動し、以下コマンドを実行します。
※--endpoint-urlは、ローカル環境にDynamoDBを立てて実行した場合に必要な引数です。実際にAWS上のDynamoDBを更新する場合は、既にawsコマンドと自分のコンソールが紐づくように設定ファイル(configure)を記載しているため、エンドポイントを指定する必要は有りません。
コンソールを開き、テーブルが作成されていることが確認できました。
AWS CLIから作成したテーブルに対して、Pythonからデータの出し入れを行います。boto3についてもAWS CLI同様に、設定ファイル(configure)の情報を読むことで、AWSの個人コンソールにアクセスを可能としています。
うまくデータが取得できており、DynamoDBにデータが登録されていることが分かります。
わたし「スクレイピングして、ニュースの取得ができました」
技術バリバリの人「次は、どのようにトップ10を決めるか、ニュースに対する重み付けの手法を検討しよう!」
続く
最後まで読んでいただき、ありがとうございました。当記事は、第一章:Windows7環境なのにdocker入れて開発することになった話【環境設定編】の続編です。システムっぽいことしてますが、まだまだ動確レベルのことを行っているのが現状です。勉強をしながらシステム構築を行っているため、ご指摘質問どしどし受け付けております。次回更新いつになるか...
第2章
技術バリバリの人「さて、環境の構築も終わったし、何やろうか」わたし「全くイメージ沸きません」
技術バリバリの人「もうちょっと考えてみてくれよ...」
わたし「...」
わたし「あ、そういえば最近変えたスマホに、『今日あなたが見るべきホームページトップ10!』みたいな機能があるんです。しかも結構興味がある内容で、ついつい見ちゃうんですよね。どういう仕組みなんでしょうか」
技術ばりばりの人「ちなみにどんなサイトが上がってくるの?」
わたし「好きなアーティストとか、最近の技術系のニュース記事とかですね」
技術ばりばりの人「なるほどね。それはターゲティング広告の一種だね。ホームページの閲覧履歴から分析をして、『おそらく関連がありそうだ』というサイトを検索しているんだね」
技術バリバリの人「おもしろそうだね、僕らも似たようなことをやってみようか。社内や仲間内に展開できる、『今日見るべきニューストップ10!』なんてのはどうかな」
わたし「確かに、これだけ多くのニュース媒体がある中で、読みたいニュースを教えてくれると助かりますね。全部読むのは無理だし」
技術バリバリの人「よし分かった。じゃぁシステム構成はこんな感じかな」
- ネットワークからWeb Scraping、APIを利用してニュース記事を取得する
- ニュース記事を分析し、出力対象のニュース記事を絞り込む
- ユーザに配信する(この際、View数等のユーザの閲覧状況も取得し、分析のパラメータとする)
わたし「また分からないことばかりだ...」
辞書整理
本文章(第2章)を読む上で頭に入れておいたほうが良い文言をピックアップ。文中分からない文言が出たら見返してください。(不足あれば、コメントいただけたら追記していきます)-
スクレイピング
- WebページからHTMLデータを収集・抽出し、整形・加工すること。
- 似たワードにクローリングがあるが、クローリングはサイトを巡回し、情報を取得することを指す
- 基本は、個人の私的利用の範囲に限る【参考2】
- GUIベースのフリーソフトもあるが、どの情報を抽出してくるか自由がきかないものが多い【参考3】
- プログラミングをする際は、Python、Ruby、JavaScriptにスクレイピング用のライブラリが有る
- ライブラリが無くとも、取得したいURLにHTTPリクエストを行い、HTMLを取得、正規表現を用いるなどして情報を取得することは可能(あくまでライブラリは、それを簡単に行えるようにしているだけ)
- 今回は、PythonのライブラリであるBeautifulSoup4を利用する【参考1】
- 参考1:【Pythonクローラー入門】クローリング スクレイピング方法 総まとめ
- 参考2:Webスクレイピングの注意事項一覧
- 参考3:悪用厳禁!プログラミング不要のWEBスクレイピングツール比較19選
-
MeCab
- NLP(自然言語処理)を行うにあたって、形態素解析を行うことができるオープンソース
- 辞書を用いて文章を形態素(単語として意味を持つ最小の単位)に分解し、品詞やタグを付属することができる
- 『形態素解析→類似度(どの程度似た意味の単語か)判定』や、『形態素解析→機械学習』のように、文字列を扱うための前処理として利用される
- うまく形態素として分解されない(もしくは利用したい単語よりもさらに細分化されてしまう)ワードのために、ユーザー定義辞書を作成することが可能(例えば機械学習を、「機械」と「学習」に分けたくない場合など)
- 参考:【技術解説】形態素解析とは?MeCabインストール手順からPythonでの実行例まで
-
AWS CLI
- AWS上のサービスに対して、ローカル環境やEC2(AWS上の仮想サーバ)からコマンドラインベースで接続することを可能にするツール(コマンドプロンプトやターミナルから、AWSを操作するコマンドを実行できるようにする)
- コンソール(ログインしてGUI上でAWSを触る)でできることは、基本的に全てCLIで実行可能
- S3(AWS上のストレージサービス)に置いてあるデータを、ローカルやEC2から覗いたり、コピーしたりすることもできる
- 今回の場合、ローカル環境からDynamoDBへアクセスし、テーブルを作成する際に利用する
- 参考:AWSコマンドラインインターフェイス(公式)
-
DynamoDB
- NoSQLデータベース
- データ構造はRDBとは異なり、KVS(キーとレコードが1:1、場合によっては2:1で結びつく)構造
- 高速なデータアクセス、書き込み
- テーブルの結合できない
- 主キーは2つまで
- 各レコードが同一の項目数でなくても良い
- Pythonで言う辞書型(Json)の構造でデータの出し入れができる
- 変化に強く、テーブル設計が楽(不要とは言っていない)
- 横方向スケールや等、改修時の手間が少ない
-
ECS
- Elastic Container Serviceの略で、AWS上でDockerコンテナをサポートする、コンテナオーケストレーション(複雑なコンピュータシステム/ミドルウェア/サービスの配備/設定/管理の自動化)サービス
- コンテナ化されたアプリケーションを、簡単に実行・デプロイすることが可能となる
- コンテナ化されたアプリケーションをAWS上で活用するためには、サーバをプロビジョニング(準備の意で、EC2上でCLIを利用し、docker等のコンテナを扱うソフトウェアを導入する)し、クラスタリング(docker-compose等で複数サーバ、コンテナを統合し、1つのサーバシステムのように扱う)必要があった。ECSの登場で、そういった管理、デプロイ等を不要とし、GUI上で簡易にコンテナアプリケーションを導入することが可能となった
- とはいえ内部ではEC2が起動され、統合的に管理されている
- 参考:Amazon Elastic Container Serviceの特徴
-
Fargate
- ECSの登場により、簡単にコンテナアプリケーションをAWS上に実現できるようになった。とはいえ、内部で動作するEC2のインスタンスタイプ選択や、スケールの調節が必要であった
- 起動中にEC2コンソールを見ると、インスタンスが立ち上がっていることも確認できた
- Fargateは、そもそもユーザからはEC2が見えず、スケールや管理も全てよろしくやってくれる
- 現在は、ECSを立ち上げる際に、EC2上でコンテナ起動をするか、Fargateでよろしくやらせるか選択することができる
- 参考:AWS ECSとFargateの組み合わせが素晴らしい件)
- 参考:ECSのバックエンドをEC2からFargateに変更するにあたり知っておくとよさそうな事
-
boto3
- AWS SDK for Python
- PythonでAWS環境を触るために必要なライブラリ
- AWS上のサービスを指定して、稼動・停止、各種操作等がPython上から行うことができる
- 今回の場合、ローカル環境からDynamoDBへアクセスし、データ操作をする際に利用する
- AWS Translateを利用してNewsタイトルを翻訳する際にも利用する予定
- [参考:AWS SDK for Python (Boto3)]https://aws.amazon.com/jp/sdk-for-python/)
必要なソフトウェアのインストール
第2章では必要なライブラリをインストールしていきます。また、当章以降は以下を前提としてシステム構築を行っていきます。-
第1章でUbuntu環境が構築されている - Python(pip含め)がインストールされている
- 次の理由から、どれだけ手順を踏んでも個人間の環境で差異が起きやすいため、Pythonのインストール方法については敢えて言及しません
- Pythonのインストールは様々な方法がある(そもそもUbuntuには最初からインストールされていたりする)
- 頻繁にバージョンアップデートがされる
- pyenv等で複数バージョン(2系と3系)を1環境に導入できる
- Anacondaのような、Pythonで便利なライブラリを一元管理してくれるディストリビューション上で開発もできる(参考:Anaconda は Environment Isolation Tool (環境分離ツール) ではない)
- とはいえ私も参考にした資料は有り、Pythonの環境構築を自分なりに整理してみるを参考にして環境構築しました
- 次の理由から、どれだけ手順を踏んでも個人間の環境で差異が起きやすいため、Pythonのインストール方法については敢えて言及しません
- AWSコンソール上にログインできる環境がある
$sudo pip install ○○
はグローバル空間に入ってしまうためダメです」的なことが書かれていますが、今回は説明を簡単にするために無視しています※管理ユーザ、パーミッションの都合上sudoをつける必要がある場面もあるかと思いますが、当記事ではsudoは全て省いています
1.Pythonに必要なライブラリのインストール
今回必要なライブラリは、以下の通り。全て$pip install hogehoge
でインストール可能。(Anaconda環境を利用している人はpip厳禁です)- BeautifulSoup4
- スクレイピングに利用
$pip install beautifulsoup4
- boto3
- Python上で、AWSの各サービスにアクセスするために利用
$pip install boto3 beautifulsoup4
- MeCab
- Python上で、MeCabの機能を利用するために利用
$pip install mecab-python3
2.MeCabのインストール及び環境セットアップ
MeCabを利用するためのライブラリはPython側で導入したが、MeCabそのものがインストールされていないため、順次インストールを行います。MeCabは、「ツール本体+設定ファイル+システム辞書+(ユーザ辞書)」から成り、それぞれインストールが必要。通常ネオロード等の用意されている辞書(システム辞書)を使うが、うまく形態素解析ができない場合、欲しいワードがネオロード上では違う品詞と解釈されていた場合、またワードへのタグ付けを行いたい場合等のために、ユーザ辞書を作成することができます。- MeCab本体のインストール(このタイミングで設定ファイルもインストールする)
-
$sudo apt-get install mecab mecab-ipadic libmecab-dev
- mecab-ipadicを入れることで、MeCabで扱う文字コードがUTF-8になります
- libmecab-devを入れることで、mecab-config(設定ファイル)が利用できるようになります
-
- mecab-ipadic-neologd(通称ネオロード)のインストール
$git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git <保存する場所のパス>
$cd <保存した場所>/mecab-ipadic-neologd
$./bin/install-mecab-ipadic-neologd -h
※自己の環境で各インストール先のファイルパスが分からなかった場合は、トップのフォルダから
$find / -name ファイル名
で全検索できます- mecab-dict-index(ユーザ辞書作成に必要なコンパイラ) - /usr/lib/mecab/mecab-dict-index - システム辞書 - /var/lib/mecab/dic/mecab-ipadic-neologd - MeCabの設定ファイル - /etc/mecabrc
- ユーザ辞書の作成
- ユーザ辞書用のフォルダ(私の場合は/home/user名/userDic)に、以下の定義(select.csv)でcsvファイルを作成する
- csvファイルの存在するフォルダに移動し、次のコマンドでコンパイルする
$/usr/lib/mecab/mecab-dict-index(環境次第でパスは変更) -d <システム辞書が入っているディレクトリ> -u <ユーザ辞書の保存先+ファイル名> -f <CSVファイルの文字コード> -t <ユーザ辞書の文字コード> <CSVファイル>
$/usr/lib/mecab/mecab-dict-index -d /var/lib/mecab/dic/mecab-ipadic-neologd -u /home/user名/userDic/select.dic -f utf-8 -t utf-8 select.csv
<ユーザ辞書の例>
select.csv
定義)表層形, 左連接状態番号, 右連接状態番号, コスト, 品詞, 品詞細分類1, 品詞細分類2, 品詞細分類3, 活用型, 活用形, 基本形, 読み, 発音,(タグ) 例1)量子コンピュータ,-1,-1,-1,名詞,一般,*,*,*,*,*,*,*,selectdic 例2) 買収,-1,-1,-1,名詞,一般,*,*,*,*,*,*,*,selectdic 例3) 量子,-1,-1,-1,名詞,一般,*,*,*,*,*,*,*,selectdic
※最初の表層形(単語そのもの)及び最後のタグさえ正しい値が入っていれば、今回のシステムは動きます。必須項目である「左連接状態番号, 右連接状態番号, コスト」の数値はいくつでも問題ありません。詳しくは参考:日本テレビ東京で学ぶMeCabのコスト計算を参照ください。
- 設定ファイルに、ユーザ辞書を追加する
- MeCabの設定ファイル、mecabrc(私の場合/etc/mecabrc)を開き、先ほど作成したユーザ辞書のパスを追加する
userdic = /home/user名/userDic/select_dic.dic
3.AWS CLIのインストール及びセットアップ
DynamoDBにローカルからアクセスするために、AWS CLIをインストールします。(なくても、コンソール上でGUIでTableを作成もできます)-
AWS CLIのインストール
$ pip install awscli
-
AWSアクセス情報の設定ファイル編集
$aws configure
AWS Access Key ID [None]: xxxxxxxxxx(IAMユーザ作ったを際のアクセスキー) AWS Secret Access Key [None]: xxxxxxxxxx(IAMユーザ作ったを際のシークレットアクセスキー) Default region name [None]: ap-northeast-1(開発を行っているリージョン) Default output format [None]: json(出力形式)
各種動作確認
ソフトウェアのインストールが終わったので、「スクレイピング」、「MeCab」、「AWS CLI」の順で動作確認を行います。
スクレイピングの動作確認
とあるニュースサイトより、情報を取得します。必要な情報は、今のところはニュースタイトルと、タイトルからリンクする際のURLのみとします。スクレイピングの基本は、以下の順序でコードを記載します。
- スクレイピング対象のURLに対してリクエスト送信
- DOMツリー(HTMLのようなタグでネストされた構造)の取得
- DOMツリーの解析
スクレイピングソースコード
# スクレイピング用ライブラリのインポート from bs4 import BeautifulSoup # HTTP通信用ライブラリのインポート(標準) import urllib.request, urllib.parse ####### 変数解説 ####### # url : スクレイピング対象のURL # parser : HTML解析器 # headers : firefoxに偽装するためのユーザーエージェントヘッダー url = "https://finovate.com/blog/" parser = "html.parser" headers = { "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0", } # HTTP通信を行いホームページにrequest、HTMLの取得 request = urllib.request.Request(url = url, headers = headers) html = urllib.request.urlopen(request).read().decode("utf-8") # パーサーのインスタンス化 parser = BeautifulSoup(html, parser) # タイトルが記載されている、h2, aタグがネストされたリストを取得 # 実際にHTMLを確認し、どのように解析すればほしい情報が取得できるか解析する必要がある allh2Tag = parser.select("h2 a") # h2, aタグのネストされたリストから、必要な情報を取得 for tag in allh2Tag: url = tag.get("href") title = tag.string print("url : " + url) print("title : " + title + "\n")
スクレイピング実行結果
url : https://finovate.com/ntt-data-services-to-acquire-sierra-systems/ title : NTT DATA Services to Acquire Sierra Systems url : https://finovate.com/quid-lands-37-5-million-round-led-by-lexis-nexis-parent/ title : Quid Lands $37.5 Million Round Led by Lexis Nexis Parent url : https://finovate.com/finovate-alumni-news-871/ title : Finovate Alumni News url : https://finovate.com/welcome-to-finovateasia-2/ title : Welcome to FinovateAsia url : https://finovate.com/welcome-to-wan-chai-finovateasia-kicks-off-hong-kong-fintech-week/ title : Welcome to Wan Chai: FinovateAsia Kicks Off Hong Kong FinTech Week url : https://finovate.com/swych-powers-wechats-travelex-pay-service/ title : Swych Powers WeChat’s Travelex Pay Service url : https://finovate.com/finovate-alumni-news-870/ title : Finovate Alumni News url : https://finovate.com/yoyo-lands-30-million-partnership-agreement/ title : Yoyo Lands $30 Million Partnership Agreement url : https://finovate.com/ondeck-partners-with-pnc-bank-to-streamline-sme-financing/ title : OnDeck Partners with PNC Bank to Streamline SME Financing url : https://finovate.com/finovateasia-is-days-away/ title : FinovateAsia is Days Away
※「3.DOMツリーの解析」について、以下に汎用的なソースコードを書いたとしても、ホームページによってDOMツリーの構造は大きく異なります。今回対象としたサイトはh2,aタグのネストされた構造が全てニュースタイトルであったため簡単に取得できてますが、div,spanタグや、各タグのクラス定義によっては、複雑なコードを各必要が有ります。対象のホームページの数だけ、最初のコスト及び保守コストがかかるため、実装前に、どのホームページを対象とするかは吟味することをおすすめします。
※今回はh2,aタグのみ取得するだけなので簡単に解析を行えていますが、実際はBeautifulSoupのメソッドを駆使して、どうにか必要な情報を取得できる場合がほとんどです。そういった際に参考にできるサイトはこちらです。参考:BeautifulSoup4のチートシート(セレクターなど)
MeCabの動作確認
ニュースタイトルの中にあるワードが見つかった場合、MeCabのユーザ定義の辞書に引っ掛けて取得するような仕組みを実現します。(実際は、MeCabは日本語の形態素解析器であるため、スクレイピング対象が英語のサイトであった場合は、AWS Translateにて翻訳した上で辞書に掛けています)当記事のMeCab環境構築の中で、ユーザ辞書に以下の定義が追加されています。この状態で、次のワードを形態素解析してみたいと思います。
- 「量子コンピューターの「米中競争」が過熱──競り合うグーグルとアリババは、量子超越性を達成できるか」
- ⇒辞書登録されているワード、「量子」が含まれる
- ⇒「量子コンピューター」については、辞書登録されたワードと少し異なる
- 「中国アリババのクラウド事業がAWS並のバケモノになりつつある件」
- ⇒辞書登録されているワードが含まれていない
select.csv
量子コンピュータ,-1,-1,-1,名詞,一般,*,*,*,*,*,*,*,selectdic 買収,-1,-1,-1,名詞,一般,*,*,*,*,*,*,*,selectdic 量子,-1,-1,-1,名詞,一般,*,*,*,*,*,*,*,selectdic
形態素解析ソースコード
# 形態素解析用ライブラリのインポート import MeCab # MeCabのどのシステム辞書を使うか指定 mecab = MeCab.Tagger("-d /var/lib/mecab/dic/mecab-ipadic-neologd") #おまじない⇛これがないと文字コードエラーが起きる模様 mecab.parse("") # 対象のニュースタイトル1つ目 test_text = "量子コンピューターの「米中競争」が過熱──競り合うグーグルとアリババは、量子超越性を達成できるか" mecab_node = mecab.parseToNode(test_text) print("ニュースタイトル① : " + test_text) # すべての形態素(単語)に対して解析を行う while mecab_node: print("原型 : " + mecab_node.surface) print("形態素 : " + mecab_node.feature) # 形態素を分割 detail = mecab_node.feature.split(",") # 形態素の10番目に値が入っている場合、出力 # ⇛ユーザ辞書で登録されているワードであることが確認できる try: print(detail[9] + "⇛ユーザ辞書に膨れまれているワードです\n") except IndexError as e: pass mecab_node = mecab_node.next print("---------------------------------------------------------------------------") # 対象のニュースタイトル2つ目 test_text2 = "中国アリババのクラウド事業がAWS並のバケモノになりつつある件" mecab_node2 = mecab.parseToNode(test_text2) print("ニュースタイトル② : " + test_text2) # すべての形態素(単語)に対して解析を行う while mecab_node2: print("原型 : " + mecab_node2.surface) print("形態素 : " + mecab_node2.feature) detail = mecab_node2.feature.split(",") # 形態素の10番目に値が入っている場合、出力 # ⇛ユーザ辞書で登録されているワードであることが確認できる try: print(detail[9] + "⇛ユーザ辞書に膨れまれているワードです\n") except IndexError as e: pass mecab_node2 = mecab_node2.next
形態素解析実行結果
ニュースタイトル① : 量子コンピューターの「米中競争」が過熱──競り合うグーグルとアリババは、量子超越性を達成できるか 原型 : 形態素 : BOS/EOS,*,*,*,*,*,*,*,* 原型 : 量子コンピューター 形態素 : 名詞,固有名詞,一般,*,*,*,量子コンピュータ,リョウシコンピューター,リョーシコンピューター 原型 : の 形態素 : 助詞,連体化,*,*,*,*,の,ノ,ノ 原型 : 「 形態素 : 記号,括弧開,*,*,*,*,「,「,「 原型 : 米中 形態素 : 名詞,固有名詞,人名,姓,*,*,米中,ヨネナカ,ヨネナカ 原型 : 競争 形態素 : 名詞,サ変接続,*,*,*,*,競争,キョウソウ,キョーソー 原型 : 」 形態素 : 記号,括弧閉,*,*,*,*,」,」,」 原型 : が 形態素 : 助詞,格助詞,一般,*,*,*,が,ガ,ガ 原型 : 過熱 形態素 : 名詞,サ変接続,*,*,*,*,過熱,カネツ,カネツ 原型 : ─ 形態素 : 記号,一般,*,*,*,*,─,─,─ 原型 : ─ 形態素 : 記号,一般,*,*,*,*,─,─,─ 原型 : 競り合う 形態素 : 動詞,自立,*,*,五段・ワ行促音便,基本形,競り合う,セリアウ,セリアウ 原型 : グーグル 形態素 : 名詞,固有名詞,組織,*,*,*,Google LLC,グーグル,グーグル 原型 : と 形態素 : 助詞,並立助詞,*,*,*,*,と,ト,ト 原型 : アリババ 形態素 : 名詞,固有名詞,一般,*,*,*,アリババ,アリババ,アリババ 原型 : は 形態素 : 助詞,係助詞,*,*,*,*,は,ハ,ワ 原型 : 、 形態素 : 記号,読点,*,*,*,*,、,、,、 原型 : 量子 形態素 : 名詞,一般,*,*,*,*,*,*,*,selectdic selectdic⇛ユーザ辞書に膨れまれているワードです 原型 : 超越 形態素 : 名詞,サ変接続,*,*,*,*,超越,チョウエツ,チョーエツ 原型 : 性 形態素 : 名詞,接尾,一般,*,*,*,性,セイ,セイ 原型 : を 形態素 : 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ 原型 : 達成 形態素 : 名詞,サ変接続,*,*,*,*,達成,タッセイ,タッセイ 原型 : できる 形態素 : 動詞,自立,*,*,一段,基本形,できる,デキル,デキル 原型 : か 形態素 : 助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ 原型 : 形態素 : BOS/EOS,*,*,*,*,*,*,*,* --------------------------------------------------------------------------- ニュースタイトル② : 中国アリババのクラウド事業がAWS並のバケモノになりつつある件 原型 : 形態素 : BOS/EOS,*,*,*,*,*,*,*,* 原型 : 中国 形態素 : 名詞,固有名詞,地域,国,*,*,中国,チュウゴク,チューゴク 原型 : アリババ 形態素 : 名詞,固有名詞,一般,*,*,*,アリババ,アリババ,アリババ 原型 : の 形態素 : 助詞,連体化,*,*,*,*,の,ノ,ノ 原型 : クラウド 形態素 : 名詞,固有名詞,一般,*,*,*,CROWD,クラウド,クラウド 原型 : 事業 形態素 : 名詞,一般,*,*,*,*,事業,ジギョウ,ジギョー 原型 : が 形態素 : 助詞,格助詞,一般,*,*,*,が,ガ,ガ 原型 : AWS 形態素 : 名詞,固有名詞,一般,*,*,*,エーダブリューエス,エーダブリューエス,AWS 原型 : 並 形態素 : 名詞,一般,*,*,*,*,並,ナミ,ナミ 原型 : の 形態素 : 助詞,連体化,*,*,*,*,の,ノ,ノ 原型 : バケモノ 形態素 : 名詞,固有名詞,一般,*,*,*,バケモノ,バケモノ,バケモノ 原型 : に 形態素 : 助詞,格助詞,一般,*,*,*,に,ニ,ニ 原型 : なり 形態素 : 動詞,自立,*,*,五段・ラ行,連用形,なる,ナリ,ナリ 原型 : つつ 形態素 : 助詞,接続助詞,*,*,*,*,つつ,ツツ,ツツ 原型 : ある 形態素 : 動詞,自立,*,*,五段・ラ行,基本形,ある,アル,アル 原型 : 件 形態素 : 名詞,一般,*,*,*,*,件,ケン,ケン 原型 : 形態素 : BOS/EOS,*,*,*,*,*,*,*,*
上記の結果から、ユーザ辞書に登録してあるワードについて、ピックアップしてくることが可能なことが分かりました。ユーザ辞書の自動更新(追加、削除)、単語ごとの重み付け(文中に現れてくる回数等、注目度から算出)が実現できれば、より必要なニュースが抽出できそうな気がしてきました。
AWS CLI及びboto3の動作確認
以下の順序で、DynamoDBにテーブルを構築して、データを出し入れします。- AWS CLI上からニュースを格納するためのテーブルの構築
- Pythonからboto3を利用してデータの出し入れを行う
テーブルに対応するjsonファイルを作成する
KeySchemaによって、ハッシュキーとソートキーを設定します。主キーが1つである場合は、ハッシュキーのみでよい。RDB形式とは異なり、TBL作成をする際にカラム名を指定する必要がある項目はキー項目のみである。今回の例では、一意になる項目としてニュース単位にIDを付与するため、ハッシュキーのみでも問題ない。tableDef.json
{ "TableName": "NewsTable", "AttributeDefinitions": [ { "AttributeName": "id", "AttributeType": "S" }, { "AttributeName": "category", "AttributeType": "S" } ], "KeySchema": [ { "KeyType": "HASH", "AttributeName": "id" }, { "KeyType": "RANGE", "AttributeName": "category" } ], "ProvisionedThroughput": { "WriteCapacityUnits": 5, "ReadCapacityUnits": 5 } }
awsコマンドを用いてテーブルを作成する
ファイルの置いてあるフォルダに移動し、以下コマンドを実行します。$aws dynamodb create-table --endpoint-url http://localhost:8000 --cli-input-json file://tableDef.json
※--endpoint-urlは、ローカル環境にDynamoDBを立てて実行した場合に必要な引数です。実際にAWS上のDynamoDBを更新する場合は、既にawsコマンドと自分のコンソールが紐づくように設定ファイル(configure)を記載しているため、エンドポイントを指定する必要は有りません。
コンソールを開き、テーブルが作成されていることが確認できました。
boto3からデータの出し入れを行う
AWS CLIから作成したテーブルに対して、Pythonからデータの出し入れを行います。boto3についてもAWS CLI同様に、設定ファイル(configure)の情報を読むことで、AWSの個人コンソールにアクセスを可能としています。
データアクセス用ソースコード
import boto3 from boto3.dynamodb.conditions import Key, Attr import sys # NewsTableへのdaoのアクセス定義 # localの場合 # dynamodb = boto3.resource('dynamodb',endpoint_url='http://localhost:8000') # AWS DynamoDBサービスの東京リージョン(ap-northeast-1)を指定 dynamodb = boto3.resource('dynamodb',region_name='ap-northeast-1') table = dynamodb.Table('NewsTable') sys.setrecursionlimit(100000) # NewsTableに対応したDao class NewsTableDao: def __init__(self): pass # 各レコードに対応したニュース(辞書型)を渡すことで、一括登録するメソッド def saveNews(self, news): table.put_item(Item = news) # scan(全量取得)したデータに対して、day項目で絞って取得するメソッド def selectNewsList(self, day): JaNewsList = table.scan(FilterExpression = Attr('day').eq(day)) return JaNewsList # NewsTableに登録するNewsに対応したオブジェクト用クラス class News: def __init__(self, id, category, day, time, news, url): self.id = id self.category = category self.day = day self.time = time self.news = news self.url = url def to_dict(cls): return { "id" : cls.id, "category" : cls.category, "day" : cls.day, "time" : cls.time, "news" : cls.news, "url" : cls.url } def main(): id = "001" category = "Cloud" day = "20180101" time = "000000" news = " 量子コンピューターの「米中競争」が過熱──競り合うグーグルとアリババは、量子超越性を達成できるか" url = "http://xxxxxxyyyyy" # ニュースの各変数をBean(Newsクラス)に格納 news = News(id, category, day, time, news, url) newsDao = NewsTableDao() # ニュースの登録 newsDao.saveNews(news.to_dict()) # 登録したニュースの取得 print(newsDao.selectNewsList(day)['Items']) if __name__ == '__main__': main()
データアクセス実行結果
[{'category': 'Cloud', 'time': '000000', 'day': '20180101', 'id': '001', 'url': 'http://xxxxxxyyyyy', 'news': ' 量子コンピューターの「米中競争」が過熱──競り合うグーグルとアリババは、量子超越性を達成できるか'}]
あとがき
わたし「スクレイピングして、ニュースの取得ができました」技術バリバリの人「次は、どのようにトップ10を決めるか、ニュースに対する重み付けの手法を検討しよう!」
続く
コメント
コメントを投稿