0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Playwright の click() が `subtree intercepts pointer events` で 30 秒タイムアウトし続けたので 3 段フォールバックを書いた話

0
Posted at

TL;DR

Playwright の click() は親切設計で、要素が「クリック可能」になるまで自動で待つ。しかしその待機判定が SPA の「透明な div が上に被さっている」ケースに弱い。エラーログには毎回:

TimeoutError: ElementHandle.click: Timeout 30000ms exceeded.
... <div class="...">...</div> subtree intercepts pointer events
... retrying click action, attempt #1

これが 30 秒続く。本番で 1 タスクごとに 30 秒待たされたら話にならない。

3 段フォールバック

通常 click → force=True → JavaScript の el.click() で諦めずに殴る:

def _safe_click(element) -> bool:
    """Playwright の click が「subtree intercepts」で詰まる時の 3 段フォールバック。"""
    # 1) 通常 click(短いタイムアウトで早めに諦める)
    try:
        element.click(timeout=5000)
        return True
    except Exception:
        pass
    # 2) force=True で intercept 判定を無視
    try:
        element.click(timeout=3000, force=True)
        return True
    except Exception:
        pass
    # 3) JS で element.click() を直接叩く(DOM レベルの click イベントを発火)
    try:
        element.evaluate("el => el.click()")
        return True
    except Exception:
        return False

3 段目の evaluate("el => el.click()") が最強で、ほぼ何でも通る。ただし「人間がクリックしたフリ」ではなく「DOM イベント発火」なので、X や reCAPTCHA みたいな反 bot 検知がある所では検出されうる。普通の SaaS の UI なら問題ない。

なぜ素の click() で詰まるのか

X の場合、ツイートカードの上にホバーで現れるツールチップ用の透明オーバーレイが乗っている。Playwright の visibility/stability チェックはそれを「上に何か乗ってる」と認識して、retry を続ける。retry の合計が 30 秒。

force=True はその判定をスキップしてクリック座標に強制クリックを送る。それでも反応しない場合は、要素にクリックイベントを直接送るしか手段がない。

教訓

ブラウザ自動化は半分は UI 戦争」。SPA の DOM 構造は来週変わる。今日動くセレクタが明日動く保証はない。_safe_click のような諦めない実装を最初から書いておくと、UI 変更でも壊れにくい。

「素の click() で完璧に動かないコードは綺麗じゃない」と思ってリトライしないと、本番で 30 秒タイムアウトを 3 回踏んで Fargate が空回りして終わる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?