pythonによるweb API入門1

# bitFlyer APIを叩いてみた

現在、pythonによるAPIの利用に関心を持っている。そこで、いろいろなAPIを叩き、それっぽいプログラムを作ることに挑戦したいと思う。
今回は、仮想通貨交換業で有名な株式会社bitFlyerのビットコイン取引可視化サイト「chainFlyer」のAPIを素材にした。
https://chainflyer.bitflyer.jp

## アプリケーションの概要
今回作るアプリケーションは、ブロックチェーンの
・トランザクションハッシュ
を入力するとそのトランザクションの
・インプットアドレス
・インプット取引額
・アウトプットアドレス
・アウトプット取引額
を出力しcsvファイルを生成するものである。

具体的な操作としては、
・トランザクションのハッシュ値を入力させる
・APIで該当するトランザクションにリクエストをかける
・json形式でデータを受ける
・受けたトランザクションデータからインプットアドレスを取得して格納する
・for文により複数ある場合には繰り返す
・アウトプットアドレスも同様に取得して格納する
・格納したインプットアドレスそれぞれに対して、APIでインプット取引額を取得して格納する
・アウトプットアドレスも同様にして、APIでアウトプット取引額を取得して格納する
・それらをデータフレーム化してCSVに書き出す
といったところである。

## 実装
### ライブラリのインポート
今回使ったライブラリはpandas, numpy, requests, jsonである。

```python
import pandas as pd
import numpy as np
import requests, json
```

### 任意のトランザクションハッシュを入力させる
まずは中身を知りたいトランザクションのハッシュ値を入力してもらう。

```python
tx_hash = input("Please Enter tx hash: ")
```
例えば、トランザクションハッシュ
"308c859992e0a9b4b4a996c3c472bc0d2cc9f4aac12990b0a86a625241b1e9ec"
を入れることにしよう。

### 入力されたtx hashからURLでAPIにアクセスする
chainFlyer APIのエンドポイントURLにリクエストを出し、該当するトランザクションのデータを要求する。

```
url_tx_hash = requests.get('https://chainflyer.bitflyer.com/v1/tx/' + tx_hash)
```

### URLからトランザクションのデータを受け取りjsonで読み込む
データを受け取り、jsonで扱えるようにする。

```
json_read1 = json.loads(url_tx_hash.text)
```
json_read1

```
{'tx_hash': '308c859992e0a9b4b4a996c3c472bc0d2cc9f4aac12990b0a86a625241b1e9ec',
 'block_height': 555497,
 'confirmed': 193,
 'fees': 150600,
 'size': 761,
 'received_date': '2018-12-26T01:19:30.57',
 'version': 1,
 'lock_time': 0,
 'inputs': [{'prev_hash': 'ea731bfd6f45a1f4992664d5a6e62913807e8d79d839d5eb7bfa08a2d5372582',
   'prev_index': 1,
   'value': 74522550,
   'script': '160014ac2cc7ee432c71a58e35cfd6c074a155514dfacc',
   'address': '37vzKYB6eBwvpmptB2E2ARz9Swxu4EEGwu',
   'sequence': 16777215},
  {'prev_hash': 'ca8cd793b13fde3e189de353a8444d916222c5157415a9158af207d59448ff76',
   'prev_index': 2,
   'value': 23020620,
   'script': '160014690491503bcbbcb7d559ba0b0af83bdf0fa15aa8',
   'address': '3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG',
   'sequence': 16777215},
  {'prev_hash': '831cab9f3222a7cb14f2626b03ef6b3b37cfb85e910e591831498cb71896ffec',
   'prev_index': 0,
   'value': 79539815,
   'script': '160014690491503bcbbcb7d559ba0b0af83bdf0fa15aa8',
   'address': '3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG',
   'sequence': 16777215},
  {'prev_hash': 'c840e730a5ac2b9254212fd333ebb142fcc362fc8f99aac5b06acc8cdc62637d',
   'prev_index': 0,
   'value': 251909635,
   'script': '160014690491503bcbbcb7d559ba0b0af83bdf0fa15aa8',
   'address': '3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG',
   'sequence': 16777215}],
 'outputs': [{'value': 300000000,
   'script': 'a9144889696acdf1c05ee27620dff5d2f4f4a74b4de187',
   'address': '38JZBto35r1upCZ23anoJQMibpdL7EBwaC'},
  {'value': 128842020,
   'script': 'a9148930fbefcabf673291abfa1ffbb2abcaf4a4253287',
   'address': '3ECRBJS6Uk39c7NAHJE9pZwxBmyynYgSW4'}]}
```

### トランザクションのインプットアドレスを全て取得して格納する


```
# jsonデータからインプットのデータを取り出す。
inputs =  json_read1["inputs"]

# トランザクションに含まれるインプットの数を数える。
length_of_inputs = len(inputs)

# インプットアドレスを全て取得し、リストに順に格納する。
inputs_address = list()
for inputs_num in range(length_of_inputs):
    inputs_address.append(inputs[inputs_num]["address"])

# リストをnumpy arrayに変換する。
inputs_address = np.array(inputs_address)
```

inputs

```
[{'prev_hash': 'ea731bfd6f45a1f4992664d5a6e62913807e8d79d839d5eb7bfa08a2d5372582',
  'prev_index': 1,
  'value': 74522550,
  'script': '160014ac2cc7ee432c71a58e35cfd6c074a155514dfacc',
  'address': '37vzKYB6eBwvpmptB2E2ARz9Swxu4EEGwu',
  'sequence': 16777215},
 {'prev_hash': 'ca8cd793b13fde3e189de353a8444d916222c5157415a9158af207d59448ff76',
  'prev_index': 2,
  'value': 23020620,
  'script': '160014690491503bcbbcb7d559ba0b0af83bdf0fa15aa8',
  'address': '3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG',
  'sequence': 16777215},
 {'prev_hash': '831cab9f3222a7cb14f2626b03ef6b3b37cfb85e910e591831498cb71896ffec',
  'prev_index': 0,
  'value': 79539815,
  'script': '160014690491503bcbbcb7d559ba0b0af83bdf0fa15aa8',
  'address': '3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG',
  'sequence': 16777215},
 {'prev_hash': 'c840e730a5ac2b9254212fd333ebb142fcc362fc8f99aac5b06acc8cdc62637d',
  'prev_index': 0,
  'value': 251909635,
  'script': '160014690491503bcbbcb7d559ba0b0af83bdf0fa15aa8',
  'address': '3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG',
  'sequence': 16777215}]
```

length_of_inputs

```
4
```

inputs_address

```
array(['37vzKYB6eBwvpmptB2E2ARz9Swxu4EEGwu',
       '3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG',
       '3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG',
       '3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG'], dtype='<U34')
```

### トランザクションのアウトプットアドレスを全て取得して格納する
```
# jsonデータからアウトプットのデータを取り出す。
outputs = json_read1["outputs"]

# トランザクションに含まれるアウトプットの数を数える。
length_of_outputs = len(outputs)

# アウトプットアドレスを全て取得し、リストに順に格納する。
outputs_address = list()
for outputs_num in range(length_of_outputs):
    outputs_address.append(outputs[outputs_num]["address"])

# リストをnumpy arrayに変換する。
outputs_address = np.array(outputs_address)
```

outputs

```
[{'value': 300000000,
  'script': 'a9144889696acdf1c05ee27620dff5d2f4f4a74b4de187',
  'address': '38JZBto35r1upCZ23anoJQMibpdL7EBwaC'},
 {'value': 128842020,
  'script': 'a9148930fbefcabf673291abfa1ffbb2abcaf4a4253287',
  'address': '3ECRBJS6Uk39c7NAHJE9pZwxBmyynYgSW4'}]
```

length_of_outputs

```
2
```

outputs_address

```
array(['38JZBto35r1upCZ23anoJQMibpdL7EBwaC',
       '3ECRBJS6Uk39c7NAHJE9pZwxBmyynYgSW4'], dtype='<U34')
```


### インプットのアドレスを１つずつAPIで検索して対応するインプット取引額を取得して格納する
```
# インプット取引額をひとつずつAPIから取得してリストに格納する。
inputs_balances = list()
for a in range(length_of_inputs):
    url_inputsAddress = requests.get("https://chainflyer.bitflyer.com/v1/address/" + inputs_address[a])
    json_read2 = json.loads(url_inputsAddress.text)
    inputs_balances.append(json_read2["confirmed_balance"])

# リストをnumpy arrayに変換する。
inputs_balances = np.array(inputs_balances)
```

inputs_balances

```
array([       0, 87330065, 87330065, 87330065])
```


### アウトプットアドレスを１つずつAPIで検索して対応するアウトプット取引額を取得して格納する
```
# アウトプット取引額をひとつずつAPIから取得してリストに格納する。
outputs_balances = list()
for b in range(length_of_outputs):
    url_outputsAddress = requests.get("https://chainflyer.bitflyer.com/v1/address/" + outputs_address[b])
    json_read3 = json.loads(url_outputsAddress.text)
    outputs_balances.append(json_read3["confirmed_balance"])

# リストをnumpy arrayに変換する。
outputs_balances = np.array(outputs_balances)
```

outputs_balances

```
array([13984660328,           0], dtype=int64)
```


### データフレームにする
```
df = pd.DataFrame(data=[inputs_address, inputs_balances, outputs_address, outputs_balances], index=["Input Address", "Input Balance", "Output Address", "Output Balance"])
df = df.T
```

df

```
Input Address	Input Balance	Output Address	Output Balance
0	37vzKYB6eBwvpmptB2E2ARz9Swxu4EEGwu	0	38JZBto35r1upCZ23anoJQMibpdL7EBwaC	13984660328
1	3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG	87330065	3ECRBJS6Uk39c7NAHJE9pZwxBmyynYgSW4	0
2	3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG	87330065	None	None
3	3Jc3GsBfZRsq3Qp4AKDyVCQWJDvoMz31NG	87330065	None	None
```


### csvファイルで書き出す

```
df.to_csv("tx.csv", index=False)
```


## 学べたこと
・APIの叩き方
・ブロックチェーンにおけるトランザクションのデータ構造
・jsonデータの処理
・for文
・arrayとリストの変換