はじめに
このプログラムについて
岐阜県から公開されたオープンデータ(csv)を、
・github actionsで定期的にスクレイピングし、
・単純な辞書配列として、無編集状態でjsonファイルを出力
・差分があればgh-pagesブランチにpush
・github pagesで直接jsonファイルにアクセスできる
プログラムです。
公開の経緯
岐阜県コロナウイルス対策サイト開発にあたり、本プログラムを開発。
他の事例でも公開されていますが、csv->json出力するにあたって加工処理が入っており、
参考にするには修正が多く必要でした。
そこで、本プログラムでは最小限の加工にとどめ、もとのcsvデータをそのままjson出力できるような形式にすることで、他の開発者が開発しやすくしています。
Product
Github
Github pagesでのJson出力
http://code-for-gifu.github.io/covid19-scraping/patients.json
http://code-for-gifu.github.io/covid19-scraping/testcount.json
http://code-for-gifu.github.io/covid19-scraping/callcenter.json
http://code-for-gifu.github.io/covid19-scraping/advicecenter.json
参考CSVファイル
岐阜県オープンデータ
https://data.gifu-opendata.pref.gifu.lg.jp/dataset/c11223-001
how to use
Github上で動作させる
起動方法
- 自分の環境にfork
- github/workflows/main.ymlに記載されたアクションが定時(10分毎)に自動で起動します
- 手動実行はできません
停止方法
-
.github/workflows/main.yml
を削除する
もしくは、 -
.github/workflows/main.yml
の、以下の3行をコメントアウトする
on:
schedule:
- cron: "*/10 * * * *”
Github Pagesでのホスティング
-
Settings
->Github Pages
->Source
でgh-pages branch
を選択。
詳細は、github actionの公式ドキュメントを参考にしてください。
https://help.github.com/ja/actions
ローカル環境での実行
pip install -r requirements.txt
python3 main.py
/data
フォルダにjsonファイルが生成されます。
技術文書
※コード全体はgithubのソースコードを参照してください
python
メイン
os.makedirs('./data', exist_ok=True)
for remotes in REMOTE_SOURCES:
data = import_csv_from(remotes['url'])
dumps_json(remotes['jsonname'], data)
- 別ファイルで定義したcsvリストをすべて読み込み、jsonファイルを出力する
データ定義部
# 外部リソース定義
REMOTE_SOURCES = [
{
'url': 'https://opendata-source.com/source1.csv',
'jsonname': 'source1.json',
},
{
'url': 'https://opendata-source.com/source2.csv',
'jsonname': 'source2.json',
},
{
'url': 'https://opendata-source.com/source3.csv',
'jsonname': 'source3.json',
},
{
'url': 'https://opendata-source.com/source4.csv',
'jsonname': 'source4.json',
}
]
-
url
:参照しているcsvのリンクを貼る -
json_name
:出力されるjsonファイル名称
csv読み込み部
def import_csv_from(csvurl):
request_file = urllib.request.urlopen(csvurl)
if not request_file.getcode() == 200:
return
f = decode_csv(request_file.read())
filename = os.path.splitext(os.path.basename(csvurl))[0]
datas = csvstr_to_dicts(f)
timestamp = (request_file.getheader('Last-Modified'))
return {
'data': datas,
'last_update': dateutil.parser.parse(timestamp).astimezone(JST).isoformat()
}
- csvのアクセスは
urllib
を活用している。 -
data
:csvをデコードしたデータそのものを格納する。 -
last_update
:ファイルの最終更新日付を取得。
csvデコード部
def decode_csv(csv_data):
print('csv decoding')
for codec in CODECS:
try:
csv_str = csv_data.decode(codec)
print('ok:' + codec)
return csv_str
except:
print('ng:' + codec)
continue
print('Appropriate codec is not found.')
- 別ファイルで定義したコーデックを順番に試す
csv→jsonデータ変換部
def csvstr_to_dicts(csvstr):
datas = []
rows = [row for row in csv.reader(csvstr.splitlines())]
header = rows[0]
for i in range(len(header)):
for j in range(len(UNUSE_CHARACTER)):
header[i] = header[i].replace(UNUSE_CHARACTER[j], '')
maindatas = rows[1:]
for d in maindatas:
# 空行はスキップ
if d == []:
continue
data = {}
for i in range(len(header)):
data[header[i]] = d[i]
datas.append(data)
return datas
- CSV文字列を[dict]型に変換
- keyとして使用できない文字を単純置換削除
jsonデータ出力部
def dumps_json(file_name: str, json_data: Dict):
with codecs.open("./data/" + file_name, "w", "utf-8") as f:
f.write(json.dumps(json_data, ensure_ascii=False,
indent=4, separators=(',', ': ')))
- 日本語文字化け対策などを施したdump jsonキット
Github Action
ymlファイルで構築している。
スケジュール
on:
schedule:
- cron: "*/10 * * * *”
- 定期実行。現在は10分間隔
pythonスクリプト実行部
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run script
run: |
python main.py
- python環境を
requirements.txt
に記載、自動でインストール - インストール後、自動でmain.pyを起動
gh-pagesにpush
- name: deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./data
publish_branch: gh-pages
- 実行結果のjsonファイルを特定のブランチに自動的にpushする
-
secrets.GITHUB_TOKEN
は自分自身を表す -
publish_dir
は出力するフォルダの設定。jsonファイルを出力するdata
フォルダを指定。 -
publish_branch
はpushするbranchを指定
参考文献
北海道:スクレイピング用Pythonスクリプト - covid19hokkaido_scraping
https://github.com/Kanahiro/covid19hokkaido_scraping/blob/master/main.py