😎

【悪用禁止】Torで匿名性を確保しながらSeleniumでスクレイピングする

2022/04/21に公開

About

Pythonを使ってスクレイピングするときに匿名性を担保したい。😎

注意

  • ここではスクレイピングそのものについては詳しく説明しません。
    だって優秀な方々が詳しく記事書いてますからそちらを参考にしてください。

使うもの

https://www.torproject.org/
https://www.selenium.dev/ja/documentation/

他の人の記事が詳しいので上記は詳細は割愛

  • Tor 経路を匿名化してくれるサービス。プロキシとして利用します。
  • Selenium コードでブラウザを操作するアプリ。

動作環境

今回の動作環境は mac[1], python3, 今回は ブラウザはChromeを使っています。

環境 version
macOS 12.3.1
Python3 3.9.12
Chrome 100.0.4896.127

ツール類のインストール

Torをインストール

Homebrewを利用してインストールします。なおHomebrew自体のインストールは他の人の記事にお任せします。

https://brew.sh

ターミナルで実行
brew install tor

Pythonで利用するパッケージのインストール

https://pypi.org/project/selenium/
https://pypi.org/project/webdriver-manager/

  • selenium Selenium/WebDriverを操作するためのPythonパッケージ。
  • webdriver-manager WebDriverを管理するPythonパッケージ。利用中のブラウザのバージョンに合わせてWebDriverをダウンロードしてくれます。👍🏻
ターミナルで実行
pip3 install selenium webdriver-manager

Pythonスクリプト

シバンでpython3を設定してます。以下のスクリプトを適当な場所に保存します。

tor.sh
#! /usr/bin/env python3
# Tor経由でスクレイピング

import os.path
import subprocess
from subprocess import PIPE
from time import sleep
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 設定
PROXY = "socks5://localhost:9050"   # Torのデフォルトポート

# Seleniumをあらゆる環境で起動させるChromeオプション
options = Options()
options.add_argument('--disable-gpu')
options.add_argument('--disable-extensions')
options.add_argument('--proxy-server=%s' % PROXY)
options.add_argument('--start-maximized')

# ダウンロードのデフォルト先を変更している
# 不要であればコメントアウトしても問題ない
DOWNLOAD_DIR = os.path.expanduser('~/Downloads')
prefs = {
   "download.default_directory": DOWNLOAD_DIR
}
options.add_experimental_option("prefs", prefs)

tor = None      # torプロセス変数
driver = None   # web-driver変数

try:
    # torの起動
    tor = subprocess.Popen(["tor"], shell=True, stdout=PIPE, stderr=PIPE)

    # ブラウザの起動。ここではChromeを起動している
    driver = webdriver.Chrome(ChromeDriverManager().install(),
                            chrome_options=options)

    # 待機用
    wait = WebDriverWait(driver=driver, timeout=30)

    # 起動画面をtorプロジェクトのトップページ
    driver.get('https://check.torproject.org')

    # 全て読み込むまで待つ
    wait.until(EC.presence_of_all_elements_located)

    # Torの確認
    # Tor経由のアクセスしているとTitleタグが congratulations となる
    if "congratulations" in driver.title.lower():
        print("torが有効です")

        # とりあえず DuckDuckGo を開く
        driver.get('https://duckduckgo.com')

        # TODO: ここでスクレイピングする
        # とりま、一旦1日開きっぱなし
        sleep(60*60*24)
    else:
        # もしTorがうまく動作していない場合はエラーで中断
        # Torの起動に失敗した場合、そもそもプロキシの設定でエラーとなるのでここまでこないはず
        raise Exception("torが有効ではありません")
except Exception as e:
    print(e)
    print("エラーが発生しました。")
    if driver is not None:
        driver.close()
        driver.quit()
finally:
    # torプロセスを終了させる
    if tor is not None:
        tor.kill()

実行できるようにする

そのままでは実行できないのでtor.shに実行権限をつける

ターミナルで実行
chmod +x tor.sh

実行する

ターミナルで実行
./tor.sh

ブラウザーが開いてTorのチェックサイトへアクセスします。
匿名性が確認できたらDuckDuckGoへ移動しています。

課題

  • Chromeのデフォルト検索エンジンをDuckDuckGoに変えたい。[2]
  • ユーザがChromeを終了させたらPythonで検出してPythonプロセスも終了させたい
脚注
  1. M1とintel両方試しています ↩︎

  2. 簡易版Tor Browerとして利用したい場合に便利 ↩︎

Discussion