整形し、書き出す
北海道コロナ感染状況のcsvをphpで整形し、JSONで書き出す
コロナウィルスが5類感染症に指定された5月中旬から、ほとんどのコロナウイルス関連のオープンデータが更新をやめてしまいました。そのため、自前で確認してきたサイトも更新されません。感染者数を外出する目安に使ってきたので、これに類するデータはないか探してみることに。すると、北海道感染症情報センターが2023年第19週よりCOVID-19の感染状況を週報として発行しています。そして、直近のみcsvデータを掲載していました。
これをうまいことJSONに変換できたら確認サイトを新たに作れるかもと思い、試行錯誤中です。フロントエンドはNuxt3で制作する予定。その前に元データを整形し、JSONデータを制作する作業を行おうと思い、作り方を検討することに。週報は週一更新なので、プログラムを定期的に動かす必要があります。それはCronで設定することにしました。下記サイトを参考に設定します。実際やってみるとメールを設定すれば、エラーの中身なども教えてくれるので便利だなと思いました。ちなみに、エックスサーバーでの設定なので、server id部分は各個人のserver idが入ります。
/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はこちらからダウンロードできます。