Selenium4系でのWebスクレイピング


# 概要
Selenium4系での記述でWebスクレイピングした内容をまとめます。

## 経緯
仕事でWebシステムの管理ページから複数のログなどを取得するscriptを作って、自動化する取り組みがありました。
何年か前にSeleniumでWebスクレイピングしていたので、応用すればいいかって思ってたら、Selenium4系だと記述方法変わってて少し混乱しました。
後、Pythonも3.11使うように指示があったので、以前使っていたモジュールが対応してなかったり、色々考える部分がありました。

## 環境
Python3.11
selenium 4.6.0
ChromeDriver（[お使いのGoogleChromeのVerに合わせてダウンロード](https://chromedriver.chromium.org/downloads)）

# 内容
Selenium4系での記述の違いは以下になります。

elementの後に(　)で囲う範囲が広くなりました。

```python
driver.find_element(By.NAME,"name").send_keys("hoge") #selenium 4系
driver.find_element_by_name("name").send_keys("hoge")　#selenium 3系
```

インポートはこんな感じで書かないとうまく動きませんでした。
どういう理屈かわかったら、追記します。どなたか知っていたら教えてください。

```python
from selenium import webdriver
from selenium.webdriver.common.by import By
```

## 今回書いたコード内容

普段自分でコード書いてるわけじゃないので、素人臭いですがとりあえず、欲しい動きはしてくれたのでよかったです。

流れとしてはWEBシステム内のログとメンバー情報を抜き出して保存するという内容です。ここには書きませんが、この後取得したcsvの加工まで自動化するscriptも作っています。

```python
import datetime
import os
import shutil
import time
import zipfile
from selenium import webdriver
from dateutil.relativedelta import relativedelta
from selenium.webdriver.common.by import By

# 定義
urlA = "http://www.hogehoge.com"
loginUrl = urlA + "/admin.html"
urlB = "https://www.hogehoge.biz/"
logUrl = urlB + "/main/hogehoge"
downloadUrl1 = urlB + "/main/hogechanhogechan"
downloadUrl2 = urlB + "/main/hogehogehoge"
memberUrl = urlB + "/hoge/hogehogehoge"
adminID = "hogechan"
loginName = "hogehoge"
password = "hogehoge"
currentpath = os.path.dirname(__file__)
```

とりあえず、使うモジュールをインポートして、定義で対象のWEBシステムのURLが長いので、分割して定義してくっ付けて使ったり、IDやパスワードを定義しています。

```python
# ブラウザを開いてログインまで
driver = webdriver.Chrome()
driver.get(loginUrl)
time.sleep(3)
driver.find_element(By.NAME, "adminid").send_keys(adminID)
driver.find_element(By.NAME, "loginname").send_keys(loginName)
driver.find_element(By.NAME, "password").send_keys(password)
driver.find_element(By.NAME, "login").click()
```
Webブラウザを開いてログインまで行います。

```python
# アクセスログの取得
driver.get(logUrl)
driver.get(downloadUrl1)
driver.get(downloadUrl2)
time.sleep(2)

# 日時の取得
dt_now = datetime.datetime.now()
lastMonth_year = str((dt_now - relativedelta(months=1)).year)[2:]
twoMonthsAgo_year = str((dt_now - relativedelta(months=2)).year)[2:]
lastMonth = str((dt_now - relativedelta(months=1)).month)
twoMonthsAgo = str((dt_now - relativedelta(months=2)).month)

# ダウンロードの移動
folder = os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH")
downloadpath = folder + "\\Downloads\\"
fileName1 = lastMonth_year + "-" + lastMonth.zfill(2) + "_idasplog.zip"
fileName2 = twoMonthsAgo_year + "-" + twoMonthsAgo.zfill(2) + "_idasplog.zip"
os.chdir(downloadpath)
shutil.move(fileName1, currentpath + "\\csv\\" + fileName1)
shutil.move(fileName2, currentpath + "\\csv\\" + fileName2)
time.sleep(1)
```
ここでは、アクセスログを取得するページからダウンロードして、ダウンロードフォルダに保存されたファイルを実行環境のcsvフォルダに格納するような流れになります。
ダウンロードフォルダを変更するようにもできるのですが、実行する環境が変わっても汎用的に動くようにしたかったのでこの形にしました。

途中日時を取得しているのは、ファイル名が年月をファイル名にするためです。ちなみにログは3月分しか保管されない糞仕様なので、1ヶ月分満タンになってる先月分と先々月分のデータのみ取得します。

```python
# メンバー情報の取得
driver.get(memberUrl)
memberXpath = ("Xpath/hogehoge")
driver.find_element(By.XPATH, memberXpath).click()
time.sleep(2)

# ダウンロードの移動
memberLink = driver.find_element(By.XPATH, memberXpath).get_attribute("href")
n = len("URL")
m = 33  # csvファイル名の文字数
fileName3 = memberLink[n : n + m]
os.chdir(downloadpath)
shutil.move(fileName3, currentpath + "\\member\\" + fileName3)

# Zipの解凍
os.chdir(currentpath + "\\csv\\")
with zipfile.ZipFile(fileName1) as myzip:
    myzip.extractall()
with zipfile.ZipFile(fileName2) as myzip:
    myzip.extractall()
```
ここでは、現在のメンバー情報を取得しています。ダウンロードの移動のところは、ファイル名の取得が面倒だったのと、後工程のためにZipの解凍を行っています。

# まとめ

Selenium4系での記述の違いは以下になります。elementの後に(　)で囲う範囲が広くなりました。

```python
driver.find_element(By.NAME,"name").send_keys("hoge") #selenium 4系
driver.find_element_by_name("name").send_keys("hoge")　#selenium 3系
```

インポートはこんな感じで。どういう理屈かわかったら、追記します。どなたか知っていたら教えてください。
```python
from selenium import webdriver
from selenium.webdriver.common.by import By
```

## 参照

https://zenn.dev/miyajan/articles/whats-new-in-selenium-4

http://holiday-programmer.net/selenium_ver_check/

https://web-tweets.com/python/pythonxselenium%E3%81%A7a%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%AEhref%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/

https://qiita.com/tomotaka_ito/items/594ee1396cf982ba9887

https://qiita.com/dkugi/items/8c32cc481b365c277ec2