DAM★ともの採点データを取得してCSV出力してみた
はじめに
カラオケで精密採点を歌うたびに、「あの曲、何点だったっけ?」「ビブラート何回だったかな?」と気になったことはありませんか?
DAM★ともには採点履歴が残っていますが、分析したくても一覧性がない、CSVでダウンロードできない、公式APIは200件までしか取れないという制約があります。
そこで今回、DAM★ともの採点データを全て取得してCSV化し、さらに3,000件以上の履歴も取得できるTypeScript製のAPIクライアントを作りました。
この記事で分かること
- DAM★ともの採点データをプログラムから取得する方法
- 公式API制限(200件)を超えて全履歴を取得する方法
- 148〜187項目もの詳細データの活用方法
- TypeScriptでの実装方法とAPI設計
作ったもの
主な機能
✅ 3つの採点タイプに対応
- 精密採点Ai - 最新の採点システム
- 精密採点Ai Hearts - デュエット対応版
- 精密採点DX-G - 従来版(詳細分析が強力)
✅ 詳細データを完全取得
公式サイトで見られる以上のデータが取れます:
{
songName: "残酷な天使のテーゼ",
totalScore: 95.680,
// レーダーチャート
radarChartPitch: 88,
radarChartStability: 91,
radarChartExpressive: 74,
// ビブラート詳細
vibratoCount: 28,
vibratoSkill: 10,
vibratoTotalSecond: 21.8,
vibratoType: "A-3", // 14種類のタイプ
// 表現テクニック
kobushiCount: 5, // こぶし
shakuriCount: 12, // しゃくり
fallCount: 8, // フォール
hiccupCount: 3, // ヒーカップ
// 音程グラフ(24セクション)
// 全国平均との比較
// などなど...
}
全148〜187項目のデータが取得可能!
✅ CSV出力機能
Excel対応のCSVで出力できるので、分析が捗ります:
# 精密採点Aiの全データをCSV出力
npm run export:csv:ai
# 上位5件だけCSV出力(テスト用)
npx ts-node src/exportCsv.ts --type=ai --limit=5
出力されるCSV:
- BOM付きUTF-8(Excelでそのまま開ける)
- 点数順に自動ソート
- タイムスタンプ付きファイル名
- 主要32項目を自動抽出
✅ 精密集計DX-G履歴取得(200件以上対応)
公式DAM APIは最大200件までしか取得できませんが、精密集計DX-Gサイト(https://dx-g.clubdam.info)から直接スクレイピングすることで、全履歴を取得できます。
# 全履歴を取得
npm run dxg:history:all
# CSV出力
npm run dxg:history:csv
セットアップ方法
1. インストール
git clone https://github.com/YOUR_USERNAME/karaoke-api
cd karaoke-api
npm install
2. 環境変数ファイルの作成
cp .env.example .env
3. 環境変数の設定
使いたい機能に応じて、以下の環境変数を設定します。
3-1. CDM_CARD_NO(必須)
全ての機能で必要な認証情報です。
取得手順:
- DAM★ともにログイン
- ブラウザの開発者ツール(F12)を開く
- ネットワークタブを選択
- 適当にページを操作して
CalorieHistoryListXML.doのリクエストを探す - レスポンス内の
<cdmCardNo>ここの値</cdmCardNo>をコピー
.env ファイルに設定:
CDM_CARD_NO=取得したcdmCardNo
3-2. CDM_TOKEN(精密採点DX-G使用時のみ)
精密採点DX-G(公式API) を使用する場合のみ必要です。
npm run dev:dxg や npm run export:csv:dxg を使う場合に設定します。
取得手順:
- DAM★ともにログイン
- ブラウザの開発者ツール(F12)を開く
- ネットワークタブを選択
- DX-Gの採点履歴ページにアクセス
- ネットワークタブで
GetScoringDxgListXML.doのリクエストを探す - リクエストの Query String Parameters から
cdmTokenの値をコピー
.env ファイルに設定:
CDM_TOKEN=取得したcdmToken
3-3. DXG_HISTORY_USERNAME(精密集計DX-G履歴取得使用時のみ)
精密集計DX-G履歴取得 を使用する場合のみ必要です。
npm run dxg:history や npm run dxg:history:csv を使う場合に設定します。
取得手順:
- DAM★とも マイページにアクセス
- ページ上部に表示される「〇〇〇〇さん」の部分を確認
- 「さん」の前の部分があなたのユーザー名です
例: 「LLENNさん」と表示されている場合、ユーザー名は LLENN
.env ファイルに設定:
DXG_HISTORY_USERNAME=あなたのユーザー名
3-4. 設定例
最終的な .env ファイルの例:
# 必須(全ての機能で必要)
CDM_CARD_NO=あなたのcdmCardNo
# 精密採点DX-G(公式API)を使う場合のみ
CDM_TOKEN=あなたのcdmToken
# 精密集計DX-G履歴取得を使う場合のみ
DXG_HISTORY_USERNAME=あなたのユーザー名
環境変数の使い分け
| 環境変数 | 必須 | 用途 |
|---|---|---|
CDM_CARD_NO |
✅ 必須 | 全ての機能で必要 |
CDM_TOKEN |
⚠️ 条件付き | 精密採点DX-G(公式API)使用時のみ |
DXG_HISTORY_USERNAME |
⚠️ 条件付き | 精密集計DX-G履歴取得使用時のみ |
4. 動作確認
# 精密採点Aiの最新5件を取得
npm run dev:ai
データが表示されれば成功です!
使い方
基本的な使用例
import { DAMClient } from './damClient';
const client = new DAMClient({
cdmCardNo: process.env.CDM_CARD_NO!,
});
// 最新5件を取得
const result = await client.getScoringAiList({ detailFlg: 1 });
result.list?.data.forEach(score => {
console.log(`${score.songName} - ${score.totalScore}点`);
});
全データを取得して統計分析
// 最大200件の全データを取得
const allData = await client.getAllScoringData('ai');
console.log(`総データ数: ${allData.length}件`);
// 平均点を計算
const average = allData.reduce((sum, s) => sum + s.totalScore, 0) / allData.length;
console.log(`平均点: ${average.toFixed(3)}点`);
// 90点以上の曲を抽出
const highScores = allData.filter(s => s.totalScore >= 90);
console.log(`90点以上: ${highScores.length}曲`);
// ビブラート回数でソート
const sortedByVibrato = allData.sort((a, b) =>
(b as any).vibratoCount - (a as any).vibratoCount
);
精密集計DX-Gから全履歴を取得
公式API制限を回避して、全履歴を取得します:
import { DxgHistoryClient } from './dxgHistoryClient';
const client = new DxgHistoryClient('YOUR_USERNAME');
// 全履歴を取得(200件以上も可能)
const allHistory = await client.getAllHistory();
console.log(`総データ数: ${allHistory.length}件`);
// 点数でソート
const topScores = allHistory
.sort((a, b) => b.totalScore - a.totalScore)
.slice(0, 10);
topScores.forEach(record => {
console.log(`${record.songName} - ${record.totalScore}点`);
console.log(`素点: ${record.baseScore}点 + ボーナス: ${record.bonusScore}点`);
});
技術的な工夫
1. 2つのアプローチ
このプロジェクトでは、2つの異なるアプローチでデータを取得しています:
公式API経由(最大200件)
// damClient.ts
async getScoringAiList(params: {
detailFlg?: number;
offset?: number;
limit?: number;
}) {
const response = await axios.get(
'https://www.clubdam.com/app/damtomo/GetScoringAiListXML.do',
{ params: { ...params, cdmCardNo: this.scrambledCardNo } }
);
return this.xmlParser.parseStringPromise(response.data);
}
メリット:
- 公式APIなので安定している
- 詳細データが取得できる(148〜187項目)
- XMLからJSONへ自動変換
デメリット:
- 最大200件までしか取得できない
スクレイピング経由(全履歴取得可能)
// dxgHistoryClient.ts
async getHistory(page: number = 1): Promise<DxgHistoryRecord[]> {
const url = `https://dx-g.clubdam.info/user/${this.username}?page=${page}`;
const response = await axios.get(url);
const $ = cheerio.load(response.data);
const records: DxgHistoryRecord[] = [];
$('table.score-history tr').each((i, elem) => {
// HTMLテーブルをパース
const record = this.parseTableRow($, elem);
if (record) records.push(record);
});
return records;
}
メリット:
- 全履歴を取得できる(3,000件以上も可能)
- ページネーションで自動取得
デメリット:
- スクレイピングなのでHTML構造変更に弱い
- 取得できる項目が少ない(15項目程度)
2. 型安全なAPI設計
TypeScriptの型定義を完備:
export interface ScoringData {
scoringAiId: string;
songName: string;
artistName: string;
playDate: string;
totalScore: number;
// ... 他多数
}
export type ScoringType = 'ai' | 'ai-hearts' | 'dx-g';
export interface DAMClientConfig {
cdmCardNo: string;
cdmToken?: string;
}
これにより、IDEの補完が効いて開発がスムーズになります。
3. ページネーション対応
全データ取得時の自動ページング:
async getAllHistory(): Promise<DxgHistoryRecord[]> {
const allRecords: DxgHistoryRecord[] = [];
let page = 1;
let hasMore = true;
while (hasMore) {
console.log(`ページ ${page} を取得中...`);
const records = await this.getHistory(page);
if (records.length === 0) {
hasMore = false;
} else {
allRecords.push(...records);
page++;
await this.sleep(1000); // サーバー負荷軽減
}
}
return allRecords;
}
4. CSV出力の工夫
Excel対応のCSV出力:
function convertToCSV(data: ScoringData[]): string {
const headers = ['曲名', 'アーティスト', '総合点', ...];
const rows = data.map(score => [
escapeCSV(score.songName),
escapeCSV(score.artistName),
score.totalScore,
// ...
]);
const csvLines = [
headers.join(','),
...rows.map(row => row.join(','))
];
// BOM付きUTF-8(Excelで正しく開くため)
return '\ufeff' + csvLines.join('\n');
}
実際に使ってみた結果
取得できたデータ
- 精密採点Ai: 200件
- 精密採点Ai Hearts: 200件
- 精密採点DX-G(公式API): 200件
- 精密集計DX-G履歴: 3,068件 🎉
分析してわかったこと
1. 平均点の推移
CSVをExcelで開いて、日付ごとの平均点をグラフ化したところ、徐々に上達していることが可視化できました。
2. 得意な音域の発見
高得点の曲を分析すると、キー設定が-2〜+1の範囲に集中していることが判明。自分の得意な音域がわかりました。
3. ビブラートの改善
ビブラート回数と点数の相関を分析。タイプ「A-3」(やや速め)が高得点につながることを発見。
4. 表現テクニックの傾向
- こぶし: 平均3.2回
- しゃくり: 平均8.5回
- フォール: 平均5.1回
このデータを参考に、意識的にテクニックを使うように練習した結果、表現力の点数が5点アップ!
まとめ
DAM★ともの採点データを全て取得できるAPIクライアントを作成しました。
できること:
- ✅ 3つの採点タイプに対応(Ai / Hearts / DX-G)
- ✅ 詳細データを完全取得(148〜187項目)
- ✅ CSV出力で分析が簡単
- ✅ 公式API制限を超えて全履歴取得(3,000件以上)
使い道:
- カラオケ上達のための分析
- 得意な曲・苦手な曲の傾向把握
- 時系列での成長記録
- 統計的なアプローチでの練習計画
データドリブンでカラオケ上達を目指す方は、ぜひ使ってみてください!
リンク
- GitHub: https://github.com/LlechiKaito/karaoke-api
- セットアップガイド: docs/setup-guide.md
- APIリファレンス: docs/api-reference.md
- Xリンク: https://x.com/TiaoYi70596
参考資料
この記事は以下を参考に作成しました:
最後まで読んでいただき、ありがとうございました!
この記事が「いいね」と思ったら、ぜひ ❤️ をお願いします。
また、改善点や質問があれば、コメント欄でお気軽にどうぞ!
Discussion