はじめに

最近オフィスで仕事をしていると、たまに「異常にネットが遅い。。。」と感じるときがあります。
これは計測のしがいがありますね!!
Don’t guess! Measure!
というわけで、ネット回線のスピードテストを自動実行して視覚化してみました。


 

やったこと

  • speedtest-cliをcron実行
  • 結果を記録
  • 記録したデータをグラフにする

計測方法

本当はGoogleスピードテストをヘッドレスブラウザから叩くようにしたかったんですが、環境作るのに手間がかかりそうだったのでやめました。
今回利用したのは、speedtest-cliというCLIで実行できるツールです。
こちらはPython製ですが、Pythonのコードは一切書いていません。
ただ、Pythonの実行環境というかpipというパッケージ管理ツールが必要となります。
以前、Pythonの環境は整えていたので今回はスムーズに導入できました。
実行環境はCentOS6です。


speedtest-cliをインストール

pip install speedtest-cli

インストールが完了したらターミナルから

speedtest

と叩くだけで回線速度の計測ができます。
しかし、これだとpingから最適な計測サーバーを選択するらしく毎回違うサーバーにつながってしまいます。
同じサーバーにつなげて時間以外の条件を変えずに計測を行いたかったので、以下のオプションのようにして実行します。

speedtest --simple --server 14623

--simpleオプションは実行結果をシンプルに表示します。
--server 14623で東京サーバーを指定しています。
サーバーは世界中にあるのですが、日本のサーバーを利用したい場合は以下のようにすると一覧を表示できます。

speedtest --list|grep -i japan
14623) IPA CyberLab (Bunkyo, Japan) [2.57 km]
 6492) denpa893 (Sumida, Japan) [6.13 km]
15047) OPEN Project (via 20G SINET) (Tokyo, Japan) [6.15 km]
18838) BGP Network (Tokyo, Japan) [6.15 km]
20976) GLBB Japan (Tokyo, Japan) [6.15 km]
19256) Love4Taylor (Tokyo, Japan) [6.15 km]
 6508) at2wn (Yokohama, Japan) [28.67 km]
 8407) Allied Telesis Capital Corporation (Sagamihara, Japan) [36.44 km]
 6087) Allied Telesis Capital Corporation (Fussa-shi, Japan) [38.13 km]
 7139) SoftEther Corporation (Tsukuba, Japan) [48.03 km]
19038) poteitooo (Nagoya, Japan) [263.76 km]
 6766) JAIST(ino-lab) (Nomi, Japan) [300.32 km]
 6368) gatolabo (Maibara, Japan) [316.59 km]
 6476) rxy (individual) (Osaka, Japan) [401.52 km]
 6405) Allied Telesis Capital Corporation (Misawa, Japan) [573.40 km]
19915) CloudRemix(IDCF) (Kitakyushu, Japan) [834.67 km]
18709) extride inc (Hitoyoshi, Japan) [914.25 km]
  811) GLBB Japan KK (Chatan, Japan) [1543.58 km]
 6581) haza (Haebaru, Japan) [1556.20 km]
21118) GLBB Japan (Naha, Japan) [1557.98 km]

シンプル表示で実行すると以下のような結果が表示されます。

speedtest --simple --server 14623
Ping: 32.296 ms
Download: 79.92 Mbit/s
Upload: 92.78 Mbit/s

計測結果を記録してグラフにする



ここまでで、ネット回線の速度は計測ができました。
続いてこちらを記録してグラフにします。
ここから急にPHPになりますがご容赦ください。

<?php

$now = date('Y-m-d H:i:s');
$result = array();
exec("speedtest --simple --server 14623", $result);

if (!$result) {
    exit;
}

// あとはcsvファイルとして記録する
$csv = implode(",", $result);
$fileName = "speedtest.csv";
$fp = fopen($fileName, "a");
fwrite($fp, $csv . ',' . $now);
fwrite($fp, "\n");
fclose($fp);

シェルでやるのが面倒くさかったので、PHPからexecで叩いてcsvファイルに記録することにしました。
こちらのPHPをcronに登録して15分毎に計測していきます。
1日あればそこそこデータとれます。
データが貯まったらcsvファイルをスプレッドシートに投げてグラフを表示します。






※実データだとまずい気がしたので、グラフは一部加工しています。


まとめ

実際に計測してみると、やはり夕方から夜にかけてどんどん速度が落ちていることがわかりました。
感覚で遅くなったと言ってもなかなか改善に動いてくれる人は少ないですが、数字とかグラフで視覚化するとあっさり動いてくれたりします。
speedtest-cliはWindowsでもPythonをインストールすれば動きますので、ネット回線の速度を計測したい人は試してみると良いと思います。
それでは、快適なネットライフを。


15. 10月 2018 · Write a comment · Categories: PHP · Tags: ,



はじめに

私の職場があるビルはいわゆるランドマークタワーで、地元ではこの中で働いているというだけで何故か信頼を得られるのですが、実際は空調が一元管理されておりあまり融通が効かず快適な職場とは言えません。
そこで導入されたのが NETATMO ウェザーステーションです。
こちらを使って気温や CO2 濃度の計測をして、社内で決められた値を超えたら管理部門に電話をするようになりました。
しかし、この情報は NETATMO 専用の Web サイトにアクセスして確認しなければならず、忙しい業務中に確認するというのは現実的ではありませんでした。
そこで今回、NETATMO API から気温・CO2 を取得し社員が頻繁に見ている社内管理ツール上に表示するようにしてみました。


 

やりたいこと

  • NETATMO API から情報を取得

NETATMO CONNECT に登録

NETATMO API を利用するするにはアプリケーションの登録が必要となります。NETATMO CONNECT に登録をします。
※NETATMO ウェザーステーションをすでに利用している前提の話です。


netatmo connect



必須項目は2018年10月現在、以下3つです。それぞれ入力します。

  • Name
    • 作成するアプリ名です
    • 深く考える必要はありません。私は「officeAtmo」としました。
  • Description
    • アプリの説明です
    • これも深く考える必要はありません。私は「管理ツール用」としました。
  • Data Protection Officer name
    • データ保護責任者の名前
    • 会社組織の場合、該当者がいるはずですのでその方の名前を入れます
    • 事前に確認了承を得てください

登録が完了すると TECHNICAL PARAMETERS の登録となりますが、こちらは特になにも入力しなくて大丈夫です。
ただし、表示されている Client id と Client secret は API で使います。


technical param




これで事前準備は完了です。ここからは実際に API を叩いてみます。


実装

私は PHPer なので PHP での実装となります。
とりあえずコード貼ります。


<?php
// NETATMO CONNECT に登録した内容で認証 API を curl で叩く
$netatmoAuth = array(
    'client_id'     => CLIENT_ID,
    'client_secret' => CLIENT_SECRET,
    'grant_type'    => 'password',
    'username'      => MAIL_ADDRESS,
    'password'      => PASSWORD,
);
$url = 'https://api.netatmo.com/oauth2/token';
// 自作 curl ライブラリ
$requestObj = new CurlHttpRequest($url, $netatmoAuth);
$timeOutSecond = 30;
// POST で
$response = $requestObj->post($timeOutSecond);

// 例外処理は適宜入れてください

// 認証情報が json で返ってくるので decode する
$response = json_decode($response['body'], true);

// 取得した認証情報のアクセストークンを使って現在のウェザーステーション情報を取得
$url = "https://api.netatmo.com/api/getstationsdata?access_token={$response['access_token']}";
$requestObj = new CurlHttpRequest($url);
$timeOutSecond = 30;
// 今度は GET で
$response = $requestObj->get($timeOutSecond);
$response = json_decode($response['body'], true);
// 気温
$netatmo['temperature'] = $response['body']['devices'][0]['dashboard_data']['Temperature'];
// CO2 濃度
$netatmo['co2'] = $response['body']['devices'][0]['dashboard_data']['CO2'];
// 湿度
$netatmo['humidity'] = $response['body']['devices'][0]['dashboard_data']['Humidity'];


Netatmo API へのアクセスは curl で行っていますが上記の例では自作の curl ラッパークラスを使っていますので、適宜ご自身の環境で書き換えてください。
まずは認証を通過する必要があるので、認証 API を叩いています。今回は閉じた環境でサクッと利用するために簡易的な方法をとっています。
grant_type に password を指定して、NETATMO CONNECT に登録した内容と取得した Client id と Client secret で POST リクエストを送ります。
認証結果が json で返却され、中にアクセストークンが含まれています。
続いてアクセストークンを使って現在のウェザーステーション情報を取得します。
こちらも json で結果が返ってくるので、その中から必要な部分を抜き出します。今回は気温・CO2濃度・湿度を社内の管理画面に表示させてみました。


まとめ

実際の管理画面はお見せできませんが、これで気になったときにすぐオフィスの快適度が数値として分かるようになりました。
まあ、そこから管理部門に電話しなきゃいけないんですけどね。。。ハードル高すぎ。。。
では快適な職場ライフを。。。




はじめに

ググるとたくさん出てくるのでご存知かとは思いますが、Instagram には API があります。また、こちらもご存知かとは思いますが Instagram API の利用申請許可が降りる可能性は極めて低いです。昨今のインスタブームに乗っかって Instagram を利用したい経営者は多数いるかと思いますが、正規の方法での利用は諦めたほうがいいでしょう。また、Instagram のスクレイピングは規約で禁止されていますのでスクレイピングで実装を支持されたエンジニアの方はその旨を伝えて拒否しましょう。

不正な方法を用いて、アカウントの作成、情報へのアクセス、または情報の取得を試みることは禁止されています。
これには、弊社から明示的な許可を得ることなく、自動化された手段を用いてアカウントを作成したり、情報を取得したりする行為が含まれます。

とはいえ、Instagram のスクレイピング自体はお勉強の題材としては良いかと思いますので、少しだけ実装をしてみました。以下の内容は自己責任の範囲でご確認ください。

 

やりたいこと

  • Instagram のハッシュタグ検索をスクレイピング
    • 最新投稿の本文を取得
    • ハッシュタグ検索結果件数を取得

実装

私は PHPer なので PHP での実装となります。
とりあえずコード貼ります。


<?php
// 検索対象ハッシュタグ
$tagList = array(
    'インスタ映え',
    'インスタ萎え',
);
foreach ($tagList as $tag) {

    // Instagram へアクセス
    $encodedTag = urlencode($tag);
    $url = "https://www.instagram.com/explore/tags/{$encodedTag}/";
    // 自作の curl ライブラリ
    $requestObj = new CurlHttpRequest($url);
    $timeOutSecond = 30;
    $instagramContentsResponse = $requestObj->get($timeOutSecond);
    
    // タイムアウト処理等は適宜いれてください

    // レスポンスから必要な json 部分を抜き出す
    $instagramContentsResponse = $instagramContentsResponse['body'];
    $positionStart = mb_strpos($instagramContentsResponse, 'window._sharedData = ');
    $positionEnd = mb_strpos($instagramContentsResponse, ';</script>');
    $length = $positionEnd - $positionStart;
    $json = mb_substr($instagramContentsResponse, $positionStart, $length);
    $json = str_replace('window._sharedData = ', '', $json);
    $jsonObj = json_decode($json);
    $infoListObj = $jsonObj->entry_data->TagPage[0]->graphql->hashtag->edge_hashtag_to_media->edges;
    foreach ($infoListObj as $index => $infoObj) {
        // Instagram 投稿 ID ?
        $infoObj->node->shortcode;
        // 投稿日時
        $stamp = date('Y-m-d H:i:s', $infoObj->node->taken_at_timestamp);
        // 投稿本文
        $text = $infoObj->node->edge_media_to_caption->edges[0]->node->text;
    }
    // ハッシュタグ検索結果件数
    $instagramPostCount = $jsonObj->entry_data->TagPage[0]->graphql->hashtag->edge_hashtag_to_media->count;
}


Instagram へのアクセスは curl で行っていますが上記の例では自作の curl ラッパークラスを使っていますので、適宜ご自身の環境で書き換えてください。
GET でアクセスできれば、file_get_contents でもなんでも構いません。
取得したレスポンスから JavaScript の部分に必要な情報が入っていますので、その部分を抜き出します。
また、データは JSON 形式になっていたため json_decode しています。
あとは必要な情報へアクセスして DB に保存するなど煮るなり焼くなり。。。
もし、文字化けする場合はサーバーの設定か PHP の文字コード設定を見直してみてください。

まとめ

今回は Instagram ハッシュタグ検索のスクレイピングを試しましたが、同じ要領で個別の投稿のスクレイピングもできるかと思います(未検証)。
このデータを収集して機械学習用のデータにすると面白いかもしれないと思いました。
ただし、冒頭にも記載しましたが Instagram の利用規約に抵触する可能性が高いので自己責任の範囲で行ってください。
上記内容の利用に関して筆者は一切の責任を負いません。
では、楽しいインスタライフを。

05. 8月 2015 · Write a comment · Categories: PHP · Tags:

PHP$_SERVER 変数でリクエストのページ内リンク (アンカータグ) を取得しようとして散々悩んでいました。
結論から言うと取得出来ません。

parse_url()を使用する例をネットで見かけますが、それはまた別な話です。
アクセス先情報は $_SERVER 変数を使用すれば取得できます。

$url = $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
こんな感じですね。



この $_SERVER[‘REQUEST_URI’] にはページ内リンク部は含まれません。
ページ内リンクは、ブラウザに取って必要な情報でサーバ側には必要ない情報ですから。

先述した、parse_url()を使用できるのは下記のような時です。



$url = 'http://www.hoge.jp/hogehoge#anc';
var_dump(parse_url($url));
まあね、実際こんなことしないですよね。
何の意味があるのか分からないですよこんなの。

どうしても、実行中 URL からアンカー部を抽出したい場合は、レンダリング後に Javascript でやるしか無いですね。
割りと必要な機能だと思うので、PHP が取り込んでくれたらいいなと思ってます。
……ないかな。

それでは。

29. 1月 2015 · Write a comment · Categories: PHP · Tags:

お仕事でレスポンスprintして、それを受け取った先方が処理をする案件がありました。こっちとしては処理が成功したらprintするだけなので余裕かと思っていたら思わぬ落とし穴がありました。

先頭に改行コードが入ってるんですが





どういうことだ?と思いましたが、蓋を開けてみたら話は単純でした。includeしているPHPファイルの先頭改行が入っていました。

 
<?php

PHPタグの前に改行が入ると出力されてしまうようです。こんな単純なミスですが、一度ハマるとなかなか抜け出せないので、ファイルを新たに作る時は先頭に改行が入らないよう気を付けます。

…新卒だから許してください。

それでは。

31. 12月 2014 · Write a comment · Categories: PHP · Tags: ,

社内のチームチャットツールとしてSlackを導入しました。
Slackの詳細についてはググればいくらでも出てくるので、そちらにお任せします。

ただ、ググってもAPIを使用してSlackbotに発言をさせる具体的な方法が出てこなかったので、紹介したいと思います。
まあ、POSTするだけなんですけどね。


まずテストしてみようとHTMLフォームを作ってPOSTしてみましたが、動作しませんでした。
HTMLからPOSTしてテストしようとしている方はご注意ください。動きません。最初からコードを書いてください。

コードはPHPで書いています。

IntegrationsにSlackbotが追加されていることを確認します。
integrations

Slackbotを選択すると設定画面が表示されます。
ここのURLに対してPOSTで送信するだけです。

url


$client = new HTTP_Client();
$client->post(
    "https://YOUR_TEAM/services/hooks/slackbot?token=TOKEN&channel={$channel}", 
    $message, 
    true
);

第一引数にSlackbot設定画面のURLを指定します。
このとき、Slack上のどのチャンネルで発言させるかをchannelパラメータに「#」付きで指定します。例えばgeneralチャンネルで発言させたければ、
https://YOUR_TEAM/services/hooks/slackbot?token=TOKEN&channel=#general
とします。
もちろん、上記URLのYOUR_TEAMとTOKENの部分は自分のSlack設定に合わせて変更してください。

第二引数にはSlackbotに発言させる文章を指定します。
使い方はいろいろあるかと思いますが、SQLがエラーを出した時にそのSQLとエラーを取得してPOSTするとかですかね。

さすがに上記コードをそのまま使おうと思われる方はいないと思いますので、クラスを作成して使いやすくしてください。

簡易的ではありますが、必要なときに必要な情報をSlackに通知させるにはこれで十分かと思います。
ご自分のサービスで使いドコロを考えて適切に通知させれば、イロイロと捗りますので是非お試しあれ。

それでは。