質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

Q&A

1回答

2167閲覧

Python+Selenium+Tor 途中403エラーになりアクセス制限を突破できない

k.nakazono

総合スコア4

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

0グッド

0クリップ

投稿2022/11/01 03:09

編集2022/11/02 04:55

前提

Python+Selenium+Torを使って、データ収集目的で、とあるサイトのスクレイピングのプログラムを実装しています。
画面のボタン押下イベントにより、表示が切り替わるページのため、Seleniumが必須なサイトです。

全部で3,000件ほどの詳細ページの情報を取得したいのですが、途中までは想定通りに動くものの、
約100件目程に差し掛かると、403エラーが表示され接続できなくなります。

driver.page_source の結果

html

1<html><head>\n<title>403 Forbidden</title>\n</head><body>\n<h1>Forbidden</h1>\n<p>You don't have permission to access /buy/search/detail/\non this server.</p>\n\n</body></html>

腑に落ちない点としては、
Torプロキシを介しての接続のため、Tor再起動するとIPアドレスが変わって、接続できるかと思いましたが、
IPを変更しても改善されず、更に加えて、通常のChromeブラウザでの該当URLへのアクセスも拒否されるようになり、突破口を見いだせない状況で質問させて頂いた次第です。

※Bot対策を行なっているサイトに、過度なクローリングは控えなければならないことは重々承知しております🙇‍♂️

実現したいこと

  • アクセス制限を受けず、安定的にクローリングが行える状態を実現したい

発生している問題・エラーメッセージ

Seleniumでアクセスした場合

Bad Request Your browser sent a request that this server could not understand.

通常のChromeブラウザからアクセスした場合

Forbidden You don't have permission to access /buy/ on this server.

該当のソースコード

python

1 2 3# メイン処理 4DOMAIN = "https://www.janpara.co.jp/" 5START_URL = "https://www.janpara.co.jp/buy/search/result/?KEYWORDS=&OUTCLSCODE=46&CLSCODE=&LINE=24" 6PROXY = 'localhost:9050' 7 8if __name__ == '__main__': 9 10 options = webdriver.chrome.options.Options() 11 options.add_argument(f'--proxy-server=socks5://{PROXY}') 12 chrome_service = fs.Service(executable_path="/Users/nakazono/Downloads/chromedriver") 13 driver = webdriver.Chrome(service=chrome_service, options=options) 14 driver.implicitly_wait(3) 15 16 nextlink = None 17 i= 0 18 results = [] 19 20 while True: 21 i += 1 22 logger.info(f"{i}ページ目===========================================================================") 23 24 driver.get(nextlink or START_URL) 25 soup = BeautifulSoup(driver.page_source, 'html.parser') 26 detail_urls = get_detail_urls(soup) 27 28 for detail_url in detail_urls: 29 try: 30 # ここで要素の情報を取得する 31 32 except Exception as e: 33 print(e) 34 continue 35 36 # 次ページへ 37 nextlink = get_nextlink("/buy/search/result/" ,soup) 38 if not nextlink: 39 break 40 41class TorControlPortClient: 42 control_address: str 43 control_port: int 44 control_password: Optional[str] 45 46 def __init__( 47 self, 48 control_address: str, 49 control_port: int, 50 control_password: Optional[str] = None 51 ): 52 self.control_address = control_address 53 self.control_port = control_port 54 self.control_password = control_password 55 56 def change_connection_ip(self, seconds_wait: int = 5) -> bool: 57 time.sleep(seconds_wait) 58 try: 59 tor_connection = socket.create_connection((self.control_address, self.control_port)) 60 password_value = self.control_password if self.control_password is not None else '' 61 message = f'AUTHENTICATE "{password_value}"\r\nSIGNAL NEWNYM\r\n' 62 tor_connection.send(message.encode('utf-8')) 63 response = tor_connection.recv(1024) 64 if response != b'250 OK\r\n250 OK\r\n': 65 sys.stderr.write('Unexpected response from Tor control port: {}\n'.format(response)) 66 return False 67 return True 68 except Exception as e: 69 print(e) 70 sys.stderr.write('Error connecting to Tor control port: {}\n'.format(repr(e))) 71 return False 72 73@retry(wait=wait_exponential(multiplier=1, min=3, max=50)) 74def get_html(url): 75 """ 76 HTTPリクエストしてBeautifulSoupオブジェクトに変換する 77 """ 78 headers = { 79 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36" 80 } 81 82 proxies = { 83 'http': 'socks5://localhost:9050', 84 'https': 'socks5://localhost:9050', 85 } 86 87 time.sleep(2) 88 89 res = requests.get(url, headers=headers, proxies=proxies) 90 print(res.content) 91 if 300 <= res.status_code <= 599: 92 tor_control_port_client = TorControlPortClient('localhost', 9051, 'test1234') 93 tor_control_port_client.change_connection_ip(seconds_wait=3) 94 print("IP Address is Changed") 95 raise Exception("IPチェンジ!!!") 96 97 soup = BeautifulSoup(res.content, 'html.parser') 98 return soup 99 100def get_detail_urls(soup): 101 items = soup.select(".search_item > h3 > a[href]") 102 for item in items: 103 yield item.get("href") 104 105def get_nextlink(path, soup): 106 try: 107 nextlink = DOMAIN + path + soup.select_one(".pageLink[title='次ページ']").get("href") 108 except Exception as e: 109 print("Last Page") 110 nextlink = None 111 112 return nextlink 113

試したこと

  • Torが機能しているか IPアドレス確認サイトで確認した
  • headless, no-sandbox オプションなどを付与してみたが結果は変わらなかった
  • ネットの接続回線とプロキシの有無を切り替えると結果は以下となった。
回線プロキシ結果
Wifi×
Wifi×
テザリング×
テザリング

補足情報(FW/ツールのバージョンなど)

  • python3.8

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

BANされたんじゃないですか

投稿2022/11/01 17:13

dark-eater-kei

総合スコア1248

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k.nakazono

2022/11/02 01:35

ありがとうございます。 アカウントログインするようなサイトでないですし、 IPアドレスもプロキシ経由でIPローリングさせていますので、 アクセス元を特定してBANされることは無いのかな、という理解でした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問