PythonからDatablistのWaterfall Phone Finder APIへ、公開されている
linkedin.com/in/... 形式のプロフィールURLを送信すると、LinkedInから電話番号を検索できます。
APIは利用可能な電話番号データプロバイダーを順番に照会し、見つかった番号を
国番号付きの国際形式で返します。
本ガイドでは、Requestsライブラリを使って一連のPython連携を実装します。 さらに、同じ検索結果を再利用し、各見込み客の氏名、LinkedIn URL、担当者を保持した 営業電話リストをローカルで作成します。
📌 お急ぎの方向けまとめ
1つのAPIで公開LinkedInプロフィールURLのリストから電話番号を検索し、 見込み客の氏名と担当者を含む営業電話リストをローカルで作成できます。 Waterfall Phone Finderは利用可能なプロバイダーを順番に試し、見つかった番号を チームが確認できる状態で保持します。
- 入力: 公開LinkedInプロフィールURLを含む見込み客レコード。
- 出力: 見つかった国際形式の電話番号、国コード、氏名、担当者を含む ローカルの架電リスト。
💡 ノーコードで進めたい場合
DatablistのWaterfall Phone Finderを使えば、コードを書かずに LinkedInプロフィールURLから電話番号を検索できます。
プロフィールURLではなく氏名しかない場合は、先に氏名から電話番号を検索する ノーコード手順、またはPythonで氏名からLinkedIn プロフィールを検索する方法をご覧ください。
Python、Requests、Datablist APIキーの準備
このPythonサンプルではrequestsパッケージを使用します。プロジェクトフォルダーを作成し、
仮想環境を有効化してRequestsをインストールした後、スクリプトファイルを作成します。
mkdir waterfall-phone-lookup
cd waterfall-phone-lookup
python -m venv .venv
source .venv/bin/activate
python -m pip install requests
touch find_phone_numbers.py
export DATABLIST_API_KEY="your-api-key"DatablistアカウントでPersonal API Keyを作成し、
DATABLIST_API_KEYに設定してください。REST APIへのアクセスはGrowthプランの機能です。
検索成功時に消費されるクレジットについては、後ほど説明します。
1つのPython関数で電話番号を検索
この例では、編集可能な3件の見込み客レコードを使用します。各レコードには、固定の
prospect_id、氏名、公開LinkedIn URL、検索結果を確認する担当者が含まれます。
- Florian Poullin:
https://www.linkedin.com/in/florianpoullin/ - Satya Nadella:
https://www.linkedin.com/in/satyanadella/ - Reid Hoffman:
https://www.linkedin.com/in/reidhoffman/
APIへ送る必要があるのは、固定IDとLinkedIn URLだけです。氏名と担当者はローカルの ソースレコードに残します。このように分けることで、検索リクエストを小さく保ちながら、 結果取得後にチームが必要とするビジネス情報を維持できます。
以下のスクリプト全体をfind_phone_numbers.pyへ貼り付けてください。
import json
import os
import time
import uuid
import requests
def find_phone_numbers(prospects, api_key, settings):
"""Submit one phone lookup task, wait, and return every result."""
tasks_url = "https://api.datablist.com/v1/enrichments/tasks"
headers = {"X-API-Key": api_key}
inputs = [
{
"inputId": prospect["prospect_id"],
"data": {"profileUrl": prospect["linkedin_url"]},
}
for prospect in prospects
]
unique_id = str(uuid.uuid4())
print(f"Task uniqueId: {unique_id}", flush=True)
payload = {
"enrichmentId": "waterfall-phone-finder",
"uniqueId": unique_id,
"settings": settings,
"inputs": inputs,
}
response = requests.post(tasks_url, headers=headers, json=payload)
response.raise_for_status()
task = response.json()
task_id = task["@id"]
task_url = f"{tasks_url}/{task_id}"
while task["status"] not in ("completed", "failed", "stopped"):
time.sleep(3)
response = requests.get(task_url, headers=headers)
response.raise_for_status()
task = response.json()
if task["status"] != "completed":
raise RuntimeError(
f"Task {task_id} {task['status']}: {task.get('error')}"
)
results = []
results_url = f"{task_url}/results"
params = {"limit": 100}
while True:
response = requests.get(results_url, headers=headers, params=params)
response.raise_for_status()
page = response.json()
results.extend(page["results"])
next_cursor = page["nextCursor"]
if next_cursor is None:
break
params["cursor"] = next_cursor
return results
if __name__ == "__main__":
api_key = os.environ.get("DATABLIST_API_KEY")
if not api_key:
raise SystemExit("Set DATABLIST_API_KEY before running this script.")
prospects = [
{
"prospect_id": "prospect-florian-poullin",
"name": "Florian Poullin",
"linkedin_url": "https://www.linkedin.com/in/florianpoullin/",
"account_owner": "Habib",
},
{
"prospect_id": "prospect-satya-nadella",
"name": "Satya Nadella",
"linkedin_url": "https://www.linkedin.com/in/satyanadella/",
"account_owner": "Florian",
},
{
"prospect_id": "prospect-reid-hoffman",
"name": "Reid Hoffman",
"linkedin_url": "https://www.linkedin.com/in/reidhoffman/",
"account_owner": "Habib",
},
]
settings = {"cacheAge": "30"}
phone_results = find_phone_numbers(prospects, api_key, settings)
print(json.dumps(phone_results, indent=2, ensure_ascii=False))次のコマンドでファイルを実行します。
python find_phone_numbers.pyDatablistが管理する同期型Requestsのサンプルも ダウンロードできます。上記のスクリプトも同じシンプルな流れで、タスクを1件送信し、 完了を待ってから、すべての結果ページを取得します。
電話番号検索を送信する
リスト内包表記により、ソースの各見込み客をAPIの入力形式へ変換します。
prospect_idはinputIdに、linkedin_urlはdata.profileUrlになります。
linkedin.com/in/...形式の公開個人プロフィールURLを使用してください。
このenrichmentはSales NavigatorのURLに対応していません。
この関数はuniqueIdを生成し、POST前に表示します。リクエストでは、その値に加えて
waterfall-phone-finder enrichment ID、キャッシュ設定、入力データを送信します。
正常に受け付けられるとHTTP 202 Acceptedとタスクの@idが返り、処理はバックグラウンドで続行されます。
Waterfall Phone Finder API リファレンスでは、 現在の設定、入力フィールド、出力、クレジット、制限を確認できます。
見込み客が1件の場合、リクエストボディは次の形式です。
{
"enrichmentId": "waterfall-phone-finder",
"uniqueId": "generated-uuid",
"settings": {
"cacheAge": "30"
},
"inputs": [
{
"inputId": "prospect-florian-poullin",
"data": {
"profileUrl": "https://www.linkedin.com/in/florianpoullin/"
}
}
]
}公開プロフィールURLが検索入力です。inputIdは、結果をソースレコード内の氏名や担当者と
結び付けるための結合キーです。自社システム内で変わらず、同じタスク内で一意になるIDを選んでください。
バックグラウンドタスクの完了を待つ
Requestsクライアントは3秒ごとにタスクを確認する間、ローカルで処理をブロックします。
Datablistのタスク自体はバックグラウンドで実行されます。ステータスがcompletedになると、
関数は結果の取得へ進みます。failedまたはstoppedの場合は、確認に使えるタスクIDを含む
エラーが発生します。
すべての結果ページを取得する
結果リクエストでは、1回につき最大100行を取得します。nextCursorがnullになるまで、
ページの取得を続けます。各結果にはソースのinputIdが含まれるため、レスポンスの順序に
依存せず、正しい見込み客へマッピングできます。
Waterfallで電話番号が見つかる仕組み
この例ではcacheAgeを"30"に設定しています。Datablistは最初に、30日以内の利用可能な
検索結果があるか確認し、存在すればAPIで再利用できます。この設定はキャッシュの利用を
許可するものであり、キャッシュヒットを保証するものではありません。
プロフィールが未解決のままの場合、managed waterfallが利用可能な電話番号データプロバイダーを 順番に試します。利用できる番号が返らなければ次のプロバイダーへ進み、利用可能な番号が 見つかると、そのレコードの検索を終了します。
国や市場をまたぐ検索にWaterfallが有効な理由
Datablistは、単一の電話番号データプロバイダーだけに依存していません。各プロバイダーが使う データセットは異なり、カバー範囲も国や市場によって変わります。あるプロバイダーに電話番号が なくても、別のプロバイダーが見つけられる場合があります。Datablistなら、これらを同じAPI連携で利用できます。
複数市場向けの架電リストを作る営業チームにとっては、最初のプロバイダーで結果がなくても、 検索対象から漏れる見込み客を減らせます。Pythonコードは1つのタスクを送信し、統一された 結果形式を読むだけなので、プロバイダーごとに個別の連携を構築・保守する必要はありません。
ワークフローで明示的に最新の検索結果が必要な場合は、cacheAgeを"0"に設定してください。
この例では、利用可能なキャッシュ結果を再利用できるよう"30"のままにします。
検索結果全体を確認する
以下はFlorian Poullinの検索結果例です。電話番号はマスキングしています。
{
"inputId": "prospect-florian-poullin",
"status": "success",
"outputs": {
"finderProvider": "wizleads",
"phoneNumber": "+33 • •• •• •• ••",
"phoneNumberCountry": "FR"
},
"creditsUsed": "500",
"error": null
}電話番号が見つかった場合、phoneNumberには国際形式の番号が入ります。
+33のプレフィックスとphoneNumberCountry: "FR"は、フランスの電話番号であることを示します。
finderProviderは、この結果を返したfinderです。この行では500クレジットが使用され、
error: nullはAPIが行単位のエラーを返していないことを意味します。
確認用の営業電話リストを作成する
phone_resultsを取得したら、営業チームが確認するためのローカルリストを作成できます。
同じファイル内で、結果を表示する処理の後に次のブロックを追加してください。
既存の結果を再利用するため、2回目のAPI呼び出しは発生しません。
results_by_id = {
result["inputId"]: result
for result in phone_results
}
call_list = []
for prospect in prospects:
result = results_by_id.get(prospect["prospect_id"])
if not result or result["status"] != "success":
continue
phone_number = result.get("outputs", {}).get("phoneNumber")
if not phone_number:
continue
call_list_record = prospect.copy()
call_list_record["result"] = result
call_list.append(call_list_record)
print(json.dumps(call_list, indent=2, ensure_ascii=False))結果のインデックスではinputIdを結合キーとして使うため、リスト上の位置に依存せず、
各結果とソースレコードの対応を維持できます。API payloadには各見込み客のIDとプロフィールURLを含め、
元のprospectsリストには架電リストで必要な氏名と担当者を残します。
Florianの行では、prospect-florian-poullinにより、返された結果が元のname、
linkedin_url、account_ownerと結び付きます。チームはresult.outputsから電話番号と
国コードFRを確認できます。ステータス、クレジット、エラーを含むAPIオブジェクト全体も、
resultの下に保持されます。
架電リストのループはprospectsの順序に従います。対象の各見込み客をコピーしてから
resultを付加するため、元のソースリストは修正や別のフォローアップチャネルに利用できます。
結果なし、エラー、電話番号が空の行は、変更されていないprospectsリストには残りますが、
call_listには追加されません。このコードにより、確認用の営業電話リストがローカルに作成されます。
Waterfall Phone Finder APIの料金を試算する
デフォルトのmanaged waterfallで新しい未キャッシュの電話番号が見つかると、1件につき
500クレジットを使用します。利用可能なキャッシュ結果は0クレジット、結果が見つからない検索も
0クレジットです。実際の消費量は、送信した全プロフィール数に500を掛けるのではなく、
返された各行のcreditsUsedで確認してください。
予算計画には、次の式を使用します。
新たに見つかった未キャッシュの電話番号数 × 500クレジット
新しい番号40件なら20,000クレジット、100件なら50,000クレジットです。現在のUSD建て基本追加購入レートでは、 $20で20,000クレジットを購入できるため、500クレジットは$0.50相当です。REST APIへのアクセスを提供する Growthサブスクリプションは別料金です。現在のプランとクレジットパッケージは Datablistの料金ページでご確認ください。
試算例として、100件のプロフィールから新しい番号20件、利用可能なキャッシュ番号5件が見つかり、
75件は結果なしだったとします。課金対象は新しい20件なので、検索には10,000クレジットを使用します。
架電リストには、見つかった25件すべてを追加できます。計算ツールには、入力総数の100や、
見つかった総数の25ではなく、20を入力してください。この例は料金計算を示すものであり、
想定成功率を示すものではありません。
よくあるエラーの解決と既存タスクの復元
DATABLIST_API_KEYが未設定: スクリプトはリクエスト前に停止します。 環境変数をexportしてから、ファイルを再実行してください。- APIキーが拒否される:
raise_for_status()がHTTPエラーを返します。 Personal API Keyをコピーし直し、リクエストのX-API-Keyヘッダーで送信されていることを確認してください。 - プロフィールURLが未対応: 空欄、不正な形式、企業プロフィール、Sales NavigatorのURLは、
linkedin.com/in/...形式の公開個人プロフィールURLへ置き換えてください。 - クレジットが不足している: 追加タスクを送信する前に、アカウント残高と利用可能なクレジットを確認してください。
- タスクが
failedまたはstopped: 再実行が必要な処理を判断する前に、エラー、取得済みの結果、 クレジット使用量を確認してください。 - 行に結果がない、またはエラーがある: 修正や別のフォローアップチャネルに備えて、 ソースの見込み客情報を残してください。その行だけでは、どのプロバイダー、地域、公開範囲の条件が 結果に影響したかは判断できません。
POSTレスポンスを取得できなかった場合は、送信前に表示されたuniqueIdを使用します。
再送信する前にタスク一覧を確認してください。 次のリクエストのyour-api-keyを置き換え、
表示された値とuniqueIdが一致するタスクを探します。
curl --get "https://api.datablist.com/v1/enrichments/tasks" \
--header "X-API-Key: your-api-key" \
--data-urlencode "enrichmentId=waterfall-phone-finder" \
--data-urlencode "limit=100"タスクが最初のページにない場合は、タスク一覧レスポンスのnextCursorをたどってください。
一致するタスクの@idをコピーし、以下のTASK_IDを置き換えて、ステータスの確認または既存結果の取得を行います。
curl "https://api.datablist.com/v1/enrichments/tasks/TASK_ID" \
--header "X-API-Key: your-api-key"
curl --get "https://api.datablist.com/v1/enrichments/tasks/TASK_ID/results" \
--header "X-API-Key: your-api-key" \
--data-urlencode "limit=100"タスクAPIドキュメントでは、 タスクの状態、結果のページネーション、中断時の動作について説明しています。
次のステップ
これで、公開LinkedInプロフィールURLに再利用できるRequests関数と、見つかった電話番号を 営業担当者の確認用にまとめる固定IDベースの結合処理が用意できました。
編集可能なサンプルを、少数の有望な見込み客に置き換えてください。固定IDと担当者を維持し、 見つかった各番号を確認してから、チームの架電プロセスへリストを渡します。まずは少量のバッチで、 IDのマッピングと返されるフィールドを確認することをおすすめします。ノンブロッキングな並行処理が必要な場合は、 Datablistが管理するasync HTTPXのサンプルをご利用ください。


