国税庁 法人番号公表サイト が提供する 法人番号 は、日本企業の名寄せにおいて最強の武器です。13 桁の番号さえ取れれば、表記ゆれを完全に解消できる。
API の使い方
- 登録:https://www.houjin-bangou.nta.go.jp/ で無料・即時発行
- 4 種のエンドポイント:番号検索、名称検索、変更履歴、ダウンロード
- 1 リクエスト 5 万件まで取得可:バルクで処理しやすい
- 変更履歴も取れる:商号変更・本店移転を時系列で追える
名寄せワークフロー
- 1既存 の会社名を正規化(EP.05 + EP.06)
- 2API の名称検索にヒット → 候補を返す
- 3人手でレビュー:複数候補が出たケースを確認
- 4法人番号で統合:以降は法人番号 = キー
グループ会社の関連性
事業承継・商号変更・合併の履歴も API から取れるので、親子関係や過去の社名まで追える。BtoB の顧客マスタ整備で最強のリファレンス。
Python 実装:API 呼出 → 名寄せ
1. 法人番号 API クライアント
Python
import osimport requestsimport xml.etree.ElementTree as ETimport time
API_KEY = os.environ["HOUJIN_BANGO_API_KEY"] # 国税庁から発行BASE = "https://api.houjin-bangou.nta.go.jp/4" # v4 (XML)
def search_by_name(name: str, mode: int = 1) -> list[dict]: """名称検索。mode=1=前方一致, 2=部分一致, 3=完全一致""" params = {"id": API_KEY, "name": name, "type": "12", "mode": str(mode)} res = requests.get(f"{BASE}/name", params=params, timeout=10) res.raise_for_status() root = ET.fromstring(res.content) return [ { "houjin_bango": c.findtext("corporateNumber"), "name": c.findtext("name"), "kana": c.findtext("furigana"), "address": c.findtext("prefectureName", "") + c.findtext("cityName", "") + c.findtext("streetNumber", ""), "kind": c.findtext("kind"), # 101=国の機関 / 201=地方公共団体 / 301=株式会社等 } for c in root.iter("corporation") ]
# 使用例results = search_by_name("ふくふく")for r in results[:3]: print(r)2. 既存 DB と API 突合(バルク処理)
Python
import pandas as pdfrom concurrent.futures import ThreadPoolExecutor
# normalize_company_name は EP.06 で定義済の正規化関数を使う
def match_company(name: str) -> dict | None: """1 社の名寄せ。完全一致 → 前方一致の順""" norm = normalize_company_name(name) # まず完全一致 exact = search_by_name(norm, mode=3) if len(exact) == 1: return {**exact[0], "match_type": "exact"} # ヒット 0 / 複数 → 前方一致 candidates = search_by_name(norm, mode=1) if len(candidates) == 1: return {**candidates[0], "match_type": "prefix"} return None # 人手レビューへ
# DataFrame の "name" 列を一括突合(並列)def bulk_match(df: pd.DataFrame, name_col: str = "name", workers: int = 5): df = df.copy() with ThreadPoolExecutor(max_workers=workers) as ex: df["match"] = list(ex.map(match_company, df[name_col])) time.sleep(0.1) # レート制限対応 return df
matched = bulk_match(my_customers_df)print(f"自動マッチ率: {matched['match'].notna().mean():.1%}")unmatched = matched[matched['match'].isna()]unmatched.to_csv("manual_review_required.csv") # 人手レビューへ3. 法人番号で統合 → グループ階層情報
Python
# match から法人番号を抜き出して統一キーにmatched["houjin_bango"] = matched["match"].apply(lambda m: m["houjin_bango"] if m else None)
# 同じ法人番号を持つ複数レコードを統合(重複は EP.09 Dedup で扱う)unified = ( matched[matched["houjin_bango"].notna()] .groupby("houjin_bango") .agg( company_name=("match", lambda s: s.iloc[0]["name"]), n_records=("user_id", "count"), sample_user_ids=("user_id", lambda s: list(s)[:5]), ) .reset_index())print(unified.head())ふくふくの進め方
「取引先マスタを統合したい」のご相談には、法人番号 API 連携(1 週間)→ 既存 DB との突合 → グループ階層情報の付与を 1 ヶ月で。
次回予告
EP.09 は重複排除(Dedup)の戦略。重複が見つかったときどのレコードを「正」とするかの話。
この記事の感想を教えてください
あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。