見出し画像

SearXNGを用いたWebスクレイピングをしてみた

こんにちは!本記事ではSearXNGを用いたWebスクレイピングについてまとめます。
日本語のドキュメントが少ないため、沼にハマると苦労する(苦労した)ので、最低限Webスクレイピングができるように、やり方を書いていきます。

はじめに

インターネット上のウェブサイトからデータを自動的に抽出する技術を「Webスクレイピング」と呼ぶ。プログラムを用いて行われるため、手作業に比べて効率的かつ正確に情報収集でき、得られたデータはデータ分析やマーケティング戦略に用いられることが多い。
今回は、複数の検索サービスを利用した同時検索ができるSearXNGをWebスクレイピングに導入して、ブラウザごとのAPI呼び出し回数や速度低下を回避できれば効率的に有益なデータ収集ができるはずである。
そこで、今回は実際にSearXNGを用いたWebスクレイピングについて、環境構築から沼にハマった点までまとめて紹介する。
Webスクレイピングに関する注意点として、Webスクレイピングは以下の理由から、サイトによっては禁止しており、最悪の場合は違法になることがある。

  • 不正利用を防ぐ

  • サーバーに過剰な負担をかける

  • 著作権侵害を防ぐ

そのため、健全な目的でWebスクレイピングをしようと思っている人は上記のことに注意して行うと良いと思われる。

SearXNGとは

検索+生成AIサービスである「Perplexity」の検索部分によく使われている(らしい)

GitHub - searxng/searxng: SearXNG is a free internet metasearch engine which aggregates results from various search services and databases. Users are neither tracked nor profiled.
Welcome to SearXNG — SearXNG Documentation (2025.9.14+23257bddc)


公式ドキュメントによると

SearXNGは、最大247の検索サービスから検索結果を集約する無料のインターネットメタ検索エンジンです。ユーザーの追跡やプロファイリングは一切行われません。さらに、SearXNGはTor経由で利用でき、オンラインの匿名性を確保できます。

とのこと。

Google APIは一日100件のリクエスト制限があり、DuckDuckGoも改悪されたようで最近速度が低下されていることに加え、一日当たりの呼び出し回数に制限があるようなので、多くのデータを集めたいWebスクレイピングにはうってつけではないかと思われる。

インストール

結果論になるが、dockerが安定して動作する。
適当なdocker環境で、安定的なネットワークで放置すると現状一番良いように思うため、docker環境でのやり方を書いておく。

  1. 作業ディレクトリを作成

mkdir my-searxng-scraping && cd my-searxng-scraping
  1. SearXNGのイメージをpull

docker pull searxng/searxng
  1. コンテナを起動

export PORT=8080
docker run --rm \\
    -d -p ${PORT}:8080 \\
    -v "${PWD}/searxng:/etc/searxng" \\
    -e "BASE_URL=http://XXX.XXX.XXX.XXX:$PORT/" \\
    -e "INSTANCE_NAME=my-searxng-instance" \\
    searxng/searxng

起動したらブラウザにアクセスする。BASE_URL を上記のままにした場合はhttp://localhost:8080にアクセスすれば良い。

試しに、「東京 天気」と検索した結果は以下のような感じになる。GoogleやDuckDuckGo, Bingなど複数の検索エンジンから取得されていることがわかる。

Webスクレイピング環境構築

タイムアウトエラーについて

DuckDuckGoの検索が10秒かかってでタイムアウトになることがあるらしい。対策は2つある。

  1. setting.ymlをいじる。デフォルトは3秒なので、20秒や30秒に変更すると良い。

outgoing:
  # default timeout in seconds, can be override by engine
  request_timeout: 3.0

設定を変更し、コンテナを再起動すれば良い。

  1. ホストモードを使用

今回使用していないが紹介する。コンテナ起動時に --net=host をつければ良いだけ。

docker run --rm \\
    --net=host \\
    -v "${PWD}/searxng:/etc/searxng" \\
    -e "BASE_URL=http://XXX.XXX.XXX.XXX:8080/" \\
    -e "INSTANCE_NAME=my-searxng-instance" \\
    searxng/searxng

secret keyの設定(やらなくても良さそう)

適当な文字列を生成し、

openssl rand -hex 32

setting.ymlのsecret keyに設定

bingなどの検索エンジンを有効にする

なぜかは知らないが、デフォルトでは検索エンジンがオフになっているものがある。

  - name: bing
    engine: bing
    shortcut: bi
    disabled: true # ← この行を削除する

disable を削除する。

403エラーが出続けた。

多くのpublic instanceはJSONフォーマットを持っていないため、設定で追加する必要がある。これを入れると綺麗に403エラーは解消される。

search:
	'''
  # formats: [html, csv, json, rss]
  formats:
    - html
    - json
	'''

(参考) https://github.com/open-webui/open-webui/issues/2824

実装

コードはcursorやgeminiなどに書かせれば良い。今回はpythonで作成した。
今回はWebスクレイピングを行った結果のcsvファイルにある情報から追加情報を検索するということがやりたかったので以下のように実装した。

  1. Webスクレイピング基本実装:

    • ツール: requestsライブラリでWebページを取得し、BeautifulSoup4でHTMLを解析する、Pythonスクレイピングの構成を採用。

    • 情報抽出: 正規表現(reモジュール)を使い、HTMLテキスト内から電話番号やメールアドレスのパターンを抽出。

  2. 並列処理による高速化:

    • 課題: 1件ずつ処理すると時間がかかりすぎるため、大幅な時間短縮が必要。

    • 解決策: concurrent.futures.ProcessPoolExecutorを導入。これにより、複数のプロセスで同時にスクレイピングを実行する並列処理を実現。

  3. 抽出精度の向上:

    • 課題: 電話番号を抽出しようとした際、北海道の郵便番号(例: 059-0032)を誤って取得してしまう問題が発生。

    • 解決策: 正規表現のルールを強化。「0から始まる」「ハイフンを除いた桁数が10桁または11桁」という2段階のチェックを導入する。

まとめと感想

本取り組みでは、SearXNGを用いたWebスクレイピングを実装しました。
いくつかやり方はあるみたいですが、dockerを用いるのが一番安定してそうです。
私自身Webスクレイピング自体初めてだったことに加えて、SearXNGは日本語ドキュメントが少なく、エラーにハマって抜け出すのが大変でした。
少しでも同じことをする人の参考になれば幸いです。それでは!

参考文献

いいなと思ったら応援しよう!

コメント

コメントするには、 ログイン または 会員登録 をお願いします。
SearXNGを用いたWebスクレイピングをしてみた|NITI Technology
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1