簡易的に Webページ をキャプチャしてその画像を OCR にかけてテキストを抽出する方法

結論

  • OCR には Tesseract を用います
  • Webサーバ には PHP の ビルトインWebサーバ を用います
  • Webページ の 画像キャプチャ には capture-website-cli を用います
    • ここは Npm 依存です

具体的方法

GitHub Actions で CI として動かす形で書いてみます。

テキストを抽出した後に「そのテキストに特定の文字列が含まれるか?」という簡易テストのようなものもやっています。

jobs:
  my_sample_job:
    (省略)
    steps:
      (省略)
      - name: 簡易的に Webページ をキャプチャしてその画像を OCR にかけてテキストを抽出し、テキストに特定文字列が含まれるかチェックする
        run: |
          yarn add --dev capture-website-cli
          sudo apt install -y tesseract-ocr libtesseract-dev tesseract-ocr-jpn fonts-migmix
          mkdir -p ./output

          php -t dist/ -S localhost:8080 &
          # Webサーバ が起きるまで待つ
          until : > /dev/tcp/localhost/8080; do sleep 1; done

          npx capture-website --full-page http://localhost:8080 --output=output/screenshot.png
          tesseract output/screenshot.png output/screenshot_ocr -l jpn txt

          # 「ようこそ!」が Webページ 上に存在しない場合はエラーを返すので CI が落ちる
          grep -q "ようこそ!" output/screenshot_ocr.txt
      - name: capture-website-cli で撮影したスクショと OCR のテキストファイル を Artifacts に保存する
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: capture-website
          path: output

補足

上記の YAML の記述についてのポイントがいくつかあります。

1. fonts-migmix をインストールしていること

  • これを入れないと日本語が化けます

2. キャプチャしたスクショ と OCR のテキストファイル を Artifacts として保存していること

  • 後から確認する時に便利です

3. Webサーバ には PHP の ビルトインWebサーバ を用いていること

  • 今や PHP ならほとんどの環境でデフォルトで入っています*1

4. Webサーバ が起動するのを待っている

until : > /dev/tcp/localhost/8080; do sleep 1; done というコマンドを実行して Webサーバ が応答を受け付けるまで無限ループさせています。

これがないと capture-website-cli が即座に実行されて、その際に Webサーバ が立ち上がっていないということでエラーになることがあります。

5. 文字列が存在するかの判定に grep -q を使っている

grep -q "ようこそ!" screenshot_ocr.txt により、もし「ようこそ!」が screenshot_ocr.txt に含まれている場合はステータスコード 0 が返ります。

含まれていない場合には 1 が返って CI が落ちます。

感想

  • 仕組みがこれよりも複雑になるようならば、サクッと Cypress 入れたほうがよいと思います
  • Tesseract の OCR の精度も高くはないので、これまた一定程度にちゃんとやるならば Vision API をサクッと使ったほうがいいと思います

*1:小さい Docker イメージには入っていないことがある

Powered by はてなブログ