整形し、書き出す

Web

北海道コロナ感染状況のcsvをphpで整形し、JSONで書き出す

コロナウィルスが5類感染症に指定された5月中旬から、ほとんどのコロナウイルス関連のオープンデータが更新をやめてしまいました。そのため、自前で確認してきたサイトも更新されません。感染者数外出する目安に使ってきたので、これに類するデータはないか探してみることに。すると、北海道感染症情報センター2023年第19週よりCOVID-19の感染状況を週報として発行しています。そして、直近のみcsvデータを掲載していました。

北海道感染症情報センター|北海道立衛生研究所
北海道における感染症の発生状況など、感染症に関する様々な情報を提供しています。

これをうまいことJSONに変換できたら確認サイトを新たに作れるかもと思い、試行錯誤中です。フロントエンドはNuxt3で制作する予定。その前に元データを整形し、JSONデータを制作する作業を行おうと思い、作り方を検討することに。週報は週一更新なので、プログラムを定期的に動かす必要があります。それはCronで設定することにしました。下記サイトを参考に設定します。実際やってみるとメールを設定すれば、エラーの中身なども教えてくれるので便利だなと思いました。ちなみに、エックスサーバーでの設定なので、server id部分は各個人のserver idが入ります。

【定期実行】XserverでのCron設定 - Qiita
契約しているXserverでプログラムを定期実行し、Twitterのbotを作成しました。その際に設定したことを備忘録と…
/usr/bin/php8.0 /home/server id/sixwheel.net/public_html/covid19.sixwheel.net/実行ファイル名

さて、肝心のプログラムです。csvを見ながら、とりあえずCOVID-19の報告数定点あたりという指定の場所を抜き出し、phpでJSON形式のファイルを書き出すことにしました。色々なサイトを検索して参考にしています。それらを基本に、保存日のcsvもデータと照らし合わせたい時に便利かなと思い、念のため保存することに。そして、加工して、JSONファイルに書き出す形が下記で実行することできました。そうそう、エックスサーバーでは絶対パスでの階層の指定が重視され、相対パスで指定するとエラーが出ました。なので、/home/からの絶対パスで指定しています。週報のPDFとcsvでは上川の位置が異なっているので、途中でデータが変わるかもと思いながらも、楽するために決め打ちで連想配列のキーを指定しています。たまに、場所が変わっていることがあるので、そのあたりもケアしなければなりません。

<?php
$url = 'https://www.iph.pref.hokkaido.jp/kansen/weekunitdata.csv';
$path = '各々の保存先のpathをいれる';
$savePath = $path . 'download/';
$filename = 'covid19-'. date('Y-m-d') .'.csv';
$rawData = '';
$jsonFile = $path . 'covid19.json';

//csvをリネームし保存
if(!$savePath.$filename) {
  file_put_contents($savePath.$filename, file_get_contents($url));
}

$rawData = file($savePath.$filename);
$rawData = mb_convert_encoding($rawData, 'UTF-8', 'SJIS');
$csv_header = $rawData[0];
$csv_body = array_splice($rawData, 1);

//配列に変更
$arrayData = [];
foreach ($csv_body as $row) {
  $arrayData[] = explode(',', $row);
}
$cols1 = array_column($arrayData, 3);
$cols2 = array_column($arrayData, 4);
$keys = ['タイトル', '見出し', '全国', '北海道', '札幌', '小樽', '函館', '旭川', '江別', '千歳', '岩見沢', '滝川', '深川', '上川', '富良野', '名寄', '岩内', '倶知安', '江差', '渡島', '八雲', '室蘭', '苫小牧', '浦河', '静内', '帯広', '釧路', '根室', '中標津', '網走', '北見', '紋別', '稚内', '留萌'];
$name = ['name'];
$cols3[] = $csv_header;

//キーを追加
$value1 = array_combine($name, $cols3);
$value2 = array_combine($keys, $cols1);
$value3 = array_combine($keys, $cols2);

//jsonに追加
$jsonRaw = array($value1, $value2, $value3);
$writeJson = json_encode($jsonRaw, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);

//json読み込み
$readJson = file_get_contents($jsonFile);
$readJson = mb_convert_encoding($readJson, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');
$readJson = json_decode($readJson);

//ファイルが存在していないと初めて書き込み
if (!file_exists($jsonFile) || $readJson[0] === null) {
  file_put_contents($jsonFile, $writeJson);
}

$data1 = $jsonRaw[0]['name'];
$data2 = $readJson[count($readJson)-1][0]->name;

//既存jsonと比較し、nameが被ってなければ配列追加
if ($data1 !== $data2) {
  array_push($readJson, $jsonRaw);
  $readJson = json_encode($readJson, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
  file_put_contents($jsonFile, $readJson);
  print_r($data1);
  echo '<br />';
  print_r($data2);
  echo '<br />';
} else {
  print_r($data1);
  print_r('ダブリー');
}

直近しかcsvデータが無いため、それ以外のところは手入力しました。それほどの数じゃないからできましたが、PDFから数字を拾うということも検討する必要があるかもしれません。出来上がったJSONはこちらからダウンロードできます。

コメント