PythonでSeleniumとTorの合わせ技


# 前置き
2021年10月頃の ↓ コレをアップデートしたもの。

https://qiita.com/kawagoe6884/items/2c4a2476db65e9bedb89

自分が書いた過去の記事を再度見ると
「回りくどいことやってんなー」とかあるあるなんですかね

~~Githubにもあげたが、使い勝手が分からず投げ出したい。~~
https://github.com/kawagoe6884/scraping-with-tor

# README
### Name
scraping-with-tor
アクセス過多によるサーバーから接続規制を回避する。

### DEMO
用意する予定は今のところ無し。

### Features
とある1行のコメントアウトの切り替えでTorを使うか使わないか決める。
気晴らし程度だが、ヘッダーにランダムなユーザーエージェント。
ついでに ”navigator.webdriver=undefined” の設定も織り込み済み。

### Requirement
* Windows10 64bit
* Python 3.8.7 64-bit
* selenium 3.141.0
* fake-useragent 0.1.11
* webdriver-manager 3.5.2

### Installation
```cmd:cmd
pip install fake-useragent
pip install webdriver_manager
```

### Usage
```python:python
url = 'https://www.google.com/'
driver = Selenium(url)
print(driver.page_source)
```

### Note
tor.exe が必要。main.pyでは適当なパスを通しているので必要に応じて変更すること。

### Author
* 作成者: kawagoe6884
* 所属: 
* E-mail: 

### Special thanks
このテンプレートの参照先URL

https://cpp-learning.com/readme/

# 以下、コード
```python:main.py
# coding:utf-8
import subprocess
import time
import getpass
import random

from fake_useragent import UserAgent
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


# ------ Tor の起動 ------
def Start_tor():
    global running
    # kill
    subprocess.call(r'taskkill /F /T /IM tor.exe', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    time.sleep(1)
    # run
    Tor = f'C:\\Users\\{getpass.getuser()}\\Desktop\\Tor Browser\\Browser\\TorBrowser\\Tor\\tor.exe'
    running = subprocess.Popen(Tor)
    time.sleep(1)


# ------ Selenium の起動 ------
def Start_selenium():
    # kill
    subprocess.call(r'taskkill /F /T /IM chromedriver.exe', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    time.sleep(1)
    # chrome-option
    options = Options()
    if 'running' in globals():
        # Tor のProxy設定を通す
        options.add_argument('--proxy-server=socks5://localhost:9050')
        # User-Agentを定義する
        UA = UserAgent().chrome
        options.add_argument('--user-agent=' + UA)
    options.add_argument('--headless')
    options.add_argument('--start-maximized')
    options.add_argument('--disable-blink-features')
    options.add_argument('--disable-blink-features=AutomationControlled')
    options.add_argument('--disable-browser-side-navigation')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--disable-extensions')
    options.add_argument('--disable-gpu')
    options.add_argument('--disable-infobars')
    options.add_argument('--ignore-certificate-errors')
    options.add_argument('--ignore-ssl-errors')
    options.add_argument('--no-sandbox')
    prefs = {'profile.default_content_setting_values.notifications' : 2}
    options.add_experimental_option('prefs', prefs)
    options.add_experimental_option("excludeSwitches", ['enable-automation'])  # navigator.webdriver=undefined とする設定
    # run
    driver = webdriver.Chrome(ChromeDriverManager(log_level=0, print_first_line=False).install(), options=options)
    # set
    driver.implicitly_wait(60)
    driver.set_window_size('1920', '1080')
    return driver


# ------ driver.getのループ ------
def Selenium(url):
    global driver
    # Webアクセスのリトライ回数を指定する
    retry_count = 5
    try:
        for count in range(retry_count + 1):
            count += 1
            # リトライ回数の上限を超えた場合はエラーにする
            if count > retry_count:
                raise Exception('リトライ回数の上限を超えました')
            # driver.get ⇒ 待機、エラーならtorとselenium起動
            try:
                driver.get(url)
            except:
                # Start_tor() # Tor 使わないならコメントアウト
                driver = Start_selenium()
            else:
                WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located)
                sec = random.uniform(1.0, 3.0)
                time.sleep(sec)
                break
    except Exception as e:
        raise e
    return driver
```