9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Python+SeleniumでGet Wild退勤打刻する

Posted at

PythonでSeleniumを覚えたので使ってみたかった。環境は以下。

  • Microsoft Windows 10 Pro
  • Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)]

動機

Get Wild退勤。
ネットで話題の「Get Wild退勤」とは? SNS大盛り上がり「あー分かります!」「今度してみますw」「出勤時はセルフコントロール」 元ネタは以下らしい。

コロナ禍の今、以前のようにさっそうとオフィスを後にすることもなかなかできなくなってしまった。在宅勤務でも、Get Wild で退勤したい。

Python+SeleniumでブラウザからGet Wild退勤打刻する

私は毎日、いわゆる普通の打刻画面からぽちぽちやっている。

こういうやつ

image.png
記事の説得力8割減だが大人の事情でお絵かきにしておいた (Powered by https://cacoo.com/ )。「退勤」ボタンを押すのが私の退勤。これに、以下をプラスしたらWild and Toughである。(Youtube: Get Wild)

実装

getwildandtough_taikin.py
#!python3.8

import time
import chromedriver_binary

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.keys import Keys

# https://selenium-python.readthedocs.io/
# この辺は退勤アプリに合わせる。あくまで私の場合。

url = "{退勤打刻URL}"
elem_name_inp_uid = "{user_id}"
elem_val_inp_uid = "{ユーザID}"
elem_name_inp_pwd = "{password}"
elem_val_inp_pwd = "{パスワード}"
elem_name_btn_logout = "{退勤ボタン}"

# driver = webdriver.Chrome() このコメントアウトの理由は後述
driver = webdriver.Chrome(ChromeDriverManager().install())

# タブを開く
# OSにあわせて (Keys.COMMAND + 't') にしたりするようだ
driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 't') 

# GetWild を開く
driver.get('https://www.youtube.com/watch?v=NHKq8IOXPxA')

# 再生ボタンをクリック
driver.find_element_by_class_name('ytp-play-button').click()

# 広告をスキップしたいけど、広告が出ないこともある
# https://github.com/1993jayant/youtube_adskipper/blob/master/youtube_adskipper.py
# https://github.com/douasin/youtube-ad-skipper/blob/master/youtube_ad_skipper.py
# https://stackoverflow.com/questions/62745175/how-to-click-the-skip-ads-button-in-youtube-using-selenium-in-python-3
# https://stackoverflow.com/questions/36503730/continue-the-script-if-an-element-is-not-found-using-selenium-in-python

# 一旦、3回分チャレンジ
# 例外が出たら次へ
for i in range(3):
    time.sleep(10)
    try:
        driver.find_element_by_class_name('ytp-ad-skip-button.ytp-button').click()
    except:
        print("ex occured");

# 最終的に、もう30秒間Getwildに浸る
time.sleep(30)

driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 't') 

# ようやく打刻
driver.get(url)

elem_inp_uid = driver.find_element_by_name(elem_name_inp_uid) 
elem_inp_uid.clear()
elem_inp_uid.send_keys(elem_val_inp_uid)
elem_inp_pwd = driver.find_element_by_name(elem_name_inp_pwd)
elem_inp_pwd.clear()
elem_inp_pwd.send_keys(elem_val_inp_pwd)
elem_btn_logout = driver.find_element_by_class_name(elem_name_btn_logout)
elem_btn_logout.click()

# お疲れさまでした
time.sleep(5)

GitHub: https://github.com/e99h2121/python_selenium_login/blob/main/getwildandtough_taikin.py

ひとりでは解けない愛のパズル

処理フローは以下。

  1. ブラウザ起動。
  2. Youtubeに遷移。
  3. 広告が出たり、出なかったり、5秒で出たり、スキップしないと1分かかったりするから、できればスキップしたい。
  4. しかし出ないときもあるから、スキップボタンを押せなかったら、構わず進まないといけない。
  5. 脳内がGet Wildに染まったら、爆破されたオフィスを妄想しながら、退勤打刻。
  6. お疲れさまでした。

ケース1: スキップできる広告の場合

getwild4.gif

ケース2: スキップしない広告の場合

getwild3.gif

以下がChance and luck という処理のゴール

image.png
画像はイメージです。

アスファルトがタイヤを切りつけてきたポイント4点

1. 広告の長さが変わるYoutubeとどう付き合うか

Youtubeの広告をSeleniumでいかに処理するかは工夫どころのようだ。
参考: 動画広告(15 秒動画広告、30 秒動画広告、スキッパブル動画広告)
動画を開いた時に以下パターンがある。

  • 数秒の広告動画(スキップできない)が流れる
  • 数秒後に「広告をスキップ」できる広告動画が流れる
  • 広告が流れない

本編の動画に極力ストレスなくPython+Seleniumで画面遷移させたい。

GitHubより

GitHubのadskipper.
https://github.com/1993jayant/youtube_adskipper

This is a program written in python programming language. It automatically clicks on the 'skip ad' button on the youtube ads. It uses opencv library's Template Matching functionality to do that.

あるいは、
https://github.com/douasin/youtube-ad-skipper/blob/master/youtube_ad_skipper.py

    def check_ad(self):
        try:
           self.driver.find_element_by_class_name("videoAdUiPreSkipButton").click()
            self.has_ad = True
            return self.driver.find_element_by_class_name("videoAdUiPreSkipText").text
        except:
            return None

    def skip_ad(self):
        try:
            self.has_ad = False
            self.total_skip_ad += 1
            print("已跳過{}個廣告".format(self.total_skip_ad))
            self.driver.find_element_by_class_name("videoAdUiSkipButton").click()
            sleep(1)
            #return self.driver.find_element_by_class_name("videoAdUiSkipButtonExperimentalText").text
        except:
            return None

Stackoverflowより

どうやってスキップボタンを押すか。
[How to click the 'skip ads' button in youtube using selenium in python 3](https://stackoverflow.com/questions/62745175/how-to-click-the-skip-ads-button-in-youtube-using-
selenium-in-python-3)
要素が見つからない時、どう処理するか。
Continue the script if an element is not found using selenium in Python

シンプルにPython例外処理の基礎

https://www.atmarkit.co.jp/ait/articles/1909/06/news019.html
で、有限回数リトライを以下、今回のGet Wild退勤では妥協点とした。

抜粋.py
# 一旦、3回分チャレンジ
# 例外が出たら次へ
for i in range(3):
    time.sleep(10)
    try:
        driver.find_element_by_class_name('ytp-ad-skip-button.ytp-button').click()
    except:
        print("ex occured");

2. ブラウザで別タブをどう開くのか

Open web in new tab Selenium + Python
これも分かっていれば簡単だが、大事なのでメモする。

引用.py
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

driver = webdriver.Firefox()
driver.get("http://www.google.com/")

# タブを開く
driver.find_element_by_tag_name('body').send_keys(Keys.COMMAND + 't') 
# You can use (Keys.CONTROL + 't') on other OSs

# ページを読み込む 
driver.get('http://stackoverflow.com/')
# 必要に応じて画面処理

# これも必要に応じて閉じる。今回のGetWild退勤打刻では、打刻画面に更に遷移
# (Keys.CONTROL + 'w') on other OSs.
driver.find_element_by_tag_name('body').send_keys(Keys.COMMAND + 'w') 

3. find_elements_by_class_namefind_element_by_class_name は別物である

複数形と、単数形があるのですね。

AttributeError: 'list' object has no attribute 'click'

などというエラーが出ていたが driver.find_elements_by_class_name(elem_name_btn_logout) 等と elements (複数形) を選択していたからであった。以下で動作。

elem_btn_logout = driver.find_element_by_class_name(elem_name_btn_logout)
elem_btn_logout.click()

参考: AttributeError: 'list' object has no attribute 'click' - Selenium Webdriver
写経をミスった凡ミスなのですが。勉強になりました。

4. ChromeDriver、更新されたらどうなるの

Python × Selenium × Chromeでブラウザ操作自動化をしてるけど、ブラウザバージョン更新のたびにChromeDriverを手動で更新するのが面倒すぎる!

たしかに今は動いていても、そのうちUpdateされたらいつの間にかエラーになりそうだ。
そんな時にこれ。

抜粋すると以下。

before.py

from selenium import webdriver
import chromedriver_binary
 
driver = webdriver.Chrome()
driver.get('https://google.com')

導入後

after.py

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
 
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('https://google.com')

まとめ: この街で優しさに甘えていたくはない

デバッグしていると脳内がWild and Toughだった。
というか退勤ボタンポチるためだけに何やってるのか早く退勤しろ社会人(私)。

等、自分の理解の助けになりました。It's your pain or my pain or somebody's painです。
Python と Playwright でブラウザを自動操作させるコードを自動生成したよ も使えるのかなあ等とおもいつつの勉強記録でした。デイリーポータルみたいだな
お楽しみいただけたらさいわいです。

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?