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
11月14日 27
11月15日 26
11月16日 61
11月17日 56
11月18日 51
11月19日 69
11月20日 61
11月21日 44
11月22日 30
11月23日 37
11月24日 77
11月25日 55
11月26日 63
11月27日 73
11月28日 54
11月29日 33
11月30日 66
12月01日 65
12月02日 51
12月03日 81
12月04日 74
12月05日 35
12月07日 93
12月08日 67
12月09日 81
12月10日 72
12月11日 114
12月12日 63
12月13日 47
12月14日 80
12月15日 62
12月16日 106
12月17日 81
12月18日 93
12月19日 56
12月20日 45
12月21日 98
12月22日 90
12月23日 108
12月24日 116
12月25日 102
12月26日 78
12月27日 62
12月28日 118
12月29日 94
12月30日 101
12月31日 95
1月01日 84
1月02日 92
1月03日 61
1月04日 160
1月05日 137
1月06日 166
1月07日 197
1月08日 191
1月09日 113
1月10日 113
1月11日 91
1月12日 198
1月13日 196
1月14日 196
1月15日 180
1月16日 104
1月17日 113
1月18日 160
1月19日 128
1月20日 163
1月21日 122
1月22日 159
1月23日 87
1月24日 70
1月25日 113
1月26日 100
1月27日 108
1月28日 111
1月29日 88
1月30日 55
1月31日 50
2月01日 75
2月02日 81
2月03日 77
2月04日 68
2月05日 76
2月06日 32
2月07日 28
2月08日 42
2月09日 55
2月10日 44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment