jenkinsのジョブ実行結果を、ajaxでwebスクレイピングしてxml形式で取得し、一覧表示してみよう

# はじめに
Jenkinsの管理コンソール、、、見づらくないですか？
ビルド履歴番号で成功とか言われても、それは誰がどのパラメータで実行したジョブ？ってなりますよね。
そこで、Jenkinsのビルド情報をwebスクレイピングで取得し、一覧表示したいと思います！
WebスクレイピングといえばPythonとBeautiful Soupの組み合わせが主流のようですが、
前回の記事同様に、Javascriptと基本的なライブラリのみを使用して解決できないか試した所、
なんとかなったので、メモを残したいと思います。
（webスクレイピングの注意事項 https://qiita.com/nezuq/items/c5e827e1827e7cb29011）
取得先とリクエスト頻度は計画的に、、、、

# 課題整理
まず、Jenkinsから情報を取得出来なければ話になりません。
そこで調査したところ、APIが用意されている事がわかりました。
使い方もシンプルで、httpリクエストメソッドオンリーで取得可能でした。
今回はジョブの実行結果を取得したいだけなので、getメソッドで対応します。

# とりあえず実行
どのようなデータが取れるのか確認する為、
google chromeにて、自身が立てたjenkinsへ以下のリクエストを投げてみました。

http://localhost:9090/api/json?
※xml形式で取得したい場合は、jsonの部分をxmlにするだけで可能

```json
{
  "assignedLabels": [
    { }
  ],
  "mode": "NORMAL",
  "nodeDescription": "ノード",
  "nodeName": "",
  "numExecutors": 2,
  "description": null,
  "jobs":[
    {
      "name": "testJob",
      "url": "http://<jenkins host>/job/testJob/",
      "color": "blue"
    },
    {
      "name": "hoge",
      "url": "http://<jenkins host>/job/hoge/",
      "color": "blue"
    }
  ],
  "overallLoad": { },
  "primaryView":
  {
    "name": "All",
    "url": "http://<jenkins host>/"
  },
  "quietingDown": false,
  "slaveAgentPort": 0,
  "unlabeledLoad": { },
  "useCrumbs": false,
  "useSecurity": false,
  "views":[
    {
      "name": "All",
      "url": "http://<jenkins host>/"
    }
  ]
}
```
え？この程度の情報しか取得できないの、、、？
うーん、、、

# 情報収集、、

更に調査を進めた所、
クエリパラメータで情報量を操作できることがわかりました。

・depth
　　値を増やす事で、より深い階層情報を取得できるようになります。
　　例えば「1」と指定すると、job配下のdisplayName(ジョブ名称が入ってる)などが取得できるようになります。
　　あまり大きな値を入力すると、情報量が増えますが、それに比例して時間が、、、

・tree
　　指定する事で、取得する要素名でフィルタリングをかける事ができます。
　　depthを指定する際は情報量が増加するので、こちらも指定する事をお勧めします
　　ちなみにですが、同一要素名称が複数存在する場合、末に「s」をつける仕様のようです。

　　jobが複数ある→jobs
　　jobの中のdisplayNameを取りたい→jobs[displayName]
　　※カンマで区切ると複数指定が可能になります。

・xpath
　　指定した要素の内容でフィルタリングをかける事ができます。

色々ありましたが、自身の求める情報を取得する為のリクエストは以下になりました。
http://localhost:9090/api/xml?depth=2&tree=jobs[displayName,builds[number,result,actions[parameters[name,value]],timestamp]]&xpath=//job[displayName='testJob']

ただ、取得して分かったのですが、JenkinsのタイムスタンプってUNIXタイムスタンプなんですね、、
取得した値に以下の関数を通して、馴染みやすい形式(yyyy/MM/dd)に変換しちゃいましょう！

``` JavaScript
function convTimestamp(intTime) {
  var date = new Date(intTime);
  var year = date.getFullYear();
  var month = ('0'+(date.getMonth()+1)).slice(-2);
  var day = ('O'+date.getDate()).slice(-2);
  var hour = ('0'+date.getHours()).slice(-2);
  var min = ('O'+date.getMinutes()).slice(-2);

  return(year + '/' + month + '/' day + ' ' + hour + ':' + min);
}
```

ちなみにですが、無効なリクエストを投げると、、、、

![Jenkins.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386831/95723dd1-6524-a903-b204-23eba5994e72.png)

紳士的なイメージのjenkinsマスコットキャラ(名前不明)がメッチャ怒ります！
真面目なツールだと思っていたのですが、エンジニアの遊び心が伺えました！
やっぱり仕事は楽しくしたいですよね！

# webスクレイピング一覧化

必要な情報の取得方法が確認できたので、ajaxによるwebスクレイピングを行い、
取得・加工して一覧表示用のhtni文字列を作成しましょう！

今回は、画像の読み込み等がない、そして、ビルド毎で一覧をしたかったので、以下のコードになりました。

``` JavaScript
// html読み込み完了後に呼び出すよう設定
$(document).ready(function(){
  // 一覧表示
  getList();
});


// 一覧表示
function getList(){
  // 一覧取得
  $.ajax({
    type: "GET",
    dataType: "xml",
    url: "http://localhost:9090/api/xml?depth=2&tree=jobs[displayName,builds[number,result,actions[parameters[name,value]],timestamp]]&xpath=//job[displayNane='testJob']"
  ]).done(function (getData){

    // build要素数分繰り返し処理を実施
    $(getData).find("build").each(function(){
      // 実行日時の変換・取得
      convTimestamp(Number($(this).find("timestamp").text()));

      // パラメータは深い階層に格納されているので、
      // findを繰り返して取得する
      $(this).find("action").each(function(){
        $(this).find("parameter").each(function(){
          if($.inArray($(this).find("name").text(), Unnecessary) == -1){
            // naneとvalueの関係になっているので、以下のように取得し、
            // 配列かhtml文字列作成用変数に格納していく
            $(this).find("name").text();  //要素名
            $(this).find("value").text(); //要素値
          }
        });
      });
    });
  });

  // html書き換え
  // 挿入先のhtmlタグは、idを設定して記載しておく
  $("#挿入先のid").html("先ほど作成したhtml文字列");
};

// 個人的にリフレッシュ処理を行いたくなったので
// 一定間隔で繰り返し処理を行う「setIntervalメソッド」を組み込み、
// そこからも呼び出すようにする
$(function(){
  setInterval(function(){
    getList();
  }, 5000);
});
```
# 最後に
とりあえず、基本的なライブラリでもなんとかなる事がわかりました。
次は新しいツールも試してみたいと思います。