PythonでTorを使ってIPを変える for Windows

##前置き
どうせ brew か sudo と思ったそこ人！！


## 注意事項
:::note warn
スクレイピング、Torの使用に関する注意点は各々で確認してください。
:::


## 実行環境
* **Windows10 64bit**
* **pip 21.2.4**
* **python 3.8.7 32bit**

その他、記載ないものは全て最新


##準備
```:必須
$ pip install PySocks
Torブラウザのダウンロード
```
```:以下、ほとんどの人がインストールしているであろうもの
$ pip install webdriver-manager
$ pip install beautifulsoup4
$ pip install pandas
chromedriver.exeのダウンロード
```
:::note warn
Torブラウザを起動して【Always connect automatically】にチェックを入れて、【Connect】をクリックしてください。
:::


##ポイント
:::note
cmdのリダイレクトをsubprocess.callで再現
【args > nul 2>&1】の代わりに【subprocess.call(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)】
:::
:::note
Torをヘッドレスモードで実行する
【Tor = f'"..\\Tor Browser\\Browser\\firefox.exe" --headless'】
:::
::: note
Seleniumを基本とした3つの方法で確認＋α
【Selenium】【Selenium + BeautifulSoup】【urllib.request + BeautifulSoup】【pandasのみ】
:::


## 以下、コード
### 宣言
```python:python
# coding:utf-8
import subprocess
import getpass
import time
import socks
import socket
import urllib.request

from selenium.webdriver.chrome.options import Options
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup
```


### Tor_start関数
```python:python
# ------ Torの起動 ------
def Tor_start():
    # 下1行のコメントアウト切り替えで出力プロセスを表示
    # subprocess.call(r'taskkill /F /T /IM firefox.exe')
    # 下1行のコメントアウト切り替えで出力プロセスを非表示
    subprocess.call(r'taskkill /F /T /IM firefox.exe', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    Tor = f'"C:\\Users\\{getpass.getuser()}\\Desktop\\Tor Browser\\Browser\\firefox.exe" --headless'
    subprocess.Popen(Tor)
    time.sleep(8)
```


### Selenium_start関数
```python:python
# ------ Seleniumの起動 ------
def Selenium_start():
    options = Options()
    options.add_argument('--headless')
    options.add_argument('--proxy-server=socks5://127.0.0.1:9150')
    driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
    driver.implicitly_wait(20)
    driver.get(url)
    return driver
```
:::note alert
【driver.get(url)】WebDriverException (note: full exception trace is shown but execution is paused at: <module>)
上記の個所でエラーが発生した場合は、Torブラウザを起動して【Refresh Tor Browser】を2回クリック、
【Always connect automatically】にチェックを入れ【Connect】をクリックしてください。
:::


### メイン処理
```python:python
url = 'https://checkip.amazonaws.com/'

# ------ IP変更1回目 ------
# ------ Seleniumのみ ------
if __name__ == '__main__':
    Tor_start()
    driver = Selenium_start()
    IP確認1回目 = driver.find_element_by_tag_name('pre').text
    driver.quit()

# ------ IP変更2回目 ------
# ------ Selenium + BeautifulSoup ------
if __name__ == '__main__':
    Tor_start()
    driver = Selenium_start()
    html = driver.page_source
    soup = BeautifulSoup(html, 'lxml')
    IP確認2回目 = soup.find('pre').get_text(strip=True)
    driver.quit()

# ------ IP変更3回目 ------
# ------ urllib.request + BeautifulSoup ------
if __name__ == '__main__':
    Tor_start()
    socks.set_default_proxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', 9150)
    socket.socket = socks.socksocket
    req = urllib.request.Request(url)
    response = urllib.request.urlopen(req)
    html = response.read()
    soup = BeautifulSoup(html, 'lxml')
    IP確認3回目 = soup.find('p').get_text(strip=True)
    subprocess.call(r'taskkill /F /T /IM firefox.exe', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

# ------ IP確認 ------
print(IP確認1回目 +'\n'+ IP確認2回目 +'\n'+ IP確認3回目)
```


### おまけ
```python:python
# ------ おまけ ------
# ------ pandasのみ、メイン処理と置き換えると動作 ------
import pandas as pd
url = 'https://www.cman.jp/network/support/go_access.cgi'
dfs = pd.read_html(url)
print(dfs[4].loc[0,1].split('IP')[0])
Tor_start()
socks.set_default_proxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', 9150)
socket.socket = socks.socksocket
dfs = pd.read_html(url)
print(dfs[4].loc[0,1].split('IP')[0])
```


##参考にしたサイト
* [Torを使って個人情報をコントロールする方法](https://qiita.com/syui/items/ebd6734a8102c7906cc1)
* [PythonでTorを用いてスクレイピングする](https://qiita.com/Michinosuke/items/81f4b893bb1406162ab3)
* [How to make urllib2 requests through Tor in Python?](https://stackoverflow.com/questions/1096379/how-to-make-urllib2-requests-through-tor-in-python)
* [まいにちプログラミング112日目　Seleniumで毎回IPアドレスを変更](http://blog.livedoor.jp/mainichi_program/archives/19806005.html)