API利用例

公開データのクエリ、データベースの同期、ovitrap 読み取り値の送信、訪問のブロックを行うための、curl、Python、JavaScript の既製のレシピ。

/ja-jp/api参照に戻る

最初のステップ

すべての呼び出しは同じデータベースから行われ、JSON を返します。パブリック エンドポイントには認証は必要ありません。プライベートなものにはアクセスキーが必要です。

ベースアドレス

/ja-jp/api

言語プレフィックスは URL の一部です (ja-jp), ただし、返されるデータは変更されません。レコードは、フィールドに登録されたとおりに銀行から取得されます。

クイックテスト
curl -G -d "municipality=Ponta Pora" --data-urlencode "country=Brasil" \
  /ja-jp/api/lastcountingpublic

応答が JSON リストの場合、統合はすでに機能しています。

キーは URL に入力されます。 POST を含むすべてのプライベート エンドポイントで、 key クエリ文字列から読み取られます (?key=SUA_CHAVE). フォームの本文のみで送信すると返されます 404 "Wrong key". 他のフィールドは引き続きリクエストの本文に表示されます。

公開データを参照する

エンドポイント /api/lastcountingpublic 最新の卵子数を疫学的緯度、経度、週、年とともに返します。それは地図、パネル、研究の出発点です。

GET/api/lastcountingpublic公共
curl
curl -G \
  --data-urlencode "municipality=Ponta Pora" \
  --data-urlencode "date_start=2025-01-01" \
  --data-urlencode "date_end=2025-12-31" \
  /ja-jp/api/lastcountingpublic
Python
import requests

BASE = "/ja-jp/api"

resposta = requests.get(
    BASE + "/lastcountingpublic",
    params={
        "municipality": "Ponta Pora",
        "date_start": "2025-01-01",
        "date_end": "2025-12-31",
    },
    timeout=60,
)
resposta.raise_for_status()

for contagem in resposta.json():
    print(contagem["date"], contagem["ovitrap_id"], contagem["eggs"])
JavaScript
const BASE = "/ja-jp/api";

const params = new URLSearchParams({
    state: "MS",
    date_start: "2025-01-01",
});

const resposta = await fetch(BASE + "/lastcountingpublic?" + params);
const contagens = await resposta.json();

console.log(contagens.length, "contagens");

同じ位置パラメータ (country, state, municipality) これらは、他のパブリック エンドポイント (オビトラップ、ブロック、EDL、EDL メンテナンス、戦略ポイント) に適用されます。エンドポイント パスを変更するだけで、すでにデータ セットが変更されます。

位置パラメータを指定しないと、エンドポイントはブラジル全体のデータを返します。市区町村または州でフィルタリングすると、応答が大幅に速くなります。

すべてのページを閲覧する

ページ分割されたエンドポイントのサポート page 1 から 100 まで。それを超えると、API はテキストで応答します。 "Maximum pagination is 100" ステータス 200 — つまり、本体はリストではなくなります。反復する前に必ず型を確認してください。

Python
import requests

BASE = "/ja-jp/api"


def baixar_tudo(endpoint, **filtros):
    """Percorre as paginas ate a API devolver uma pagina vazia."""
    registros = []

    for pagina in range(1, 101):
        resposta = requests.get(
            BASE + endpoint,
            params=dict(filtros, page=pagina),
            timeout=60,
        )
        resposta.raise_for_status()
        dados = resposta.json()

        # limite de paginacao atingido: a API devolve uma string, nao uma lista
        if not isinstance(dados, list):
            print("Aviso:", dados)
            break

        if not dados:
            break

        registros.extend(dados)

    return registros


ovitrampas = baixar_tudo("/getmunicipalityovitrapspublic", municipality="Ponta Pora")
print(len(ovitrampas), "ovitrampas")
100ページまでいきましたか? 101 ページを試す代わりにフィルターを絞り込みます。郡ごとに調べるか、次のコマンドを使用します。 date_start e date_end 期間をより小さな間隔に分割します。

増分同期

ミラーリングされたベースを維持するには、実行のたびにすべてを再度ダウンロードしないでください。エンドポイント /api/lastcountingpublic 受け入れられました id, これは、その識別子のカウントのみを返します。 date (収録日) e date_collect (data de coleta).

Python
import json
import os
import requests

BASE = "/ja-jp/api"
ESTADO = "ultimo_id.json"


def ultimo_id_lido():
    if os.path.exists(ESTADO):
        with open(ESTADO) as arquivo:
            return json.load(arquivo)["counting_id"]
    return 0


def sincronizar():
    ultimo = ultimo_id_lido()
    novas = []

    for pagina in range(1, 101):
        resposta = requests.get(
            BASE + "/lastcountingpublic",
            params={"municipality": "Ponta Pora", "id": ultimo, "page": pagina},
            timeout=60,
        )
        resposta.raise_for_status()
        dados = resposta.json()

        if not isinstance(dados, list) or not dados:
            break

        novas.extend(dados)

    if novas:
        maior = max(item["counting_id"] for item in novas)
        with open(ESTADO, "w") as arquivo:
            json.dump({"counting_id": maior}, arquivo)

    return novas


print(len(sincronizar()), "contagens novas")

常に最大値を維持してください counting_id 実行日ではなく、受信されました。今日フィールドに入力されたカウントは前の週を参照している可能性があり、ID によるフィルターではこれらのレコードがエスケープされません。

CSVにエクスポート

公開カウントにはすでに座標が含まれているため、追加の結合を行わずにスプレッドシートを生成したり、マップをフィードしたりできます。

Python
import csv
import requests

BASE = "/ja-jp/api"

COLUNAS = [
    "counting_id",
    "municipality",
    "state_code",
    "ovitrap_id",
    "latitude",
    "longitude",
    "week",
    "year",
    "eggs",
    "date",
    "date_collect",
]

resposta = requests.get(
    BASE + "/lastcountingpublic",
    params={"state": "MS", "date_start": "2025-01-01"},
    timeout=60,
)
contagens = resposta.json()

with open("contagens.csv", "w", newline="", encoding="utf-8") as arquivo:
    escritor = csv.DictWriter(arquivo, fieldnames=COLUNAS, extrasaction="ignore")
    escritor.writeheader()
    escritor.writerows(contagens)

print("Arquivo contagens.csv gerado com", len(contagens), "linhas")

データの送信

次の例ではプライベート API を使用しており、キーが必要です。キーの地理的範囲によって、何を記録できるかが定義されます。自治体キーは自治体自体でのみ記録します。

POST/api/postcountingプライベート

既存のオビトラップの測定値を送信します

すでに登録されているオビトラップの卵子数を送信します。オビトラップは次の場所にあります。 ovitrap_group_id 主要な自治体内で、疫学週はフィールドから計算されます。 date.

curl
curl -X POST \
  -d "ovitrap_group_id=97" \
  -d "ovitrap_lat=-7.000000" \
  -d "ovitrap_lng=-8.000000" \
  -d "date=2025-01-20" \
  -d "counting_observation_id=1" \
  -d "counting_eggs=5" \
  "/ja-jp/api/postcounting?key=SUA_CHAVE"
Python
import requests

BASE = "/ja-jp/api"
CHAVE = "SUA_CHAVE"

resposta = requests.post(
    BASE + "/postcounting",
    params={"key": CHAVE},          # a chave vai na URL
    data={                          # os dados vao no corpo
        "ovitrap_group_id": 97,
        "ovitrap_lat": -7.000000,
        "ovitrap_lng": -8.000000,
        "date": "2025-01-20",
        "counting_observation_id": 1,
        "counting_eggs": 5,
    },
    timeout=60,
)

print(resposta.status_code, resposta.json())
# 200 "Contagem registrada"
注意: 送信された座標が登録された座標と異なる場合、ovitrap は新しい位置で更新されます。読み取り時のエージェントの座標ではなく、常にポイントの実際の座標を送信します。
POST/api/postcountingプライベート

読み取り値の隣に新しいオビトラップを取り付けます

もし ovitrap_group_id 自治体にまだ存在しない場合、同じリクエストでオビトラップが作成されます。アドレスと、該当する場合はタイプも送信します (ovitrap_type_id: 1 都会的なパターン; 2 rural).

Python
import requests

BASE = "/ja-jp/api"
CHAVE = "SUA_CHAVE"

resposta = requests.post(
    BASE + "/postcounting",
    params={"key": CHAVE},
    data={
        "ovitrap_group_id": 96,
        "ovitrap_address_district": "Centro",
        "ovitrap_address_street": "Rua das Flores",
        "ovitrap_address_number": "123",
        "ovitrap_address_complement": "",
        "ovitrap_address_sector": "Setor 04",
        "ovitrap_responsable": "Maria Souza",
        "ovitrap_block_id": "12",
        "ovitrap_type_id": 2,          # 1 = urbana (padrao), 2 = rural
        "ovitrap_lat": -7.000000,
        "ovitrap_lng": -8.000000,
        "date": "2025-01-20",
        "counting_date_collect": "2025-01-27",
        "counting_observation_id": 1,
        "counting_eggs": 5,
    },
    timeout=60,
)

print(resposta.status_code, resposta.json())
具体的な回答:
  • 400 — 足らない ovitrap_lat, ovitrap_lng ou ovitrap_group_id.
  • 400 — ovitrap_type_id 1や2とは違います。
  • 404 — このオビトラップには、年と週のカウントがすでにあります。
  • 500 — 送信された日付が将来のまたは無効な疫学週に当たる。
POST/api/postactionプライベート

ブロック訪問を登録する

使用 block_id すでに登録されているブロックで訪問を開始します。ブロックがまだ存在しない場合は、送信します block_group_id ブロックデータを入力すると、主要な市区町村内で自動的に作成されます。

Python — 既存のブロック
import requests

BASE = "/ja-jp/api"
CHAVE = "SUA_CHAVE"

visita = {
    "block_id": 97,
    "date": "2025-01-20",

    "block_land_residence": 10,
    "action_land_residence_out": 2,
    "action_land_residence_breedings": 1,
    "action_land_residence_treated": 1,

    "action_deposit_a1_quantity": 4,
    "action_deposit_a1_eliminated": 2,
    "action_deposit_a1_treated": 1,
    "action_deposit_a1_larvicid": 10,

    "action_observation": "Foco encontrado em pneus nos fundos do imovel.",
}

resposta = requests.post(
    BASE + "/postaction", params={"key": CHAVE}, data=visita, timeout=60
)

if resposta.status_code == 409:
    print("Ja existe visita para esse quarteirao nessa semana")
else:
    print(resposta.status_code, resposta.json())
Python — ブロックの作成
visita = {
    "block_group_id": 97,
    "date": "2025-01-20",
    "block_address_district": "Centro Historico",
    "block_address_sector": "Setor 04 - Norte",
    "block_coordinates": "[[-7.123, -34.845], [-7.124, -34.846]]",
    "block_lat": -7.123456,
    "block_lng": -34.845678,
    "block_responsable": "Joao da Silva",

    "block_land_residence": 10,
    "action_land_residence_out": 2,
    "action_land_residence_breedings": 1,
    "action_land_residence_treated": 1,

    "action_observation": "Area com alta densidade de recipientes descartaveis.",
}

resposta = requests.post(
    BASE + "/postaction", params={"key": CHAVE}, data=visita, timeout=60
)
print(resposta.status_code, resposta.json())

不動産および預金分野の完全なリスト (a1, a2, b, c, d1, d2, e) いる エンドポイントリファレンス. 未送信の数値フィールドはゼロとみなされますが、数値ではない値は 400 を返します。

レコードを削除する

削除は決定的であり、常に主要な自治体に限定されます。

curl
# leitura de uma ovitrampa (identificada pela ovitrampa + data)
curl -X POST -d "ovitrap_group_id=97" -d "date=2025-01-20" \
  "/ja-jp/api/postdeletecounting?key=SUA_CHAVE"

# a ovitrampa inteira
curl -X POST -d "ovitrap_group_id=97" \
  "/ja-jp/api/postdeleteovitrap?key=SUA_CHAVE"

# visita de um quarteirao (quarteirao + data)
curl -X POST -d "block_group_id=97" -d "date=2025-01-20" \
  "/ja-jp/api/postdeleteaction?key=SUA_CHAVE"

# o quarteirao inteiro
curl -X POST -d "block_group_id=97" \
  "/ja-jp/api/postdeleteblock?key=SUA_CHAVE"
間違った値で投稿されたカウントを修正するには、次のコマンドを使用して読み取り値を削除します。 /api/postdeletecounting そしてもう一度送信してください /api/postcounting — 再送信すると重複エラーが返されます。

エラー処理

応答本文は常にメッセージを含む JSON 文字列です。すべてのエラーが再試行に値するわけではないため、それぞれのケースに対処する価値があります。

状況コード何をするか
"Wrong key"404キーが本文ではなくクエリ文字列にあることを確認してください。
二重カウント404今週はすでにオビトラップに関する記事が読まれています。再送信する前に削除してください。
重複訪問409今週すでにブロックへの訪問があります。
範囲外403このブロックはチャーベ市に属していません。繰り返さないでください。
必須フィールドがありません400提出物を修正します。繰り返すと同じエラーが返されます。
無効な週または年です500この日付は、受け入れられている疫学週の範囲外です。フィールドを修正してください date.
Python
import time
import requests

NAO_REPETIR = {400, 403, 404, 409}


def enviar(url, chave, dados, tentativas=3):
    for tentativa in range(tentativas):
        try:
            resposta = requests.post(
                url, params={"key": chave}, data=dados, timeout=60
            )
        except requests.RequestException as erro:
            print("Falha de rede:", erro)
            time.sleep(5 * (tentativa + 1))
            continue

        if resposta.status_code in NAO_REPETIR:
            print("Erro definitivo:", resposta.status_code, resposta.json())
            return None

        if resposta.ok:
            return resposta.json()

        # 500 e demais erros de servidor: espera progressiva e tenta de novo
        time.sleep(5 * (tentativa + 1))

    return None

良い習慣

  • 可能な場合は常に自治体または州でフィルタリングします。フィルタリングを行わずに、クエリは国全体をスキャンします。
  • 増分同期を優先する id 毎日ベース全体を下げます。
  • リクエストを連続して送信します。 API は、クライアントあたり数十の同時呼び出しを想定して設計されていません。
  • 反復する前に、応答がリストであることを確認してください。ページング制限メッセージにはステータス 200 が付いています。
  • を保存します。 counting_id そして block_id 受信しました - これらにより、Conta Ovos レコードをシステム内のレコードと照合できるようになります。
  • 疫学週を決定フィールドとして扱います。Conta Ovos は、オビトラップごとに週に 1 回の読み取り、ブロックごとに週に 1 回の訪問のみを受け入れます。
  • ページをフォローしてください mudanças 統合を更新する前に。