Challenge #13: HTML Table Parsing 〜HTMLのテーブルをパースする〜 – Alteryx Weekly Challenge

こんにちは、小澤です。

人はなぜ好き放題自由なHTMLを記述してしまうのか? そして、ブラウザはなぜいい感じにレンダリングしてしまうのか?

必要なデータがWeb上にあって、APIやファイルの形式では提供されてないからHTMLファイルを取得してパースしないといけない、という事態は度々発生します。 そんな時、Alteryxでそれに太刀打ちできるのか?

というわけで難易度BeginnerやIntermediateには目もくれずAdvancedの問題ばかりをやっていますw 今回はChallenge #13です

では、果敢にチャレンジしていきたいと思います。

問題の内容

さて、どのような問題なのでしょうか。 まずはデータを確認してみましょう。

入力データは以下のようになっています。

それに対して出力は以下のようになります。

この入力のHTMLをブラウザで開くと以下のようになっています。

なんてことはない、tableタグの中でkey-valueの形式になっているデータを取り出せればいいという問題のようです。

HTMLってXMLでなんとかなるんじゃね?

はい、というわけなのでHTMLをスクレイプするという本気でやりだすと辛い問題となっていますが、幸いにしてAlteryxにはXML Parseつーるという強力な味方がいるので、早速やってみましょう。

やってみると以下のように...うまくいきません。 metaタグが閉じられていないとのことです。さすが難易度がAdvancedの問題はそんなに優しくありませんね。

というわけなので、HTMLとして解析するためにまずはRツールを配置してライブラリを読み込みます。

library(rvest)

え?それは反則だろって? では、仕方ないのでRツールはあきらめて、Pythonツールを配置して以下のコードを入力します。

from ayx import Alteryx
Alteryx.installPackages("beautifulsoup4")
from bs4 import BeautifulSoup

え?やってることは変わらんからこれも反則? もう、しかたないなぁ...

ちゃんとAlteryxでやる

では、ちゃんとAlteryxでやっていきましょう。 ワークフロー全体は以下のようになります。

ワークフローの中身自体はツール数も少なく、一見すると簡単そうですね!

対象データの確認

今回必要なのはテーブルの中身だけです。 その部分を取り出すためにHTMLファイル全体の構造を確認しておきましょう。

<html xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
  <head>
    <META http-equiv="Content-Type" content="text/html">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body style="margin:0px 0px 0px 0px;overflow:auto;background:#FFFFFF;">
    <table style="font-family:Arial,Verdana,Times;font-size:12px;text-align:left;width:100%;border-collapse:collapse;padding:3px 3px 3px 3px">
      <tr style="text-align:center;font-weight:bold;background:#9CBCE2">
        <td></td>
      </tr>
      <tr>
        <td>
          <table style="font-family:Arial,Verdana,Times;font-size:12px;text-align:left;width:100%;border-spacing:0px; padding:3px 3px 3px 3px">
            (ここに取得したいデータが入ってる)
          </table>
        </td>
      </tr>
    </table>
  </body>
</html>

(ここに取得したいデータが入ってる)の部分はkey-valueごとに以下のような感じで入っています。

...
<tr>
  <td>In Country</td>
  <td><Null></td>
</tr>
<tr bgcolor="#D4E4F3">
  <td>MSA</td>
  <td>4885</td>
</tr>
...            

さすが難易度Advanced! tableタグが隙を生じぬ二段構えです。 いい感じに内側のテーブルのみを取り出せればいいのですが、、

tableタグを取り出す。

RegExツールを使ってtableタグの部分だけ取り出して見ましょう。

ものすごく単純に考えて、tableの中身だけを取り出す正規表現にしてみました。

結果は以下のように、tableタグがから始まっています。

ここで、「よっしゃこれでいける!」と思わずにCell Viewerを使って全体を確認してみると悲しいことが発覚します。

少々ゴリ押しですが、この部分は含まないように正規表現の中身を以下のように書き換えました。

^.*(<table .*>.*</table>) </td> </tr> </table>.*$

これで欲しいテーブルのみを取得できました。

今度こそXMLとしてパースする

tableの中身は見た感じXMLとしてパースできる形式になってそうなので、今度こそこのデータにXML Parseツールを使います。 結果は以下のように...エラーが出ます。

最初に確認したデータによると、値が入っていない項目の<td>タグ内の値が<Null>となっているため、こいつもタグとして処理しようとしているようです。 Formulaツールを使ってこの値をNullであることが識別できる別な値に変えてしまいましょう。 今回は空文字にしました。

Replace([Description], "<Null>", '')

これでXML Parseツールを使うと3度目の正直ということで無事以下のようにパースできました。

あとはSelectツールでtd列をName, td2列をValueに変更し、RecordID列と合わせて3列のみ残したのち、 Formulaツールで空文字をNullに置き換えれば完成です。

iif([Value] != '', [Value], Null())

以下のように同じ出力が得られました。

おわりに

今回は、Alteryx Weekly Challenge #13に挑戦してみました。

難易度Advancedとは一言で言っても

  • マクロなども含む複雑なワークフローを組み立てる必要がある
  • 特定のツールを利用すること自体が高難易度だったり、ツールの深い使い方を知ってる必要があるから難しい
  • 扱う対象データやツールのベースとなっている技術に対する知見も必要だったりする

など、色々な意味での高難易度が含まれているようです。

Alteryxの導入なら、クラスメソッドにおまかせください

日本初のAlteryxビジネスパートナーであるクラスメソッドが、Alteryxの導入から活用方法までサポートします。14日間の無料トライアルも実施中ですので、お気軽にご相談ください。

alteryx_960x400