aboutsummaryrefslogtreecommitdiffhomepage
path: root/scripts/fetch-logoform-events.mjs
blob: f499d47456a8310854ede66d8a33590ef98b0a0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// LoGoフォーム(小平市)の手続き一覧を取得する。
//
// LoGoフォームのページ自体は自動アクセス防止(TRUSTBANKの確認画面)で
// ブラウザから開けないことがある。一方、一覧のAPIは直接呼べる。
// ただし Node の fetch では 403 になるため、curl を使って取得している。
//
// 使い方:
//   node scripts/fetch-logoform-events.mjs            # イベント情報(procedure id 49006)
//   node scripts/fetch-logoform-events.mjs 48668       # 電子申請(手続き一覧)
//   node scripts/fetch-logoform-events.mjs 49006 --json
//
// procedure id は、手続きページの設定に "id" として入っている。
// 2517(イベント情報)は 49006、666(電子申請)は 48668。

import { execFileSync } from 'node:child_process';

const DEFAULT_ID = '49006';
const args = process.argv.slice(2);
const asJson = args.includes('--json');
const procedureId = args.find((a) => /^\d+$/.test(a)) ?? DEFAULT_ID;

const PAGE = procedureId === '48668'
  ? 'https://logoform.jp/procedure/exdH/666'
  : 'https://logoform.jp/procedure/exdH/2517';

const UA =
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';

const curlArgs = [
  '-s',
  '--max-time',
  '30',
  '-X',
  'POST',
  '-H',
  'Content-Type: application/json',
  '-H',
  'Accept: application/json',
  '-H',
  `Referer: ${PAGE}`,
  '-H',
  `User-Agent: ${UA}`,
  // 空のオブジェクトで全件返る。page などの項目を足すと「不明な項目」で弾かれる。
  '-d',
  '{}',
  `https://logoform.jp/api/procedure/branch/detail/search/${procedureId}`,
];

let raw;
try {
  raw = execFileSync('curl', curlArgs, { encoding: 'utf8', maxBuffer: 20 * 1024 * 1024 });
} catch (error) {
  console.error('curl の実行に失敗しました。curl が使えるか確認してください。');
  console.error(String(error).slice(0, 300));
  process.exit(1);
}

let data;
try {
  data = JSON.parse(raw);
} catch {
  console.error('JSONとして読めませんでした(自動アクセス防止の画面が返っている可能性があります)。');
  console.error(raw.slice(0, 300));
  process.exit(1);
}

const items = Array.isArray(data.items) ? data.items : [];

if (asJson) {
  console.log(JSON.stringify(items, null, 2));
  process.exit(0);
}

console.log(`procedure_id=${procedureId} 件数=${items.length}`);
for (const item of items) {
  const description = (item.description ?? '').replace(/\s+/g, ' ').trim();
  console.log(
    `- [${item.category_name}] ${item.procedure_name}` +
      (description ? `\n    ${description.slice(0, 120)}` : '') +
      `\n    https://logoform.jp${item.form_url ?? ''}`,
  );
}