ラベル connpass の投稿を表示しています。 すべての投稿を表示
ラベル connpass の投稿を表示しています。 すべての投稿を表示

2022/04/19

[Power BI] カスタム関数をつかったQueryを含むデータセットが自動更新できない

(追記: Excel のブックをそのまま Power BI Service にあげて使用するのではなく、Power Query + Excel Pivot Table レポートを Power BI Desktop でレポートを書き換えています。Power Query クエリの多くをそのまま移行できるのは、モダンExcel + Power BI の組み合わせの使い勝手の良いところです)

データを元にしたレポートやダッシュボードを複数のユーザーと定期的に共有することは、Excel で工夫・時間をかけて実現できますが、Power BI Service を含む Power BI は、その目的のためにつくられたこともあり、Excel での苦労や時間を軽減してくれます。

特に、モダンExcel な使い方をしているユーザーにとって魅力に見えるのは、レポートのデータ更新の自動化 につきるかと思います。

以前紹介した投稿 [Excel] Excel で JSON データを読み込む で利用してる connpass を使ったレポートなども、個人でデータを確認する分には Excel は柔軟で使いやすいのですが、他の人と、定期的に共有するとなった場合の共有方法については非常に悩みました。Excel ユーザーとしては OneDrive の活用が理想だったと思いますが、OneDrive と PowerQuery (取得と変換)の組み合わせはあまり良くありません。OneDrive といえども他社のファイルサーバー/サービス同様にxlsxのファイル保存先としてしか使えず、メールやメッセンジャーなどで保存先のパスを共有しながら、画像を貼り付けるような使い方になってしまいます。

もし、クラウドに保存している xlsx の「データ更新」ボタンが定期的、自動的に押され、そこにあるデータを表示できたら、、、

これは Pivot Table レポートや Power Query を活用し、複数の人とそれらを共有しなければならないデータエンジニアがいつも思うことです。これを可能にするのが、Power BI Service のダッシュボードやレポートで、データセットの設定にある「スケジュールされている更新」です。


この設定を行い、レポートおよびダッシュボードを共有することで、自動更新された最新データの表示が可能になります。以下は17日、18日の設定時に発生したエラーを含む対応がうまくいき、データセットが自動更新された履歴です。成功すると [状態] が完了になります。


解決しなければならなかった課題は複数あったのですが、今回、関連する日本語の情報を見つけることがなかなかできなかったので、そのうちのひとつを今回ご紹介したいと思います。残りもおって紹介したいと思います。

エラーメッセージ

データセットの[更新スケジュールの設定] で表示されたエラーの内容は「現在、以下のデータソースが更新をサポートしていないため、このデータセットの更新をスケジュールできません、、、」「・Query1 のデータソース」でした。


Query1 は具体的なクエリの名前を指しているわけではありません。
さらに具体的な Query に含まれるエラーの原因を探します。上の図の青い文字のリンク「データセットの表示」をクリックすると、エラーが発生しているデータセットの更新の状況を確認することができ、[最新の情報に更新済み] に更新しようとした日時が表示され、その横に注意マークがあるのでそれをクリックしてみました。するとどうやらデータセットに含まれる「動的データソース」があるために更新されない、と明示的に書かれていました。


このデータセットには、動的データソースが含まれています。動的データソースは Power BI サービスでは更新されないため、このデータセットは更新されません。詳細情報: https://aka.ms/dyanmic-data-sources。のメッセージ画面

このダイアログで紹介している https://aka.ms/dynamic-data-sources のページを開くと、実は非常に詳しく Power BI におけるデータ更新について書かれているのですが、これを全部読み込んで理解するのはなかなかつらいものがあります。以下、このページの日本語の URL です。

Power BI でのデータの更新
https://docs.microsoft.com/ja-jp/power-bi/connect-data/refresh-data

今回のケースにおける問題となった動的データソースは、connpass から REST API を使い JSON データを取りこむ際につかった start パラメーターが原因でした。どうしてこれが原因であるかがわかったのは後述する YouTube 動画のおかげです。

    ソース = Json.Document(Web.Contents("https://connpass.com/api/v1/event/?keyword=JAWS&count=100&start=" & p1)),
しかし、この start パラメーターによるページングの機能を使って、対象とするデータを Power BI に取りこむ(import) ことをしなければ集計ができません。この時点で日本語の情報が少なかったので、Power BI の UI を英語に切り替えて、英語でエラーメッセージやダイアログのメッセージを拾って検索することにしました。

ヘルプは上級者も含むユーザーを対象としているため、解決につながる直接的なイメージをその段階では思い浮かべることができなかったかもしれませんが、今思うとこの段階で Web.Contents のヘルプを読み込むべきでした。以下のヘルプの 例1 が解決方法だったのです。

Web.Contents
https://docs.microsoft.com/ja-jp/powerquery-m/web-contents 

解決方法は動的データソース表記を変更する

英語のキーワードのよる検索の試行錯誤の結果、以下の YouTube の解説ビデオを見つけることができました。

Making sure your Power BI web data source refreshes online (RelativePath, Query, BrowserContents)

上記の YouTube をみて、それから Web.Contents のヘルプをみると ? をつかったパラメーターの表記は NG で、ダイナミックURLを受け付けない静的ベース URL に対して、RelativePath や Query プロパティをつかった方法を使えばいいことがわかります。

上述のソースは以下のような表記方法に変わりました。
    ソース = Json.Document(Web.Contents("https://connpass.com/api/v1/event/?keyword=JAWS&count=100",
        [Query=[start=p1]])),

複数のパラメータの表記方法などは Web.Contens のヘルプに書かれています。
これで、パラメーターの変数を変えたいために動的URLを使うカスタム関数を作成し、その関数がクエリに含まれるためにスケジュールした更新が失敗する、といったことを回避することができます。

以上、参考になれば幸いです。

2020/05/01

[Excel データの取得と変換] Webページのテキストデータを取得する

[注意] Webサイトによってはスクレイピングを明確に禁止しているサイトもあるので、利用の際は確認してください。

Power Query / Power BI の[データの取得と変換]によりさまざまなデータソースから Excel や Power BI Desktop にデータを取り込むことができることは、このブログでもご紹介してきました。

特に「テーブル」を使った Web ページからのデータの取り込みは非常に簡単になったのも [データの取得と変換] を使う理由です。この素晴らしい機能が、いまだに Excel ユーザーの中で知名度が低いのは、本当に残念です。

[マイクロソフト] チュートリアル:Power BI Desktop を使用して Web ページのデータを分析する
https://docs.microsoft.com/ja-jp/power-bi/desktop-tutorial-importing-and-analyzing-data-from-a-web-page

今回は、HTMLのテーブルにもなっていないWebページのデータを取得する方法をご紹介します。俗に「ウェブ スクレイピング」と呼ばれるもので、そもそもデータの再利用などを考慮していないページから、最新のデータを取得する、昔はやった方法です。

Doorkeeperconnpassで勉強会開催情報を公開しているAWSのユーザーグループ「JAWS-UG」の両サービスの登録会員数の取得を例としてその方法をご紹介します。ちなみに両サイトはREST APIを公開しているので、勉強会開催情報の取得では本来スクレイピングする必要はないのですが、公開APIを調べる限りだと「登録メンバー数」を取得するAPIがありませんでした。しばらく「登録メンバー数」の取得は月1回なので目視&手作業で行っていましたが、外出自粛で時間ができたので「データ取得の自動化」をしようと思い立ちました。APIを使ったデータの取り込みは以下でご紹介しました。

[Excel] Excel で JSON データを読み込む
https://road2cloudoffice.blogspot.com/2017/06/excel-excel-json.html

Webスクレイピングのポイントは「テキスト ファイル」で扱う

操作の大まかな流れは以下になります。

  1. Webページのhtmlファイルを「テキスト ファイル」としてPower Queryに取り込む
  2. 該当する行を固有のキーワードでフィルターをかけて特定する
  3. 特定した行から、該当するデータを抽出する
  4. 抽出したテキスト データの属性を調整する(テキストから整数など)
それでは順を追ってみていきましょう。

1)テキストファイル形式で取り込む

Webページの構成上「テーブル」形式のものは取り込みやすいのですが、以下のような数値を取り込むのは、HTMLの構造上、テーブル内のデータとして認識されていません。


このようなWebページからデータを取り込むには、まずリボンの[データ]タブの[データの取得と変換]の[データの取得]にある、[その他のデータ ソースから]の[Webから]を使います。

(直接 [Webから] でも OK。ただしExcel2016以前の[Webクエリ]は別モノなので注意)

サンプルとして利用する、JAWS-UG全国のURL(https://jaws-ug.doorkeeper.jp/)を入れます。今回の場合は [基本] を選択したままで [OK] を押します。


今回 [Document] のテーブルビューは使えません。WebページをHTMLのテーブルビューではなく「テキスト」として扱います。そのため、URLのフォルダーアイコン上で右クリックメニューの [データの変換] を選びます。


Power Query エディター ウィンドウが開くので、[クエリの設定] の [適用したステップ] にある [ソース] の横にある歯車マーク(①)をクリックして、[形式を指定してファイルを開く] のドロップダウンリスト(②)を開き、[テキスト ファイル] (③)を選択します。


テキスト ファイル形式を指定することで、Power Query内にWebページのhtmlファイルは「テキスト」として読み込まれます。ここから該当する箇所を探します。

2)フィルターをかけて行を特定する

上からテキストを見て探してもよいですが、最終的には「フィルター」の機能を使って、該当するデータを含む行を絞り込みます。今回の場合は、メンバー数のデータがある部分を取り出したく、該当する記述は以下になります。

<a class="label label-full community-members-count" href="/members">9464人</a>
class名の"label label-full community-members-count"と href="/members" はユニークでフィルターのキーワードで使えそうです。以下のようにタグをコピーして行フィルターをかけます。

3)行からデータを抽出する

MID関数のような機能を使ってテキストの行からメンバー数に該当する数値を抜き出します。抜き出した結果は列を追加して新しく加えるので、[列の追加] タブにある [抽出] を使います。

4)データの属性を調整する

抽出されたデータは「テキスト」なので、これを整数に変換し、列名も変更します。
以下のように簡単に変更することが可能です。


上記では Doorkeeper のWebページからメンバー数を抽出しましたが、同じ手順で connpass からもメンバー数を抽出することが可能です。いくつかの支部のメンバー数を抽出した結果は以下のようになります。


一度シートを作成してしまえば、あとは [データ] タブの [クエリと接続] の [すべての更新] ボタンで、Webページを参照し、最新のデータに更新します。以下のアニメーションGIFでは、合計が 22,887人だったものが、東京支部が1名増えて、22,888人に更新されています。


なお、今回はスクレイピングの手法で、これからも再利用可能なWebページでしたが、Webページの作り方によっては再利用ができないものもあるので、すべてのケースに適用できるわけではないことをご留意ください。(毎回手作業が発生するものは自動化する意味がないからです。ここでいう「自動化」は [クエリと接続] と [すべて更新] ボタンを押すことで最新のデータになるものを指します)

次のステップ

この手の自動化ツールは汎用性を目指さなくてもいいので、該当する支部をすべて抜き出しシートにコピペしながら手作業で一度作成すれば、あとは [すべて更新] で瞬時に最新データに更新されるので、自動化・省力化の目的は達成です。

しかし、ちょっと冗長な感じがするので、時間があれば以下のようなことを検討できるかもしれません。

  • URLを変数としてもらい、メンバー数を返すユーザー関数にする
  • ユーザー関数を使って、計算対象支部の増減に柔軟に対応するシートにする
たぶん、できると思います。対象支部は50以上あるので、汎用化するか、手作業でやるかは微妙な数ですが、できれば汎用化して、またアウトプットしたいと思います。

もうひとつは「最終開催日」の取得です。これはREST APIの勉強会情報の開催日からも取れそうですし、ページを指定して上記の方法のようなスクレイピングでもとれそうです。

以下、ポエム

しばらくこのデータの取得と更新は月に1回、対象の支部が50程度なので、1時間くらいかけて行っていました。各支部の状況なども確認できるので、決して無駄な時間ではない、と考えていましたが、このデータのチェックを月1回から週1回に行う可能性が出てきました。

そうなると、週1回の1時間かかるデータ更新は外部の協力者に作業依頼する方法もありました。しかし、私たちはIT業界にいます。データを扱うITベンダーのマーケティング部門の人間であれば、ITを使って自動化・省力化を考えたほうが前向きだと思っています。ノンテク部門はお金で解決しがちですが、IT業界にいるのですから、やはりITで解決することにまずはチャレンジしたいです。

立場上、できれば、AWSのGlueやQuickSightを使ったほうがいいと思います。個人でデータを扱うのに適した Excel ではなく、クラウド上でデータ処理を行い、他の人たちと処理したデータを共有すべきタスクができたらチャレンジしたいと考えます。

以上、最後はポエムでまとめてしまいましたが、REST APIなどが提供されていない場合、昔ながらのスクレイピングによるデータ取得も、現在、Excel や Power BI Desktop の Power Query でコーディングレスで可能なことがおわかりいただけたかと思います。
何らかの参考になれば幸いです。
Powered by Blogger.

自己紹介

自分の写真
1989年新卒で日本IBMに入社しダウンサイジング担当としてホストコンピュータと繋げるオフコン、UNIX、PCサーバーのプロジェクトを担当。1997年 MSKK(現日本マイクロソフト)入社、NT4出荷に伴い企業向けサポート部門のビジネスマネージャーとして Excel 使いとなり、2002年 にMSMVPなどをサポートするユーザーコミュ二ティ部門を設立、部門をリード。2006年にMSKK退職後、企業向けのITトレーニング会社・団体に携わり、2014年頃よりPowerBI勉強会主催メンバーの一人として参画、そのコミュニティ活動で MSMVP for Data Platform PowerBI 2017受賞。https://mvp.microsoft.com/ja-jp/PublicProfile/5002635 同年にMVP Awardを返上し、アマゾン ウェブ サービス ジャパンに入社、コミュニティプログラム担当として現在に至る。