LoginSignup
2
2

More than 5 years have passed since last update.

Python3+Selenium(Selene)+Chrome(headless)でMyDNS.jpを自動更新する

Last updated at Posted at 2017-12-30

Dockerイメージの作成

環境を汚したくないので、Dockerを使います。
Dockerfile中のgoogle-chromeの内容は
EC2 UbuntuでGoogle Chromeをヘッドレス実行してスクリーンショットを採取する手順を参考にしています。

Dockerfile
FROM    python:3.6-stretch

ENV     DEBIAN_FRONTEND noninteractive

RUN apt-get update && \
        apt-get install -y --no-install-recommends unzip wget curl unzip fontconfig && \
    wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add - && \
    echo "deb http://dl.google.com/linux/chrome/deb/ stable main" | tee /etc/apt/sources.list.d/google-chrome.list && \
    apt-get update && \
    apt-get -y install --no-install-recommends  google-chrome-stable

RUN     apt-get update && \
        apt-get install -y --no-install-recommends python3-dev python3-pip && \
        rm -rf /var/lib/apt/lists/*
RUN     pip3 install selene --pre

RUN wget https://chromedriver.storage.googleapis.com/2.31/chromedriver_linux64.zip && \
    unzip chromedriver_linux64.zip -d /usr/bin/

WORKDIR /data
VOLUME  /data

COPY    IPAfont00303.zip /data/IPAfont00303.zip

RUN unzip IPAfont00303.zip -d /usr/share/fonts/ && \
    fc-cache -fv

IPAfont00303.zipファイルのダウンロードはDockerfile中にwgetすると終了コードがエラーになって失敗するため事前にzipファイルでダウンロードしておき、ビルド時にホストからコピーします。

MyDNS.jp更新用のスクリプト作成

Python経由でSeleniumを使用して更新を行います。
Selenium単体だと要素の指定が面倒なため、
CSSセレクタなどで要素の選択ができる「Selene」を使用します。

※Seleneの導入については、Selene : Python にも Selenide ライクな Selenium ラッパーありますを参考にさせて頂きました。

mydns.py
# -*- coding: utf-8 -*-
import os
import traceback
import sys
import logging

from selene import config
from selene.browsers import BrowserName
from selene.api import *
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def main():
    args = sys.argv
    logger = logging.getLogger(__name__)

    username = os.getenv("MYDNS_USER", "guest")
    password = os.getenv("MYDNS_PASS", "password")

    if len(args) < 2:
        raise ValueError("Please specify one of the least argument")

    options = Options()

    # google-chromeのインストールパス指定
    options.binary_location = '/usr/bin/google-chrome'

    # ヘッドレスモードで起動
    options.add_argument('--headless')
    options.add_argument('--no-sandbox')

    # 画面サイズ指定
    options.add_argument('--window-size=1280,1024')

    driver = webdriver.Chrome('chromedriver', chrome_options=options)

    config.browser_name = BrowserName.CHROME

    browser.set_driver(driver)

    # Mydnsトップページを開く
    browser.open_url('https://www.mydns.jp/')

    # ユーザー名,パスワード入力してログインボタンをクリック
    setvalue_nophoto('dd.content12:nth-child(3) > input:nth-child(1)',username)
    setvalue('dd.content12:nth-child(5) > input:nth-child(1)',password)
    clickbutton('dd.content12:nth-child(7) > input:nth-child(1)')

    # IP ADDE DIRECTを選択
    clickbutton('''body > table:nth-child(1) > tbody:nth-child(1) > 
                    tr:nth-child(4) > td:nth-child(1) > table:nth-child(1) > 
                    tbody:nth-child(1) > tr:nth-child(5) > td:nth-child(1) > 
                    a:nth-child(1) > img:nth-child(1)''')

    # IP v4アドレスをセット
    setvalue('dd.content14:nth-child(4) > input:nth-child(1)',args[1])

    # checkボタン押下
    clickbutton('dd.content12:nth-child(9) > input:nth-child(1)')

    # okボタン押下
    clickbutton('''table.content14:nth-child(3) > tbody:nth-child(1) > 
                    tr:nth-child(6) > td:nth-child(1) > input:nth-child(1)''')

    driver.quit()

def setvalue(cssselector,value):
    setvalue_nophoto(cssselector,value)
    browser.take_screenshot("mydns")

def clickbutton(cssselector):
    clickbutton_nophoto(cssselector)
    browser.take_screenshot("mydns")

def setvalue_nophoto(cssselector,value):
    s(by.css(cssselector)).set_value(value)

def clickbutton_nophoto(cssselector):
    s(by.css(cssselector)).click()

if __name__ == '__main__':
    main()

要素のCSSセレクタはブラウザからの取得そのままなので、最適ではない可能性があります。
第一引数には設定するIPv4アドレスを設定します。

Jenkinsで定期実行してみる

jenkinsfile
pipeline {
    agent {
        docker {
            image '(ビルドしたdockerイメージ名)'
        }
    }
    environment {
        MYDNS_USER="(mydnsのユーザー名)"
        MYDNS_PASS="(mydnsのパスワード)"
    }       
    stages() {
        stage('update-mydns')
        {
            steps() {
                checkout scm
                script { 
                    def ipaddress = globalip()

                    sh script: 'python mydns.py ' + ipaddress

                    archiveArtifacts artifacts: 'mydns/*.png'
                }
            }
        }        
    }

}

def globalip() {
    sh (
        returnStdout: true, 
        script: '''
            curl ifconfig.io
        '''
    )
}

archiveArtifactsしておけば、Selenium中で取得したスクリーンショットの保存が行えます。

2
2
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
2
2