BEACHSIDE BLOG

MicrosoftとかC#を好むレンジャーの個人メモ

QnA Maker でヨガのポーズからその特徴を調べる( Python でスクレイピングしてデータ準備編 )

もし、ヨガのレクチャーを受けたとき、そのポーズがなんの効果があるか知りたいと思うだろうと妄想したので QnA Maker などを使って解決しようと思いました。

(ヨガのレクチャー受けてるときはポーズになんの効果あるかとか説明ありそうですけどね、まだ受けてないので知らんのです!)

逆に、肩こりを改善したいとかからなんのポーズをとればよいかってのもありそうですが、QnA Maker には向かないと思ったので今回はやりません。
(そう、この物語は諸事情により QnA Maker 使って前提のシナリオなのです)。

冗談半分な前置きはさておき本題です。やりたいことは、

ここでのゴールは QnA Maker でヨガのポーズからその特徴を調べるためのデータを作りたい ってところです。

そのために以下のことをします。

  • ヨガのポーズと効果が載ってそうなサイトをスクレイピング
  • QnA Maker にインプットする形式に変更

目次

ヨガのポーズと効果が載ってそうなサイトをスクレイピング

C#er な私なので Python だと生産性がた落ちですが、使いたいという理由だけで Python をでやりましょう。Jupyter Notebook (というか Azure Notebook を使ってますが)で書いてます。

YOGA HACK というサイトのヨガポーズ辞典 ( https://www.yogaroom.jp/yogahack/yogapose ) からスクレイピングさせていただきます。

ぱっと見た感じ、山のポーズのURLが https://www.yogaroom.jp/yogahack/yogapose/001 で、他のポーズは最後の連番が異なってるのでそういう構成なんだと察します。
クローリングし出すとリクエスト数が増えて先方にご迷惑をかけたら困るのでしません。

HTMLを見てみる

ページには以下のような情報があるので、ここから特定の情報をとってこようと思います。

f:id:beachside:20190809162639p:plain

データが存在しない場合は「なし」となるのですね。あとは、HTMLには都合よくカスタムデータ属性なんてついてるわけはないですね。

f:id:beachside:20190809162812p:plain:w400

画面からどの情報を取得するかと、コードの column の定数の定義をこんな感じしました。

f:id:beachside:20190809165630p:plain

コードで定数定義しておきます。

1つのURL から必要な情報を返す

https://www.yogaroom.jp/yogahack/yogapose/001 とかを引数にもらったらヨガのポーズの情報を返す関数を以下のように作りました。

特に解説するほどのコードも無いですが、14-15行目では、ページの定義が全て同じか知らんので値が取れなかった時は諦めるためのものです。

この時点で QnA Maker のインプットに必要な形式に変えてないのは、QnA 以外のインプットとしても使う予定なので、まずはプリミティブな状態で保存しようとしてます。

URLをぐるぐるしてデータを取得

愚直に URL の最後の連番をインクリメントしてループします。とりあえず動作検証に3ページだけ(つまり range_stop_value = 4 にセットする)試します。
取得したデータは Pandas の DataFrame に入れちゃいましょう。

Jupyter Notebook で DataFrame を出力して確認するとこんな感じに。

f:id:beachside:20190809170711p:plain

実際には149が最後なので、range_stop_value = 150 にしてます。 最後にTSVに出力します。DataFrame についてくる index は出力不要なので取り除きます。 encoding はデフォで UTF-8かと思いますがちょっと検証した名残で消さずに書いときました。

これで、Jupyter Notebook で実行すると、data フォルダにファイルが保存されます。

ここまでのコード全体はこちらの notebook: "1_scraping.ipynb"にあります。

QnA Maker にインプットする形式に変更

Jupyter Notebook で、先ほどの処理とは別のファイルで処理を書きます。

ヨガのポーズ情報の読み込み

まず、必要な TSV ファイルのパスの定数情報を定義して、先ほど作成した TSV を読み込みましょう。

QnA Maker のインプット形式へ変更

QnA Maker では様々な形式のデータソースがサポートされています(詳しくはこちら)が、今回はシンプルに TSV を使います。質問と回答のペアを出力すればよいです。

回答は、データが「なし」の場合は文章にしません。あと、効果のうち、[症状] と [効果] と [メンタル]は文章として一文にしようと思います。

f:id:beachside:20190809173549p:plain

上図のベビーコブラだとこんな感じです。

質問「ベビーコブラってどない?」

回答「ベビーコブラのポーズ (別名: ベイビーコブラのポーズ)ですね。難易度は初級です。ジャンルはうつぶせ / 後屈です。肩 / 背中を使います。僧帽筋 / 背筋にトレーニング効果があります。バストアップ / 姿勢改善とリラックスに効果があります。注意事項として、首のトラブル、腰のトラブル、 妊娠中の時にこのポーズは行わないでください。」

ということで、回答(というよりはポーズの説明)の文を作る関数はこんな感じにつくりました。

C# の TryParse 系でありそうな out パラメーター修飾子なんちゃらするのができないですが、それっぽく try_have_values メソッドとか作ってるのは C# 味ある~感じでしょうか。

後は、ヨガのポーズの tsv を一行ずつ読み込んで create_description メソッド読み込んで、ポーズと説明文の TSV を作って保存するだけです。

これらコード全体は、こちらの notebook: "2_generate-qna-datasource.ipynb" にあります。

NEXT STEP

次回は、このデータを使って QnA Maker でポーズを聞いたらその説明を返すところをやります。