Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
日本のCOVID-19接触確認のデータを取得して、アイテムを見る。
import urllib
import json
import datetime
import requests, zipfile, io
import collections
import pprint
import export_pb2
import math
# 曝露通知情報を取得する。
# 辞書の配列を取得する。辞書のキーは、region, url, created。
# createdはUTCのエポックタイム、単位はミリ秒。
def getENItemList():
# list.jsonを取得する。
url = 'https://covid19radar-jpn-prod.azureedge.net/c19r/440/list.json'
body = urllib.request.urlopen(url).read()
# 曝露通知情報のZIPファイルのリストを取得する。
enList = json.loads(body)
return enList
# ZIPアーカイブを取得して、その中のexport.binを返す。
# https://stackoverflow.com/questions/9419162/download-returned-zip-file-from-url
def getExposureBin(zip_url):
r = requests.get(zip_url)
z = zipfile.ZipFile(io.BytesIO(r.content))
return z.read("export.bin")
# ZIPアーカイブを取得して、その中のキー情報 TemporaryExposureKeyExport を返す。
# バッファの詳細:
# https://developer.apple.com/documentation/exposurenotification/setting_up_an_exposure_notification_server
def getTemporaryExposureKeyExport(zip_url):
# ZIPアーカイブから、export.binを取得する。
ebin = getExposureBin(zip_url)
# 先頭16バイトのヘッダ文字列と、メッセージ本体に分離する。
header = ebin[:16]
message = ebin[16:]
# メッセージのデシリアライズ。
export = export_pb2.TemporaryExposureKeyExport()
export.ParseFromString(message)
return export
# xx月xx日、の文字列を返す。
#def getDateString(enItem):
# createdAt = datetime.datetime.fromtimestamp(enItem["created"] / 1000)
# return f"{createdAt.month}月{createdAt.day:02d}日"
def getDateString(epochSeconds):
createdAt = datetime.datetime.fromtimestamp(epochSeconds)
return f"{createdAt.month}{createdAt.day:02d}{createdAt.hour}時"
enList = getENItemList()
keyCount = 0
# 2020年7月29日から、COVID-19のキー配布サーバが、毎次0時に処理を開始するようになった。このため0時以降に前日分のキー数をカウントする。
# 7月30日時点で、日中にキー配布が実行されている。日中に適時キー配布が行われ、午前0時に前日の未配布分が配布される振る舞いだと前提する。
# これの処理フローは、午前1時あたりに、このスクリプトが実行されるものとする。その実行日のキーはまだ配布されていないから:
# サーバ発行日が前日であれば、キーの発行びが前日であるキー数を、登録者数に加算する。
# サーバ発行日が現在の日にちであれば、キーの日付が前日であるキー数を、登録者数に加算する。
previousDateTime = datetime.datetime.now() + datetime.timedelta(days=-1)
nowDateTime = datetime.datetime.now()
for enItem in enList:
# 作成日が前日もしくは今日のものをフィルタリングする。アイテムの作成時間は、エポック時間、単位はミリ秒。
createdAt = datetime.datetime.fromtimestamp(enItem["created"] / 1000)
# print(createdAt)
if (createdAt.month == previousDateTime.month and createdAt.day == previousDateTime.day) or (createdAt.month == nowDateTime.month and createdAt.day == nowDateTime.day):
# ZIPファイルを読み込む。キーのタイムスタンプを取得する。
zip_url = enItem["url"]
export = getTemporaryExposureKeyExport(zip_url)
end_datetime = datetime.datetime.fromtimestamp(export.end_timestamp)
# キーのタイムスタンプが前日であれば、登録者数に加算する。
if end_datetime.month == previousDateTime.month and end_datetime.day == previousDateTime.day:
# deltaDays = math.ceil((export.end_timestamp - export.start_timestamp) / ( 60 * 60 * 24)) # 期間の日数
# print(f"start:{getDateString(export.start_timestamp)} end:{getDateString(export.end_timestamp)} days:{deltaDays} count:{len(export.keys)} {export}")
# keyCount += len(export.keys) / deltaDays
keyCount += len(export.keys)
# 結果を出力する。
print(f"{previousDateTime.month}{previousDateTime.day:02d}{keyCount}")
syntax = "proto2";
message TemporaryExposureKeyExport {
// Time window of keys in the file, based on arrival
// at the server, in UTC seconds.
optional fixed64 start_timestamp = 1;
optional fixed64 end_timestamp = 2;
// Region from which these keys came (for example, MCC).
optional string region = 3;
// Reserved for future use. Both batch_num and batch_size
// must be set to a value of 1.
optional int32 batch_num = 4;
optional int32 batch_size = 5;
// Information about associated signatures.
repeated SignatureInfo signature_infos = 6;
// The temporary exposure keys themselves.
repeated TemporaryExposureKey keys = 7;
}
message SignatureInfo {
// App Store app bundle ID.
optional string app_bundle_id = 1;
// Android app package name.
optional string android_package = 2;
// Key version in case the EN server signing key is rotated.
optional string verification_key_version = 3;
// Three-digit mobile country code (MCC) for validating the key file.
// If a region has more than one MCC, the server can choose
// which MCC to use. This value does not have to match the client's MCC,
// but must correspond to one of the supported MCCs for its region.
optional string verification_key_id = 4;
// All keys must be signed using the SHA-256 with ECDSA algorithm.
// This field must contain the string "1.2.840.10045.4.3.2".
optional string signature_algorithm = 5;
}
message TemporaryExposureKey {
// Temporary exposure key.
optional bytes key_data = 1;
// Varying risk associated with a key depending on the diagnosis method.
optional int32 transmission_risk_level = 2;
// Number representing the beginning interval for temporary exposure
// key validity (ENIntervalNumber).
optional int32 rolling_start_interval_number = 3;
// Number of intervals in a period.
optional int32 rolling_period = 4 [default = 144];
}
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: export.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name='export.proto',
package='',
syntax='proto2',
serialized_options=None,
create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x0c\x65xport.proto\"\xd1\x01\n\x1aTemporaryExposureKeyExport\x12\x17\n\x0fstart_timestamp\x18\x01 \x01(\x06\x12\x15\n\rend_timestamp\x18\x02 \x01(\x06\x12\x0e\n\x06region\x18\x03 \x01(\t\x12\x11\n\tbatch_num\x18\x04 \x01(\x05\x12\x12\n\nbatch_size\x18\x05 \x01(\x05\x12\'\n\x0fsignature_infos\x18\x06 \x03(\x0b\x32\x0e.SignatureInfo\x12#\n\x04keys\x18\x07 \x03(\x0b\x32\x15.TemporaryExposureKey\"\x9b\x01\n\rSignatureInfo\x12\x15\n\rapp_bundle_id\x18\x01 \x01(\t\x12\x17\n\x0f\x61ndroid_package\x18\x02 \x01(\t\x12 \n\x18verification_key_version\x18\x03 \x01(\t\x12\x1b\n\x13verification_key_id\x18\x04 \x01(\t\x12\x1b\n\x13signature_algorithm\x18\x05 \x01(\t\"\x8d\x01\n\x14TemporaryExposureKey\x12\x10\n\x08key_data\x18\x01 \x01(\x0c\x12\x1f\n\x17transmission_risk_level\x18\x02 \x01(\x05\x12%\n\x1drolling_start_interval_number\x18\x03 \x01(\x05\x12\x1b\n\x0erolling_period\x18\x04 \x01(\x05:\x03\x31\x34\x34'
)
_TEMPORARYEXPOSUREKEYEXPORT = _descriptor.Descriptor(
name='TemporaryExposureKeyExport',
full_name='TemporaryExposureKeyExport',
filename=None,
file=DESCRIPTOR,
containing_type=None,
create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='start_timestamp', full_name='TemporaryExposureKeyExport.start_timestamp', index=0,
number=1, type=6, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='end_timestamp', full_name='TemporaryExposureKeyExport.end_timestamp', index=1,
number=2, type=6, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='region', full_name='TemporaryExposureKeyExport.region', index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='batch_num', full_name='TemporaryExposureKeyExport.batch_num', index=3,
number=4, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='batch_size', full_name='TemporaryExposureKeyExport.batch_size', index=4,
number=5, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='signature_infos', full_name='TemporaryExposureKeyExport.signature_infos', index=5,
number=6, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='keys', full_name='TemporaryExposureKeyExport.keys', index=6,
number=7, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=17,
serialized_end=226,
)
_SIGNATUREINFO = _descriptor.Descriptor(
name='SignatureInfo',
full_name='SignatureInfo',
filename=None,
file=DESCRIPTOR,
containing_type=None,
create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='app_bundle_id', full_name='SignatureInfo.app_bundle_id', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='android_package', full_name='SignatureInfo.android_package', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='verification_key_version', full_name='SignatureInfo.verification_key_version', index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='verification_key_id', full_name='SignatureInfo.verification_key_id', index=3,
number=4, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='signature_algorithm', full_name='SignatureInfo.signature_algorithm', index=4,
number=5, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=229,
serialized_end=384,
)
_TEMPORARYEXPOSUREKEY = _descriptor.Descriptor(
name='TemporaryExposureKey',
full_name='TemporaryExposureKey',
filename=None,
file=DESCRIPTOR,
containing_type=None,
create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='key_data', full_name='TemporaryExposureKey.key_data', index=0,
number=1, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=b"",
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='transmission_risk_level', full_name='TemporaryExposureKey.transmission_risk_level', index=1,
number=2, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='rolling_start_interval_number', full_name='TemporaryExposureKey.rolling_start_interval_number', index=2,
number=3, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='rolling_period', full_name='TemporaryExposureKey.rolling_period', index=3,
number=4, type=5, cpp_type=1, label=1,
has_default_value=True, default_value=144,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto2',
extension_ranges=[],
oneofs=[
],
serialized_start=387,
serialized_end=528,
)
_TEMPORARYEXPOSUREKEYEXPORT.fields_by_name['signature_infos'].message_type = _SIGNATUREINFO
_TEMPORARYEXPOSUREKEYEXPORT.fields_by_name['keys'].message_type = _TEMPORARYEXPOSUREKEY
DESCRIPTOR.message_types_by_name['TemporaryExposureKeyExport'] = _TEMPORARYEXPOSUREKEYEXPORT
DESCRIPTOR.message_types_by_name['SignatureInfo'] = _SIGNATUREINFO
DESCRIPTOR.message_types_by_name['TemporaryExposureKey'] = _TEMPORARYEXPOSUREKEY
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
TemporaryExposureKeyExport = _reflection.GeneratedProtocolMessageType('TemporaryExposureKeyExport', (_message.Message,), {
'DESCRIPTOR' : _TEMPORARYEXPOSUREKEYEXPORT,
'__module__' : 'export_pb2'
# @@protoc_insertion_point(class_scope:TemporaryExposureKeyExport)
})
_sym_db.RegisterMessage(TemporaryExposureKeyExport)
SignatureInfo = _reflection.GeneratedProtocolMessageType('SignatureInfo', (_message.Message,), {
'DESCRIPTOR' : _SIGNATUREINFO,
'__module__' : 'export_pb2'
# @@protoc_insertion_point(class_scope:SignatureInfo)
})
_sym_db.RegisterMessage(SignatureInfo)
TemporaryExposureKey = _reflection.GeneratedProtocolMessageType('TemporaryExposureKey', (_message.Message,), {
'DESCRIPTOR' : _TEMPORARYEXPOSUREKEY,
'__module__' : 'export_pb2'
# @@protoc_insertion_point(class_scope:TemporaryExposureKey)
})
_sym_db.RegisterMessage(TemporaryExposureKey)
# @@protoc_insertion_point(module_scope)
7月11日 0
7月12日 0
7月13日 0
7月14日 2
7月15日 5
7月16日 8
7月17日 5
7月18日 2
7月19日 2
7月20日 5
7月21日 4
7月22日 8
7月23日 1
7月24日 2
7月25日 6
7月26日 4
7月27日 7
7月28日 9
7月29日 13
7月30日 13
7月31日 19
8月01日 1
8月02日 5
8月03日 15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.