ebaysdkでキーワード検索した結果をGoogleSpreadSheetsに書き込む

## はじめに
ebayのAPIを利用するために必要なことは[前回の記事](https://qiita.com/starcoffee66/items/68f9affb38e1f6e65c6e)をご覧ください。
今回は`ebaysdk`というライブラリを使用してebayに出品されている商品を
キーワード検索で取得した情報を`gspread`を使用して
Google Spread Sheetsに書き込むやり方を紹介したいと思います。

## 下準備
まずは[こちらの記事](https://qiita.com/164kondo/items/eec4d1d8fd7648217935)を参考に
Google Spread SheetsにPythonからアクセスするための必要な下準備を済ませてください。

## ライブラリのインストール
次に必要なライブラリをインストールしましょう。

```
pip install ebaysdk gspread oauth2client
```

## 参考コード
※`spread_sheet_key`は記録用に作成したスプレッドシートのURLの
`https://docs.google.com/spreadsheets/d/SPREADSHEET_KEY/edit#gid=0`
`SPREADSHEET_KEY`の部分に当たります。

このプログラムを実行するとこのようにスプレッドシートに取得した値が書き込まれます。
![gspread.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350795/cb27a914-f652-7650-a352-7e5c49b5525d.png)


```python:ebay_sdk.py
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from ebaysdk.finding import Connection as Finding
from ebaysdk.exception import ConnectionError

appkey = 取得したAPP KEY
keyword = "Marvel Spiderman"  # 検索したいキーワード
jsonf = "~~~~~~~~~.json"  # 下準備で保存したjsonファイル名
spread_sheet_key = "SPREADSHEET_KEY"  # 分からない方は上記を参考にしてください


# Google Spread Sheetsにアクセス
def connect_gspread(jsonf, key):
    scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
    credentials = ServiceAccountCredentials.from_json_keyfile_name(jsonf, scope)
    gc = gspread.authorize(credentials)
    worksheet = gc.open_by_key(key).sheet1
    return worksheet


# ebaysdkで取得した情報をスプレッドシートに書き込み
def write_to_sheet(ws, response_dict):
    ws.update_title(keyword)  # ワークシート名を検索したワードにする
    column = ["商品ID", "商品名", "通貨", "値段"]
    results = response_dict["searchResult"]["item"]

    for item in (results):
        column.append(item["itemId"])
        column.append(item["title"])
        column.append(item["sellingStatus"]["currentPrice"]["_currencyId"])
        column.append(item["sellingStatus"]["currentPrice"]["value"])

    cell_list = ws.range("A1:D" + str(len(results)))  # 検索結果の数だけ範囲指定

    for i, cell in enumerate(cell_list):
        cell.value = column[i]

    ws.update_cells(cell_list)  # リクエストを減らすために一気に更新


try:
    api = Finding(appid=appkey, config_file=None)
    response = api.execute("findItemsAdvanced", {
        "keywords": keyword,
        "itemFilter": [
            {"name": "MinPrice", "value": "50", "paramName": "Currency", "paramValue": "USD"},
            {"name": "MaxPrice", "value": "150", "paramName": "Currency", "paramValue": "USD"}
        ],
        "sortOrder": "CurrentPriceHighest"
    })
    response_dict = response.dict()
    write_to_sheet(connect_gspread(jsonf, spread_sheet_key), response_dict)
except ConnectionError as e:
    print(e)
    print(e.response.dict())

```

まず初めに、以下のコードでebayのapiにアクセスしていて
キーワードでの検索結果を`response`に格納している
`itemFilter`では最低価格と最高価格を指定しているが、他にも商品の状態（新品や中古）で絞ることもできる。

```python
try:
    api = Finding(appid=appkey, config_file=None)
    response = api.execute("findItemsAdvanced", {
        "keywords": keyword,
        "itemFilter": [
            {"name": "MinPrice", "value": "50", "paramName": "Currency", "paramValue": "USD"},
            {"name": "MaxPrice", "value": "150", "paramName": "Currency", "paramValue": "USD"}
        ],
        "sortOrder": "CurrentPriceHighest"
    })
```

次に、`connect_gspread(jsonf, spread_sheet_key)`でスプレッドシートにアクセスしていて
取得したワークシートの情報とレスポンスを辞書化したものを`write_to_sheet`の引数に渡しています。

```python
response_dict = response.dict()
write_to_sheet(connect_gspread(jsonf, spread_sheet_key), response_dict)
```

ワークシートの１行目は何の列なのかを分かりやすくする為にカラム名を入れたいので

```python
column = ["商品ID",  "商品名", "通貨", "値段"]
```

としています。
次に、商品の検索結果だけが欲しいので

```python
results = response_dict["searchResult"]["item"]
```

で、検索結果の商品情報を`results`に格納して、検索でヒットした数の分の商品情報を
`column`に順番に追加するようにしています。

```python
for item in (results):
    column.append(item["itemId"])  # 商品ID
    column.append(item["title"])   # 商品名
    column.append(item["sellingStatus"]["currentPrice"]["_currencyId"])  # 通貨
    column.append(item["sellingStatus"]["currentPrice"]["value"])        # 値段
```

各自で欲しい情報を`column`に追加していってください。
この際に気をつけなければならないことがあります。
今回は`["商品ID",  "商品名", "通貨", "値段"]`の順番なので、
この順番通りに各商品の情報を`column`に追加していかなければなりません。
![gspread.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350795/ba703501-911b-24fd-58f0-1b1dde0c6a04.png)

理由としては、`update_acell`や`update_cell`で一つずつ更新することもできるのですが
これだと検索結果が多かった場合にリクエストが多くなってしまい
APIのリクエスト制限に引っかかってしまいます。

なので大量のデータを一気に更新できるように、`update_cells`を使います。
この`update_cells`の引数は一次元配列じゃないといけないので、順番に入れるようにしています。

```python
cell_list = ws.range("A1:D" + str(len(results)))

for i, cell in enumerate(cell_list):
    cell.value = column[i]

ws.update_cells(cell_list)
```

`ws.range("A1:D" + str(len(results)))`としているのは
例えば検索結果が3商品ヒットの場合
1行目はカラム名`A1(商品ID)、B1(商品名)...`
2行目から検索結果となりますよね`A2(検索結果1の商品ID)、B2(検索結果1の商品名)...`
そして3商品ヒットなので最後は`D4(検索結果3の値段)`となるようにしたいので
検索結果毎に動的に設定できるように`"A1:D" + str(len(results))`としてあります。

`ws.range()`は、ワークシート内の選択した範囲内のセルの情報が取得されます。

なので取得したセルの情報を`cell_list`に格納して

```python
for i, cell in enumerate(cell_list):
    cell.value = column[i]
```

`column`に入っている商品情報を`cell_list`の各セルに書き込んでいきます。

```python
ws.update_cells(cell_list)
```

あとは`update_cells`で編集した`cell_list`を引数で渡せば、一気に更新できます。

今回は、とりあえず動くように作りましたが
他に分かりやすく簡潔にできる方法などあれば教えて頂けると幸いです。