Code Monkey home page Code Monkey logo

fukui-opendata-gomisyusyubi-json's Introduction

福井県オープンデータ ごみ収集日一覧CSVをJSONに変換するツール

福井県オープンデータライブラリ」で公開されている、県内17市町の「ごみ収集日一覧」データの形式を、CSV(Shift-JIS)からJSONに変換します。

Description

樹里「というわけで、福井県内自治体のごみ収集日一覧JSONデータを作成するアプリを作ってみた」
絵子「ほう。なんでまた突然」
樹里「それがな、久しぶりに福井県オープンデータに公開されてるデータを使って、アプリでも作ってみようとしたんだがな」
絵子「福井県は昔からオープンデータの公開に熱心だよね」
樹里「で、ごみ収集日一覧のデータを見てみたんだが、なんとShift-JISのCSVなんだよ。この令和の時代に」
絵子「うーん。確かにそのままだと扱いにくいよね」
樹里「Shift-JISのCSVなんだよ。この令和の時代に
絵子「2回言わなくていいよ。あと太字にしなくてもいいよ」
樹里「これではどうしようもないので、まずはちゃんとしたUTF-8のJSONに変換するツールから作ってみたわけだ」
絵子「なるほど。経緯はよくわかった」

Usage

樹里「使い方は簡単。Node.js製のアプリなので……」

git clone https://github.com/8amjp/fukui-opendata-gomisyusyubi-json.git
cd fukui-opendata-gomisyusyubi-json
npm install

樹里「上記のコマンドでインストールして、」

node index.js

樹里「と実行すれば、distディレクトリにJSONデータが出力される」
絵子「あら本当に簡単」
樹里「じゃあ、アプリがどういう動きをするのか解説しよう」

index.js

樹里「まずは、メインとなるコードだ」

/*
  「福井県オープンデータライブラリ」の「ごみ収集日一覧」ページで公開されている
  収集日のCSVデータ(Shift-JIS)をJSONに変換します。
*/

const scraper = require('./lib/scraper');
const generator = require('./lib/generator');
const page = 'https://www.pref.fukui.lg.jp/doc/toukei-jouhou/opendata/list_ct_gomisyusyubi.html'; // 「ごみ収集日一覧」ページのURL

(async () => {
    // ページ内の17市町のCSVデータのURLを取得
    const resources = await scraper.scrape(page)
    // すべてのCSVを取得してJSONに変換して出力
    await Promise.all(resources.map(resource => generator.generate(resource)))
    console.log('できたよ!')
})();

絵子「scrapergeneratorっていうのが、樹里が作ったモジュール?」
樹里「そう。scraperで「ごみ収集日一覧」ページからCSVへのリンクを取得している。で、generatorでCSVを取得してJSONに変換している」
絵子「なるほど」
樹里「では、各モジュールの動きをみてみよう」

lib/scraper.js

樹里「次に、ページをスクレイピングして、CSVへのリンクを取得するscraperモジュールだ」

/*
  指定されたページ内の、CSVへのリンクをを取得します。
*/
const fetch = require('node-fetch');
const cheerio = require('cheerio');
const url = require('url');

module.exports.scrape = async (page) => {
    // 指定されたページのHTMLを取得する
    const response = await fetch(page)
    const body = await response.text()
    // cheerioでページをスクレイピング
    const $ = await cheerio.load(body)
    // 末尾が'.csv'のリンクをすべて取得
    const relativePaths = await $('a[href$=".csv"]').map((i, el) => $(el).attr('href')).get()
    // 絶対パスに変換
    const absolutePaths = await relativePaths.map(path => url.resolve(page, path))
    return absolutePaths
}

樹里「スクレイピングにはcheerioというライブラリを使用している」
絵子「知ってる。jQueryっぽく操作できるやつだよね」
樹里「そう。そのcheerioで、属性セレクターを使って、href属性 が ".csv" で終わるa要素、すなわちCSVへのリンクを取得してだな、その配列を返している」
絵子「なるほど」

lib/generator.js

樹里「最後に、データの変換を行うgeneratorモジュールだ」

/*
  指定されたURLのCSVを取得し、文字コードをShift-JISからUTF-8にに変換して出力します。
*/
const path = require('path');
const fs = require('fs-extra');
const fetch = require('node-fetch');
const parse = require('csv-parse/lib/sync');

module.exports.generate = async (resource) => {
    // ファイル名を生成
    const file = path.basename(resource, '.csv') + '.json'
    // 指定されたURLのCSVを取得
    const response = await fetch(resource)
    const buffer = await response.arrayBuffer()
    // CSVの文字コードをShift-JISからUTF-8にに変換
    const decoder = new TextDecoder("Shift_JIS")
    const csv = decoder.decode(buffer)
    // CSVをJSONに変換
    const json = await parse(csv, { columns: true, trim: true })
    // JSONを出力
    const result = await fs.outputJson(path.join('dist', file), json, { spaces: 4 })
    return result
};

樹里「まず、node-fetchでCSVを取得して、Shift-JISからUTF-8に変換する」
絵子「へー、TextDecoderっていうので文字コードを変換できるんだね」
樹里「で、csvというライブラリのcsv-parseという機能を使って、CSVをJSONに変換しているわけだ」
絵子「便利なライブラリだねー」

樹里「さて、処理の結果、このようなJSONが出力される」

[
    {
        "行": "",
        "音": "",
        "町名": "在田町",
        "読み": "あいだ",
        "燃える": "火・金",
        "燃えない": "2・4木",
        "プラスチック製容器包装": "",
        "カン": "1・3水",
        "ビン": "4水",
        "ペットボトル": "2水",
        "ダンボール": "3水",
        "蛍光灯": "4木",
        "キーワード": "清水",
        "備考": "清水南"
    },
    // 以下略

絵子「これ、キーが日本語になってるけど問題ないの?」
樹里「ああ、仕様に則った正しいJSONだぞ」
絵子「へー、そうなんだ」
樹里「なにより、Shift-JISのCSVよりははるかに扱いやすい」
絵子「よっぽどキライなんだね」


樹里「……さて、無事にShift-JISのCSVをJSONに変換できた」
絵子「めでたしめでたし、だね」
樹里「いやいや、データの形式を変換しただけで、何も出来上がってないぞ。大事なのは、このデータを使ってどんなアプリを作るかだ」
絵子「そりゃそうだ。さ、次はアプリ制作に挑戦だ!」

Author

8amjp

fukui-opendata-gomisyusyubi-json's People

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.