💵 CLINEに賭けてみた 3ドル目 👯‍♀️

# 前回の記事
https://qiita.com/u83unlimited/items/6eed8ad679833d6a741b

# 今回のお題
- ある**動的にHTMLを出力している**サイトから**メインかつ大きな画像**のURLを取得し、ダウンロードするダウンローダー（CLIプログラム）を作れ

# 成果物
今回は非公開で。（察し） そもそも進捗率60%ぐらいで中途半端にダウンロードされる状態なので……
あ、**下のclinerules自体がかなりCLINEに改善提案させていて3～4割ぐらい反映されています。**　機能も盛ったし、開発ロードマップとかは出力そのままなので、成果物といえるかもしれません。

# clinerules
- この.clinerulesはmarkdownで書かれています。

## プログラム概要

- 各種サイトをスクレイピングして、画像をダウンロードする CLI プログラム

## 要求仕様

- **言語は TypeScript,環境は Node.js とする**
- vitest による自動テストは必須
- 各サイト向けの解析モジュールと、ダウンロードモジュールに分割される
- CLI プログラムではあるが、絵文字や各種インタラクティブ CLI ライブラリを用いて、分かりやすく華やかにしてほしい
- プラグイン機構にする
  - 新しいサイト対応を外部プラグインとして追加可能に
  - `plugins/` ディレクトリを作成し動的ロード
- キャッシュ機構を用意する
  - HTML の解析結果をキャッシュ
  - 一時的な中断からの再開を高速化
- npmの`crypto`モジュールは使わず、node.jsの標準機能で代替する
- ts-nodeを使わず`tsx`モジュールを使う

### 解析モジュール

- 各サイトの DOM 構造を解析し、画像の URL を取得する
- サムネイル画像は不要で、最大の画像の URL をダウンロードする
- 動的に生成しているサイトも多いので、ヘッドレスブラウザ等の利用もできるようにする
  - 静的サイトには不要なので、サイトごとに戦略を変えられるようにする

### ダウンロードモジュール

- 画像 URL のダウンロードに対応する
  - 並列ダウンロードに対応するが、レートリミット制限は厳しめにかけたい（**1 サイト、1 秒につき 1 ダウンロードがデフォルト**）
    サイトごとにレート制限を個別に適用
  - ストリーミングダウンロードを基本とする
    - メモリ効率の良いストリーム処理
    - 大きな画像も効率的に処理
  - ダウンロード途中で中止する可能性があるので、再開しても正常にダウンロードできるようにする
    - 画像ファイルはそこまで重くはない想定のため、単純に壊れたファイルは消して再ダウンロードするフローでよい
  - ダウンロード履歴（URL ではなく画像のハッシュ）を管理し、デフォルトでは過去にダウンロードした画像は再ダウンロードしない
    - ただし再ダウンロードするニーズはあるのでオプションで再ダウンロードにすること
  - ダウンロード中はどのファイルがどの程度 DL できているか出力すること
  - **保存形式は元画像が gif,jpg の場合はそのまま、PNG の場合はロスレス webp とする**

## 開発規約

### ファイル操作

- CLINE が現フォルダ（image-downloader）以外のフォルダ、ファイルを操作する際は必ずユーザーの許可を求めること

### Git

- ひとまずローカルで Git 管理はするが、Github/GitBucket/GitLab 等のオンラインの Git 管理 SaaS は利用してはいけない
- **コミットの前に自動テストを実行し、成功すること**
- コミットは日本語で行うこと
- コミットも適切な粒度で行っていいが、`by CLINE`と AI が行ったことを明確にすること

### コーディング

- 関数型のアプローチをできるだけ用いる
  - できるだけクラスを用いない
  - 純粋関数と副作用のある関数に分ける
  - 状態の数やスコープを最小限にする
- わかりにくい処理や特殊な処理を行う場合はコメントを残す

## 開発ロードマップ

1. **フェーズ 1: 基本機能**
   - 基本的な CLI 構造
   - 静的サイトのスクレイピング
   - シンプルなダウンロード機能

2. **フェーズ 2: 拡張機能**
   - ヘッドレスブラウザ対応
   - ダウンロード履歴管理
   - インタラクティブ UI

3. **フェーズ 3: 高度な機能**
   - プラグイン機構
   - 並列ダウンロード
   - メタデータ管理

4. **フェーズ 4: 最適化**
   - パフォーマンス改善
   - エラーハンドリング強化
   - 包括的なテスト

# 注目点/気になった点
- ライブラリを駆使してCLIツールとしてはヘルプなども充実した今っぽいCLIツールができた
- **4時間/15ドル費やしたが、後述の問題で中途半端に目的外のファイルも含めてダウンロードされる状態。漏れもあり、進捗は6割前後**
    - ただ、しがないCRUDアプリ制作おじさんの俺には、設計/実装力（プラグイン機構とかキュー回りとか並列DLとか）の面で作れないレベルのものが仕上がってきたのでやっぱりコスパがぶっ壊れている。
- 2025年3月現在、CLINE的には**スクレイピング系CLIツールを作るのはTS/node.jsがベストだと判断している**
    - Pythonか迷ってて言語含めて提案させたらTS/Node.jsが推されて意外でした
    - ただし**node.jsがTS直接実行できるようになったのは知らず、ちょっと古くてESM対応に難のあるts-nodeを推してきた挙句、ESM対応でハマる😔**
        - `.clinerules`で[tsx](https://www.npmjs.com/package/tsx)を使えと書いたのはこのため。それでもわざわざTSをコンパイルしようとしたり、迷走する……
- 今回、問題となったのは **DOMやスクリーンショット、画像からの要約/解釈/推論能力の低さ** 、あと**ウェブサイトのページ同士のグラフ構造の理解能力の低さ**。
    - 普通にリクエスト飛ばしてDOM取得したり、今回ブラウザ操作に[puppeteer](https://www.npmjs.com/package/puppeteer)を選んでガンガン立ち上げて解析しようとするんですが、そのページが何のページなのかとか、画像が何なのかあまり理解してない（全く理解できてないわけでもない）ので進みが遅い……
    - あと画像一覧ページを渡すので詳細ページをリストアップし、そちらに遷移して画像URLを浚う必要があるのですが、**ウェブサイトのグラフ構造が理解できておらず、画像詳細ページから画像一覧ページに戻ってしまい無限ループにはまること複数回……** 解析段階でこれなので当然出来上がったプログラムも同じ問題がありました……。
    - ユーザーが「このページにはDL対象の画像が●枚ある」「そのページはインフォメーションページだから解析しなくてよい」「このクラスが定義されたimgタグはアイコン画像だから除外して」とか、かなり細かいレベルまで答えを提示してようやくちょっと進むかなという感じ
        - 「いや指示出す側の問題だろ」という批判は当然あると思うし、自覚もあるが、ここまで細かい粒度まで言わないと進まないのは厳しく、**スクレイピング部分だけは人間のエンジニアの方が早い可能性がある**
        - 「1+2=3」には人間が逆立ちになってもかなわないほど強いが、「1+X=3（なお人間が提示する答えなので曖昧＆ズレがある模様）」を解くのは難しい的な側面もちょっと感じました
        - あと **時間の感覚があんまりない？** のかな、動的サイトのためコード修正→ブラウザ立ち上げて解析って繰り返すことになるんですけど、**平気で1ループ10分超える（動的サイトのため全ページ開いてからスリープが入り、画像一覧ページから数十ページの詳細ページに飛ぶため）のに何の改善も図ろうとしない** のも痛かったです。多分ツール実行中とかはAIも待機状態なのでお金自体はかかってない（コスト表示見てる限りでは多分。自信ない）んですけど、マジで話が進まん……

# 総評
- 進捗6割で15ドル、2000円オーバーしてるので痛いっちゃ痛いですが、CLIツール作成の性能とか、現状のAIの課題とか色々見えてきたのはよかったと思います

# 後書き
- 先週末の日曜に買った20ドルが消えたので30ドル買い足しました💸