kintone で検索クエリを実行する Python プログラム

kintone で検索クエリを実行する Python プログラムを作りました。
今回は API トークンを使っています（ユーザー名／パスワードではなく）。

（PHP版は curl を使わないとできなさそうだったので、あきらめました。）

マニュアル「[複数のレコードを取得する](https://cybozu.dev/ja/kintone/docs/rest-api/records/get-records/)」に、「limit の初期値は、100件です。一度に取得できるレコードは、500件までです。」の記載があります。


#### 実行

```console
python 41_get_records_query.py
```

#### 検索クエリ実行

```python:41_get_records_query.py
import base64
import urllib.request
import json
from pathlib import Path

appno = 123 # APIトークンも切替え必要
#appno = 124 # APIトークンも切替え必要

uri = "https://sample.cybozu.com/k/v1/records.json"

binary_bytes = base64.b64decode("abcabcabcabcabcabcabcabcabcabcabcabc")
#binary_bytes = base64.b64decode("defdefdefdefdefdefdefdefdefdefdefdef")

binary_string = binary_bytes.decode('latin1')

headers = {
    "X-Cybozu-API-Token": binary_string,
    "Content-Type": "application/json",
}

body = {
    "app": appno,
    "query": '印刷 not in ("確認") limit 500' # チェックボックス
#    "query": '作成日時 >= "2024-10-01"' # 作成日時
#    "query": '氏名 = "鈴木太郎"' # 文字列（１行）の設定
#    "query": 'レコード番号 <= 456 and 印刷 not in ("確認") limit 500' # AND条件

}

req = urllib.request.Request(
            url=uri,
            data=json.dumps(body).encode(),
            headers=headers,
            method="GET",
            )

response = urllib.request.urlopen(req)
res_dict = json.load(response)

# JSON を整形して表示する
#print(json.dumps(res_dict, indent=4, ensure_ascii=False))

# 「TBL_製品情報_商品名_バーコード」の value を抽出
for record in res_dict.get("records", []):
    case_no = record.get("問合せ番号", {}).get("value")
    record_no = record.get("レコード番号", {}).get("value")
    created_by = record.get("作成者", {}).get("value", {}).get("name")
    created_time = record.get("作成日時", {}).get("value")
    updated_by = record.get("更新者", {}).get("value", {}).get("name")
    updated_time = record.get("更新日時", {}).get("value")

    #print(f"問合せ番号: {case_no}｜レコード番号: {record_no}｜作成者: {created_by}｜作成日時: {created_time}｜更新者: {updated_by}｜更新日時: {updated_time}")

    for row in record.get("TBL_製品情報", {}).get("value", []):
        bar_code = row["value"].get("TBL_製品情報_商品名_バーコード", {}).get("value")
        print(f"問合せ番号: {case_no}｜バーコード: {bar_code}｜レコード番号: {record_no}｜作成者: {created_by}｜作成日時: {created_time}｜更新者: {updated_by}｜更新日時: {updated_time}")

```

　
出力例（レコード単位で）
```console
問合せ番号: 202501_00001｜レコード番号: 345｜作成者: 鈴木太郎｜作成日時: 2025-01-25T01:10:00Z｜更新者: 鈴木太郎｜更新日時: 2025-01-25T01:10:00Z
問合せ番号: 202501_00002｜レコード番号: 346｜作成者: 鈴木太郎｜作成日時: 2025-01-25T01:11:00Z｜更新者: 鈴木太郎｜更新日時: 2025-01-25T01:11:00Z
```

　
以下のように変更すると、レコードの一括更新も可能です。

```python
body = {
    "app": appno,
    "records": [

      {
        "id": "345",
        "record": {
          "印刷": {
            "value": [
              "確認",
            ],
          },
        },
      },
      {
        "id": "346",
        "record": {
          "印刷": {
            "value": [
              "確認",
            ],
          },
        },
      },


            method="PUT",


# JSON を整形して表示する
print(json.dumps(res_dict, indent=4, ensure_ascii=False))


```

　
以下は、一括更新用のデータを作るための、テキスト変換プログラムです。

```console:実行
python CreateData.py > update_records_list.txt
```

```python:CreateData.py
import re

# 入力ファイルパス
input_file = "output_records_list.txt"

with open(input_file, "r", encoding="utf-8") as f:
    for line in f:
        match = re.search(r"レコード番号: (\d+)", line)
        if match:
            record_id = match.group(1)
            output = (
                "      {\n"
                f'        "id": "{record_id}",\n'
                "        \"record\": {\n"
                "          \"印刷\": {\n"
                "            \"value\": [\n"
                "              \"確認\",\n"
                "            ],\n"
                "          },\n"
                "        },\n"
                "      },"
            )
            print(output)

```

　
kintone のマニュアル「[複数のレコードを更新する](https://cybozu.dev/ja/kintone/docs/rest-api/records/update-records/)」によると、「一度に対応できるレコードは100件まで」とされています。100件を超えるレコードを更新する必要がある場合は、本手順で、100件以下に分割して手作業で更新します（今のところ）。


## ユーザー名／パスワード版

<b>実行</b>

```console
python 42_get_records_query.py
```

<b>検索クエリ実行</b>


```python:42_get_records_query.py
import base64
import urllib.request
import json
from pathlib import Path

appno = 123
#appno = 124

uri = "https://sample.cybozu.com/k/v1/records.json"

username_password = "YourUserName:YourPassword"
auth_header = base64.b64encode(username_password.encode())

headers = {
    "Host": "sample.cybozu.com:443",
    "X-Cybozu-Authorization": auth_header,
    "Content-Type": "application/json",
}

body = {
    "app": appno,    
    "query": '印刷 not in ("確認") limit 500' # チェックボックス
#    "query": '作成日時 >= "2024-10-01"' # 作成日時
#    "query": '氏名 = "鈴木太郎"' # 文字列（１行）の設定
#    "query": 'レコード番号 <= 456 and 印刷 not in ("確認") limit 500' # AND条件
}

req = urllib.request.Request(
            url=uri,
            data=json.dumps(body).encode(),
            headers=headers,
            method="GET",
            )

response = urllib.request.urlopen(req)
res_dict = json.load(response)

# JSON を整形して表示する
#print(json.dumps(res_dict, indent=4, ensure_ascii=False))

# 「TBL_製品情報_商品名_バーコード」の value を抽出
for record in res_dict.get("records", []):
    case_no = record.get("問合せ番号", {}).get("value")
    record_no = record.get("レコード番号", {}).get("value")
    created_by = record.get("作成者", {}).get("value", {}).get("name")
    created_time = record.get("作成日時", {}).get("value")
    updated_by = record.get("更新者", {}).get("value", {}).get("name")
    updated_time = record.get("更新日時", {}).get("value")

    #print(f"問合せ番号: {case_no}｜レコード番号: {record_no}｜作成者: {created_by}｜作成日時: {created_time}｜更新者: {updated_by}｜更新日時: {updated_time}")

    for row in record.get("TBL_製品情報", {}).get("value", []):
        bar_code = row["value"].get("TBL_製品情報_商品名_バーコード", {}).get("value")
        print(f"問合せ番号: {case_no}｜バーコード: {bar_code}｜レコード番号: {record_no}｜作成者: {created_by}｜作成日時: {created_time}｜更新者: {updated_by}｜更新日時: {updated_time}")

```

出力例（レコード単位で）
```console
問合せ番号: 202501_00001｜レコード番号: 345｜作成者: 鈴木太郎｜作成日時: 2025-01-25T01:10:00Z｜更新者: 鈴木太郎｜更新日時: 2025-01-25T01:10:00Z
問合せ番号: 202501_00002｜レコード番号: 346｜作成者: 鈴木太郎｜作成日時: 2025-01-25T01:11:00Z｜更新者: 鈴木太郎｜更新日時: 2025-01-25T01:11:00Z
```