スクレイピング入門　（Python）

# はじめに
昨今なにかとアツいスクレイピング。
様々な理由で興味がある人もいるのではないでしょうか

私自身も
- 趣味であるTCG（主にポケモンカード）を何とかECサイトで定価購入したい
- でもECサイトの定価販売なんて秒で売り切れるから買えない
- 代わりに機械が勝手に買ってくれたらうれしいな

という願望からスクレイピングに手を出し、何とか自動購入ツールを完成させました。

今回はそんな私がスクレイピングに入門するにあたって学んだことを
備忘録として記します。

※様々な記事で言われていることですが、スクレイピングを禁止しているサイトもあるのでご自身で規約を読まれて自己責任でお願いします。

# 紳士的なスタンスで開発を
某図書館システムの事件がよくある例ですが、サイトを巡回するようなプログラムを作る場合はアクセス頻度の設定に気を付けましょう。
逮捕されます！まじで！

1秒に1回程度が界隈標準となっているとかいないとか。。。
（サイトによっては規約に明記されていることもあるので、規約の確認はしっかり行いましょう）


# 環境
|ライブラリ名  |バージョン  |備考  |
|---|---|---|
|selenium  |4.13.0  |Web ブラウザの操作を自動化するためのフレームワーク  |
|requests|2.31.0|HTTP通信用のPythonのライブラリ<br>※現状は未使用|
|BeautifulSoup|4.12.2  |HTMLやXMLファイルからデータを取得し、解析するPythonのWEBスクレイピング用のライブラリ<br>※現状は未使用|

※venv仮想環境内のwebドライバを最新版に更新するときは仮想環境内のディレクトリにあるwebドライバ(.exe)ファイルを入れ替える！
# いざ、Tips
必要なライブラリは適宜インストール＆インポートしておいてください
```python
import selenium
import requests
import bs4
import time
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
```

## ブラウザ起動
起動する
```python
driver = webdriver.Chrome() #chrome起動
```

ヘッドレスモードで起動する場合
```python
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
```

## ページ遷移する
まずは操作したいページにアクセスする
```python
driver.get("アクセスしたいページのURL")
```

## 基本は要素を探してメッセージを送る
操作したいページにアクセスしたら、実際にページ内を操作していく
基本的な流れは「要素を探す⇒メッセージ（操作内容）を送信する」

### 要素を探す
```python
driver.find_element(By.ID, "login_handle")
```
要素を探すためのキーはいくつか種類がある
|キー|内容||
|---|---|-|
|By.ID|id属性値で指定||
|By.CSS_SELECTOR|class属性で指定||
|By.CLASS_NAME|name属性で指定||
|By.XPATH|XPathで指定|一番便利かも！|

https://qiita.com/suipy/items/18af39c5199df6430c84

### 文字の入力　send_keys()
```send_keys()```で文字を入力する
```python
driver.find_element(By.ID, "login_handle").send_keys("送りたいメッセージ")
```
エンターキー押下などはこのように送る
```python
driver.find_element(By.ID, "login_handle").send_keys(Keys.ENTER)
```
### ボタンクリック click()
```click()```でボタンをクリックする
```python
driver.find_element(By.CSS_SELECTOR, ".style_BasketSumToOrder__buttonLargeText__mhPU9").click()
```
上記```click()```の方法で「element click intercepted」のエラーが出る場合は
```execute_script()```を使ってjavascript実行させる
```python
btn_add_cart = driver.find_element(By.ID, "add_cart")
driver.execute_script('arguments[0].click();', btn_add_cart)
```


## ページの読み込みが完了するまで待機する
まだ読み込まれていない要素へアクセスしようとするとエラーが発生するので、これを回避する為に読み込みが完了するまで待機する必要がある。
```python
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome() #chrome起動
wait = WebDriverWait(driver=driver, timeout=30)# 最大の読み込み時間を設定 今回は最大30秒待機できるようにする

wait.until(EC.presence_of_all_elements_located)# 要素が全て検出できるまで待機する
```
注意点としては
- ```wait```の定義は```driver```のインスタンスを作成したときのみで十分で、以降は使い回しできること
- ```wait.until()```は待ちたいタイミングで呼ぶこと

## 指定した要素が見つかるまでの待機時間を設定する
ページ内の全ての要素が読み込まれていなくても、使いたい要素が読み込まれ次第処理を開始したいときがある。（というかタクト考えると基本こっちの方が需要高そう）
```python
import selenium
from selenium import webdriver

driver = webdriver.Chrome() #chrome起動
driver.implicitly_wait(10) #今回は最大10秒待機する
```
```implicitly_wait()```の呼び出しは```driver```のインスタンスを作成した時のみで十分で、以降は気にする必要はない。
待ちたいタイミングで毎回関数を呼び出す必要が無いので便利

## WebDriverとMS Edgeのバージョンが合わなくなったとき

https://softcore777.main.jp/AExpert/SeleniumDL/EdgeDrv/index.html

# 最後に
ここまで読んでいただきありがとうございます。

まだまだスクレイピングに関して勉強中の身ですので
本記事も随時アップデートしていきます！！

ご意見、ご感想、コメントぜひぜひよろしくお願いいたします。


zennでも活動していますので、応援よろしくお願いします。

https://zenn.dev/hiyokotti