対象タグの種類

HTML フォームを構成する主要タグは以下の 3 種類だ。

タグ用途典型例
<input>単一値の入力。type 属性で挙動が変わる。text / password / email / checkbox / radio / hidden / file / date など
<select>ドロップダウン・複数選択。都道府県・性別・権限種別
<textarea>複数行テキスト入力。コメント・備考・本文

📌 button・submit は除外する

本シリーズでは データ入力に使う要素のみを抽出対象とする。type="submit"type="button"<input> はエンティティとして意味がないため除外する。

input type 属性の一覧

type 値用途抽出対象
text一般テキスト入力
passwordパスワード
emailメールアドレス
number数値入力
tel電話番号
date日付
checkboxチェックボックス
radioラジオボタン
hidden隠しフィールド✅(セキュリティ監査用)
fileファイルアップロード
submit送信ボタン❌ 除外
button汎用ボタン❌ 除外
resetリセットボタン❌ 除外

収集対象の属性一覧

属性名対象タグ意味
name全タグフォーム送信時のキー名。DB カラム候補として最重要。
id全タグHTML 上の識別子。label との紐付けに使う。
typeinput入力の種類。DB 型推定に使う。
placeholderinput / textarea入力例・ヒント文言。
required全タグ必須入力かどうか。NOT NULL 制約の判断材料。
maxlengthinput / textarea最大文字数。VARCHAR の桁数設計に使う。
minlengthinput / textarea最小文字数。
min / maxinput[type=number/date]数値・日付の範囲。CHECK 制約候補。
patterninput正規表現バリデーション。
valueinput / optionデフォルト値・送信値。
multipleselect / input[file]複数選択可否。

label タグの取得戦略

フォームの「表示名」として最も重要なのが <label> タグのテキストだ。 label と input の紐付けには 3 つのパターンがある。

HTML — label の 3 パターン
<!-- パターン 1: for 属性 + id 属性 -->
<label for="username">ユーザー名</label>
<input id="username" type="text" name="username">

<!-- パターン 2: label でラップ -->
<label>
  メールアドレス
  <input type="email" name="email">
</label>

<!-- パターン 3: aria-label 属性(label タグなし)-->
<input type="search" name="q" aria-label="キーワード検索">

dataclass によるエンティティ定義

収集した属性を格納する Python dataclass を定義する。 これが PART 06・07 での実装の中核となる。

Python — extractor/models.py
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Optional


@dataclass
class InputEntity:
    """HTML フォーム内の 1 つの入力要素を表すエンティティ"""

    # ---- 基本識別情報 ----
    tag: str                          # "input" / "select" / "textarea"
    type: str                         # input type 属性値 or "select" / "textarea"
    name: Optional[str] = None        # name 属性(DB カラム候補)
    id: Optional[str] = None          # id 属性

    # ---- 表示情報 ----
    label: Optional[str] = None       # 関連 label のテキスト
    placeholder: Optional[str] = None # placeholder 属性

    # ---- バリデーション情報 ----
    required: bool = False
    maxlength: Optional[str] = None
    minlength: Optional[str] = None
    min: Optional[str] = None
    max: Optional[str] = None
    pattern: Optional[str] = None

    # ---- 値情報 ----
    value: Optional[str] = None       # デフォルト値
    options: list[str] = field(default_factory=list)  # select の選択肢

    # ---- メタ情報 ----
    form_id: Optional[str] = None     # 所属する form タグの id
    page_url: Optional[str] = None    # 抽出元 URL

📌 dataclass を使う理由

辞書(dict)でも同等のデータを持てるが、dataclass にすると型ヒントが付き、IDE の補完が効き、__repr__ が自動生成されてデバッグしやすい。JSON 変換も dataclasses.asdict() 一発でできる。

Python — JSON 変換サンプル
import json
import dataclasses
from extractor.models import InputEntity

entity = InputEntity(
    tag="input",
    type="text",
    name="username",
    id="username",
    label="ユーザー名",
    required=True,
    maxlength="50",
)

# dataclass → dict → JSON
print(json.dumps(dataclasses.asdict(entity), ensure_ascii=False, indent=2))

次の章では…

PART 06 では requests + BeautifulSoup を使って、このモデルに実際のデータを詰め込む「静的ページ抽出」の実装を解説します。

→ PART 06 — 静的ページ実装へ