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
import zipfile
import 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
8月04日 20
8月05日 29
8月06日 17
8月07日 22
8月08日 12
8月09日 12
8月10日 10
8月11日 28
8月12日 29
8月13日 15
8月14日 18
8月15日 8
8月16日 10
8月17日 32
8月18日 20
8月19日 23
8月20日 38
8月21日 30
8月22日 12
8月23日 7
8月24日 26
8月25日 25
8月26日 33
8月27日 35
8月28日 38
8月29日 18
8月30日 14
8月31日 37
9月01日 21
9月02日 27
9月03日 23
9月04日 27
9月05日 11
9月06日 5
9月07日 21
9月08日 13
9月09日 23
9月10日 37
9月11日 37
9月12日 11
9月13日 8
9月14日 22
9月15日 23
9月16日 21
9月17日 20
9月18日 23
9月19日 13
9月20日 6
9月21日 1
9月22日 6
9月23日 23
9月24日 28
9月25日 17
9月26日 10
9月27日 9
9月28日 16
9月29日 14
9月30日 21
10月01日 16
10月02日 16
10月03日 11
10月04日 7
10月05日 17
10月06日 15
10月07日 23
10月08日 26
10月09日 31
10月10日 12
10月11日 14
10月12日 22
10月13日 24
10月14日 26
10月15日 22
10月16日 19
10月17日 8
10月18日 5
10月19日 21
10月20日 31
10月21日 26
10月22日 25
10月23日 20
10月24日 9
10月25日 11
10月26日 23
10月27日 19
10月28日 15
10月29日 22
10月30日 36
10月31日 15
11月01日 12
11月02日 19
11月03日 16
11月04日 23
11月05日 28
11月06日 44
11月07日 24
11月08日 17
11月09日 34
11月10日 42
11月11日 53
11月12日 39
11月13日 41
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.