たれながし.info

とあるITエンジニアの備忘録

PythonでTor経由のスクレイピング

はじめに

.onionドメインのWebサイトをスクレイピングしたいと思い調べたところ、ブラウザなどのWebクライアントからの通信がTorのSOCKSプロキシを経由するように構成すればスクレイピングできるとのことで、いくつかのWebクライアントを利用して実施してみます。

.onionドメインでない通常のWebサイト(*.comとか、*.jpなど)について、送信元IPアドレスを隠蔽してスクレイピングしたい場合もこの方法で可能です。

※ちなみに、WebサイトによってはTor経由のアクセスを禁止してたり、Tor経由だとreCAPTCHAが動作するサイトがあるので、そういう場合は適宜対応や諦める必要があります。

実施環境について

  • OS:Windows11 Enterprise 22H2 64bit
  • Python:3.10.0
  • Torブラウザ:バージョン不明 ※2023/10/04時点の最新
  • Chrome:バージョン117

Torブラウザ付属のTorについて

Torブラウザを利用してTorへの通信を確立すると、Windows版の場合は「tor.exe」というプログラムがTCPの9150と9151で待ち受けて起動します。

9150がTorネットワークに接続するためのSOCKSプロキシ、9151が制御ポートです。
(制御ポートを使うと、Torの設定や状態確認ができるらしい)

> $tor_process = (Get-Process | where ProcessName -eq "tor").id
> Get-NetTCPConnection | where State -eq "Listen" | where OwningProcess -eq $tor_process | Select-Object LocalAddress,LocalPort,State

LocalAddress LocalPort  State
------------ ---------  -----
127.0.0.1         9151 Listen
127.0.0.1         9150 Listen

スクレイピングの実施

3種類のWebクライアントで、.onionドメインのWebサイトをスクレイピングする例です。
htmlの取得までを実施します(htmlを取得できれば後は解析するだけなので)。

TorのSOCKSプロキシを利用するので、事前にTorブラウザを起動し、Torネットワークへの接続を確立しておく必要があります。


.onionドメインのサイトは「Facebook」と「DuckDuckGo」の.onionドメインVerを利用しました。

Webクライアントが「Chrome」の場合

Webクライアントが「Chrome」の場合です。
Selenium+ChromeDriver経由でChromeを操作してスクレイピングを実施します。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("--proxy-server=socks5://127.0.0.1:9150")

driver = webdriver.Chrome(options=options)
driver.get("https://facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion")
print(driver.page_source)

Webクライアントが「requests」の場合

Webクライアントが「requests」の場合です。
https://requests.readthedocs.io/en/latest/

import requests

proxies = {
    'http' : "socks5h://localhost:9150",
    'https' : "socks5h://localhost:9150"
}

url = "https://facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion"
res = requests.get(url, proxies=proxies)
print(res.text)

Webクライアントが「requests_tor」の場合

Webクライアントが「requests_tor」の場合です。
https://github.com/deedy5/requests_tor

「requests_tor」は、Tor接続に特化したPythonのWebクライアントです。
TorブラウザのHTTPヘッダを模倣したり(User-Agentなど)、複数サイトへの同時接続などができます。

from requests_tor import RequestsTor

rt = RequestsTor(tor_ports=(9150,), tor_cport=9151)

# 単一サイトへの接続
url = 'https://facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion'
r = rt.get(url)
print(r.text)

# 複数サイトへの接続
urls = ['https://facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion', 
        'http://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion']

for r in rt.get_urls(urls):
    print(r.url)
    print(r.text)