Unofficial Python client for LCSC Electronics search/product/datasheet APIs
Project description
lcsc
LCSC Electronics (www.lcsc.com) の検索・商品情報・データシート取得用の非公式 Python クライアント。
完全な API 仕様調査結果は docs/LCSC_API.md を参照 (実 API ライブコール + フロント Nuxt チャンク解析からの 173 エンドポイント抽出に基づく)。
特徴
- 認証不要 — LCSC API は Cookie 無しで動く (User-Agent のみ実質必須)
- シーン自動分岐 —
client.search("キーワード")1 つで 5 種類のシナリオを処理:- LCSC コード → 商品詳細を直接取得
- メーカー型番 → 完全一致 1 件 (1 API call)
- スペック値 → カテゴリ商品リスト
- ブランド名 → ブランド詳細
- ヒット無し → empty result
- 完全な型付け — pydantic v2 モデルで 62 フィールドの商品スキーマを完全カバー
- データシート PDF ダウンローダ 内蔵
- テストピラミッド (Detroit 学派) — ユニット 69 + インテグレーション 100 + ライブ 53 = 222 テスト
- エージェント向け CLI — Trevin の 10 原則準拠 (
--json/agent-context/--deliver/ profiles / feedback)
インストール
# PyPI から
pip install lcsc
# or
uv add lcsc
# ローカル開発
uv sync
要件: Python 3.13+
CLI
pip install -e . で lcsc バイナリが入る。エージェント (Claude Code / Cursor 等) 向けに Trevin Chow の 10 原則 を満たすよう設計:
# 高レベル検索 (5 シーン自動分岐: product / brand / list / partial / empty)
lcsc search CYPD3120-40LQXI
lcsc --json search C475897 # 機械可読 JSON
# サジェスト
lcsc suggest get Displ
# 商品操作
lcsc product list --catalog 1199 --encap 0603 --param "Tolerance=±1%" --in-stock
lcsc product get C475897
lcsc product filters --catalog 949
# カテゴリ
lcsc category list # 16 トップ
lcsc category list --master # 40 全マスター
lcsc category tree --root 17 # 階層ツリー表示
# ブランド
lcsc brand get 199 # Infineon/CYPRESS
# サードパーティ流通在庫
lcsc third search Displayport --sort-field price
lcsc third for-product C475897
lcsc third has-stock C475897
# データシート PDF (--deliver で配送先指定)
lcsc datasheet download C475897 --deliver file:./out.pdf
lcsc datasheet download C475897 --deliver stdout > out.pdf
lcsc datasheet download C475897 --deliver webhook:https://example/hook
lcsc datasheet url C475897
# プロファイル (永続デフォルト)
lcsc profile save kicad-bom --catalog 17 --in-stock --page-size 50
lcsc profile use kicad-bom
lcsc --profile kicad-bom product list --keyword stm32
# エージェント向け introspection
lcsc agent-context # versioned JSON: 全コマンドツリー + exit codes + profile fields
# フィードバック (エージェントからの摩擦報告)
lcsc feedback send "schema drift in product/detail: param_xxx vanished" -t schema-drift
LCSC_FEEDBACK_ENDPOINT=https://example/cli-feedback lcsc feedback send "..."
Exit code taxonomy (lcsc agent-context 参照)
| code | name | trigger |
|---|---|---|
| 0 | ok | 成功 |
| 1 | generic | 未分類エラー |
| 2 | usage | typer の usage エラー |
| 4 | not_found | LcscProductNotFound, LcscNotFound |
| 22 | invalid_field | LcscInvalidField, ValueError, ファイル上書き拒否 |
| 23 | waf_blocked | LcscWAFBlocked (XSS/SQLi 風入力) |
| 24 | server_error | LcscServerError |
| 30 | http_error | その他の HTTP/接続エラー |
ライブラリとしての使い方
基本: キーワード検索からデータシートまで
from lcsc import LcscClient
with LcscClient() as c:
# 高レベル: 1 つのキーワードで自動分岐
result = c.search("CYPD3120-40LQXI")
if result.is_product:
p = result.product
print(f"{p.product_code} {p.product_model} ({p.brand_name_en})")
print(f" price @ qty=100: ${p.price_at(100).usd_price}")
print(f" stock: {p.stock_number}")
for spec in p.param_vo_list:
print(f" {spec.param_name_en}: {spec.param_value_en}")
# データシート PDF を保存
c.datasheet.download(p, "./datasheet.pdf")
カテゴリ + フィルタで商品検索
with LcscClient() as c:
# カテゴリツリー (16 トップ)
tree = c.catalog.home_tree()
resistors = next(n for n in tree if n.category_name_en == "Passives")
# leaf を探す
leaves = resistors.leaves()
# フィルタ選択肢を取得
pg = c.product.param_groups(catalog_ids=[1199]) # Chip Resistor SMT
print(f"packages: {pg.packages()[:5]}")
print(f"manufacturers: {pg.manufacturers()[:5]}")
print(f"dynamic attrs: {list(pg.param_name_value_map.keys())[:5]}")
# フィルタを掛けて検索
page = c.product.list(
catalog_ids=[1199],
encap_values=["0603"],
param_map={"Tolerance": ["±1%"], "Resistance": ["10kΩ"]},
in_stock=True,
sort_field="price", sort_type="asc",
page_size=10,
)
for p in page:
print(f" {p.product_code} {p.product_model} ({p.brand_name_en})")
全件走査 (ページネーション自動)
with LcscClient() as c:
for p in c.product.iter_all(catalog_ids=[1199], encap_values=["0603"]):
# 最大 5000 件 (LCSC API の totalRow 上限)
...
サードパーティ流通在庫
with LcscClient() as c:
# キーワード検索
page = c.third.search("Displayport", sort_field="price", sort_type="asc")
for p in page:
print(f" {p.product_code_manufacturer} from {p.product_source}")
# 単一商品に対するサードパーティ在庫
page = c.third.for_product("C475897")
ブランド (メーカー) 情報
with LcscClient() as c:
b = c.brand.detail(199) # Infineon
print(f"{b.brand_name_en} ({b.brand_level})")
print(b.company_intro_en)
for cat in b.catalog_vos:
print(f" - {cat.catalog_name_en}")
エラー処理
すべての API エラーは LcscError 派生:
from lcsc import (
LcscClient,
LcscProductNotFound, # code=405 "This product does not exist."
LcscInvalidField, # code=405 "Invalid field..."
LcscNotFound, # code=404
LcscServerError, # code=500
LcscWAFBlocked, # WAF 403 (XSS/SQLi 風キーワード)
LcscHTTPError, # その他の HTTP/接続エラー
)
try:
with LcscClient() as c:
c.product.detail("C99999999", 0)
except LcscProductNotFound:
print("Product not found")
ユーザー入力をそのまま渡す場合は WAF 対策にサニタイズ:
from lcsc.utils import sanitize_keyword, is_wAF_dangerous
user_input = "<script>alert(1)</script>"
if is_wAF_dangerous(user_input):
user_input = sanitize_keyword(user_input)
アーキテクチャ
lcsc/
├── __init__.py # 公開 API
├── client.py # LcscClient: httpx ラッパー + API モジュールへのファサード
├── errors.py # 例外階層
├── models.py # pydantic v2 レスポンスモデル
├── utils/
│ └── sanitize.py # WAF 対策の入力サニタイザ
├── api/ # 9 ドメインモジュール (suggest/search/catalog/product/brand/third/discount/home/datasheet)
└── cli/ # Typer CLI (Trevin の 10 原則準拠)
├── app.py # ルート Typer app + 例外→exit code 変換
├── context.py # CliContext (json_mode, profile, lazy client)
├── profile.py # ProfileStore (~/.lcsc/profiles.json)
├── output.py # rich テーブル / JSON / stderr 分離
├── exit_codes.py # 安定 exit code taxonomy
├── error_wrap.py # LcscTyper + @with_error_handling
└── commands/ # 各 noun (search/suggest/product/category/brand/...)
テスト
テストピラミッド (Detroit 学派):
tests/
├── conftest.py # 共通フィクスチャ
├── fixtures/ # 実 API から収集した JSON (_collect.py で再生成可)
├── unit/ # 純粋関数 + データモデル (46 + CLI 23 = 69 件)
├── integration/ # 実 client + 実モデル + httpx.MockTransport で HTTP 境界モック (74 + CLI 26 = 100 件)
└── live/ # 実 LCSC API 接続 (API 38 + CLI 15 = 53 件、LCSC_LIVE_TEST=1 で有効化)
設計方針:
- Unit: 純粋関数とデータモデルのみ。collaborator は本物 (no mock)、ネットワーク無し
- Integration: 実
LcscClient+ 実httpx.Client+ 実 model。HTTP 境界だけhttpx.MockTransportで差し替え - Live:
LCSC_LIVE_TEST=1で実 LCSC API を叩く。形と最小限の不変条件のみアサート (LCSC 側のデータ変動に強い)
実行:
# fast (unit + integration)
pytest
# include live (real network)
LCSC_LIVE_TEST=1 pytest
# with coverage
pytest --cov=lcsc --cov-report=term-missing
# only one layer
pytest tests/unit
pytest tests/integration
pytest tests/live # 自動的に skip される (LCSC_LIVE_TEST=1 が無いと)
カバレッジ実績: 95% (769 statements / 25 miss)
フィクスチャ再生成
LCSC API のスキーマが変わったら:
python tests/fixtures/_collect.py
制約 (LCSC 側の)
- ページサイズ最大 100
- 検索結果上限 5000 件 (フィルタを追加して絞り込む)
- 価格は USD 固定 (
accept-languageは無視される) - ソート可能フィールドは
price,stock,brand,model,encapStandard,productArrangeのみ - 認証 API (
/wmsc/authn/...,/wmsc/cart/...等) は未実装 (検索ライブラリの範囲外)
ライセンス
MIT (LICENSE)。LCSC とは無関係の非公式クライアント。
教育・個人利用を想定しており、商用大量スクレイピングには使用しないこと。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lcsc-0.1.0.tar.gz.
File metadata
- Download URL: lcsc-0.1.0.tar.gz
- Upload date:
- Size: 14.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79272b7eb963001a1af3e5d98e36643b0fe920c4ce4bef1a06d1e0f0ef28adf3
|
|
| MD5 |
dc5ab148f04a8628b192d5f1198b3153
|
|
| BLAKE2b-256 |
79a69d2cf08c80a7fb00462741a537d235e2b91373dc1b8ef6af6945999e94c2
|
File details
Details for the file lcsc-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lcsc-0.1.0-py3-none-any.whl
- Upload date:
- Size: 63.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f20bf4702b562317f59a0f8e3aa6759687d8d5308681cac8640fc6a90e5cd22
|
|
| MD5 |
85a5cf6568e6789248718478cad0ab29
|
|
| BLAKE2b-256 |
80714ad78b8d4d3e34eaa03c265dc3fafbef1632073f58629a9d68e594086797
|