つぶの境地

こっちはなんでも🐜

(4)プログラム初心者がPythonを勉強してみる39日目

f:id:tubushiki:20171130145311j:plain

 

情報収集の為のPython

Seleniumから勉強してみようということで書いてみたw

 

前回記事はコチラ 

blog2.tbshiki.com

 毎日の作業を自動化してみる

前回記事にも書いたけど、スクレイピングのパッケージをどれから勉強したらいいかわからなくなっていました。

 

「とりあえず何か書かないと・・・」

 

毎日仕事であるサイトに複数のcsvファイルを手作業でアップロードしています。

それを自動化してみよう!と試行錯誤( ・`д・´)

 

Python初心者の初コードなので、汚いコードで間違いだらけだと思うのですが

その点はご了承ください・・・w

 

 

初めてのPythonプログラム

目的 : "サイトにアクセスしてcsvファイルをアップロード"の自動化

言語 : Python

スクレイピング用パッケージ : Selenium

使用ブラウザ : GoogleChrome

 

Python初心者が書いたプログラムです!

このコードを使用してもらえるのはスーパーミラクル光栄ですが、

何が起きても自己責任でお願いします!ごめんなさい!!

 

【注意点・仕様?・備考】

  • Windowsで実行
  • サイトにはログインが必要
  • アップロードするcsvファイルは複数
  • アップロード完了時にダイアログが表示される
  • 稀にアップロード失敗するので2回繰り返し(ループになるとだめなので2回まで)
  • アップロード完了csvファイルの記録をとりたい
  • アップロード後に表示されるページに表示されたテキストの記録をとりたい
  • 完了メッセージを表示したい

 コード

from selenium import webdriver 
from selenium.webdriver.common.alert import Alert
import time
import os
import wx
import sys

#サイトログインページ情報とログイン情報をまとめる
TOP_URL = "example.com"
UPLOAD_URL = "http://hogehoge.example/"
ID = "id"
PASSWORD = "password"

#ディレクトリを取得
dir_name = (os.path.dirname(__file__))
dir_name = dir_name.replace('\\', '/') #Windows用?に\を/に置換

#完了メッセージ表示用のwxPython
wx_app = wx.App()

#ブラウザ読み込み
driver = webdriver.Chrome("./chromedriver.exe") #chromedriver.exe読み込み
driver.set_page_load_timeout(600) #ページロード最大600秒
driver.get(TOP_URL) #chrome起動→ログインページに移動

time.sleep(1)

#ログイン
id = driver.find_element_by_name("loginid")
id.send_keys(ID)
password = driver.find_element_by_name("password")
password.send_keys(PASSWORD)

time.sleep(1)

#ログインボタンをクリック
login_button = driver.find_element_by_name("login")
login_button.click()

time.sleep(1)

#csv一覧のテキストファイルを読み込みで開いてリストに
csv_list_file = open('./csvlist.txt', 'r') #csvファイルの一覧テキストファイルを読み込み
csv_list = csv_list_file.readlines()
csv_list_file.close()

#csv一覧からできたリスト分繰り返し
for i in range(len(csv_list)):

    #csvを読み込ませるページに移動
    driver.get(UPLOAD_URL)

    time.sleep(1)

    #ファイルの絶対パスを変数に ファイルは/csv/にある
    file_choice_str = dir_name + '/csv/' + csv_list[i].rstrip()

    #ファイル読み込み
    file_choice = driver.find_element_by_name("fileupload")
    file_choice.send_keys(file_choice_str)

    time.sleep(1)

    #アップロードボタンをクリック
    now_upload = driver.find_element_by_class_name("uploadbotton")
    now_upload.click()

    time.sleep(1)

    #読み込み停止時再実行の為の変数設定
    loop_count = 0

    #読み込み停止時再実行用繰り返し
    while True:

        #再実行しすぎを防止
        loop_count += 1

        if loop_count >= 3:
            #エラーメッセージボックスを表示
            wx.MessageBox('3回失敗', 'Python')
            #エラーが続いたのでプログラムを終了
            sys.exit()

        try:
            #ダイアログの表示取得
            alert_text = Alert(driver).text

            #取得した文字列を表示
            print(alert_text)

            #ダイアログのOKを選択
            Alert(driver).accept()

            time.sleep(1)

            #whileを抜ける
            break

        except:
            print("読み込みエラー")

    #ブラウザに表示されたメッセージを取得
    fin_massege = driver.find_element_by_class_name("massege")
    fin_massege_str = fin_massege.text #文字列として変数に代入
    #複数行の場合改行を半角スペースに置換して1行に、行末に改行
    fin_massege2 = csv_list[i].rstrip() + fin_massege_str.replace("\n"," ") + "\n"
    print(fin_massege2)

    #完了ログ用テキストを開いて追記
    fin_massege_txt = open('./finmassege.txt', 'a')
    fin_massege_txt.write(fin_massege2)
    fin_massege_txt.close()

    #読み込みが完了したcsvをテキストから削除して上書き(実際には作り直し)
    csv_list_file = open('./csvlist.txt', 'r') #読み込み専用で開く
    csv_list2 = csv_list_file.readlines() #行ごとにリスト化
    del csv_list2[0] #1行目にあたるリスト0番目を削除
    csv_list_file = open('./csvlist.txt', 'w') #書き込み専用で開く(この時にテキストファイルは空白になる)
    csv_list_file.writelines(csv_list2) #0番目を削除したリストをテキストファイルに
    csv_list_file.close() #テキストファイルを終了

    #繰り返しの為の初期化
    alert_text = ""

#ブラウザを閉じる
driver.close()

#完了メッセージボックスを表示
wx.MessageBox('完了', 'おっPython')
読み込み部分
from selenium import webdriver 
from selenium.webdriver.common.alert import Alert
import time
import os
import wx
import sys
  •  ブラウザ操作の為の selenium 
  • ダイアログを操作する為の alert 
  • 負担軽減の為の time
  • テキストファイル操作の為の os
  • 完了メッセージ表示の為の wx
  • 無限ループ時にプログラム終了させる為の sys

以上のパッケージ・モジュールを読み込みしています。

ページ情報とログイン情報をまとめる
#サイトログインページ情報とログイン情報をまとめる
TOP_URL = "example.com"
UPLOAD_URL = "http://hogehoge.example/"
ID = "id"
PASSWORD = "password"

ログインページのURLとアップロードページのURLが別なのでそれぞれを変数に

ログインIDとパスワードもそれぞれ変数に代入。

ディレクトリ取得
#ディレクトリを取得
dir_name = (os.path.dirname(__file__))
dir_name = dir_name.replace('\\', '/') #Windows用?に\を/に置換

テキストファイルを操作するためにファイルの場所を取得しています。

.pyファイルとcsv一覧や完了メッセージ記録のテキストは同一ディレクトリに設置。

ディレクトリを取得したときにパスが ”\” (バックスラッシュ)になっているので "/" (スラッシュ)に置換しています。

この部分はもっといい方法がありそう・・・

 完了メッセージを出力するためにwxPython用設定
#完了メッセージ表示用のwxPython
wx_app = wx.App()

 PythonにはGUIを操作するwxPythonを読み込む。

Seleniumでいう"driver = webdriver.hogehoge"と同じようなもんだと思ってる。

Selenium用のchromedriverを読み込ませる
ブラウザ読み込み
driver = webdriver.Chrome("./chromedriver.exe") #chromedriver.exe読み込み
driver.set_page_load_timeout(600) #ページロード最大600秒
driver.get(TOP_URL) #chrome起動→ログインページに移動

time.sleep(1)

 前回も紹介した記事を参考にchromedriverを読み込ませる。

qiita.com

csvファイルのアップロードには時間がかかる場合もあるので待ち時間を長めに設定。

2~3分で終わるけども10分で設定してる。

以下リファレンスを参考に driver.set_page_load_timeout(*) で待ち時間を設定。

www.seleniumqref.com

接続先への負担分散?防止?の為にページ遷移後には1秒の待機を設定。

IDとパスワードを入力してログインボタンをクリック
#ログイン
id = driver.find_element_by_name("loginid")
id.send_keys(ID)
password = driver.find_element_by_name("password")
password.send_keys(PASSWORD)

time.sleep(1)

#ログインボタンをクリック
login_button = driver.find_element_by_name("login")
login_button.click()

time.sleep(1)

send.key() と .click() を使ってログイン情報を入力してログイン。

ここでもページ遷移後には1秒の待機を設定。

読み込ませるcsv一覧のテキストを読み込み

#csv一覧のテキストファイルを読み込みで開いてリストに
csv_list_file = open('./csvlist.txt', 'r') #csvファイルの一覧テキストファイルを読み込み
csv_list = csv_list_file.readlines()
csv_list_file.close()

プログラムと同一ディレクトリに保存している csvlist.txt に読み込ませるcsvファイル名をまとめている。

 csvlist.txtの内容

product001.csv
product002.csv
product003.csv
product004.csv
product005.csv

テキストファイルを読み込み専用で開いて、1行ずつリストに格納。

テキストを閉じる。

 リストの分繰り返し
#csv一覧からできたリスト分繰り返し
for i in range(len(csv_list)):

    #csvを読み込ませるページに移動
    driver.get(UPLOAD_URL)

    time.sleep(1)

 for を使って繰り返しを設定。

繰り返し先頭でアップロードページへ移動させています。

アップロードするcsvファイルのパスを変数に設定してアップロード
    #ファイルの絶対パスを変数に ファイルは/csv/にある
    file_choice_str = dir_name + '/csv/' + csv_list[i].rstrip()

    #ファイル読み込み
    file_choice = driver.find_element_by_name("fileupload")
    file_choice.send_keys(file_choice_str)

    time.sleep(1)

    #アップロードボタンをクリック
    now_upload = driver.find_element_by_class_name("uploadbotton")
    now_upload.click()

    time.sleep(1)

アップロードするcsvファイルは /csvフォルダに置いています。

下記記事を参考に .send_keys を使ってcsvファイルのパスを読み込ませます。

アップロードボタンをクリックさせて待機。

読み込みエラーの対応とダイアログの確認・ダイアログ選択
   #読み込み停止時再実行の為の変数設定
    loop_count = 0

    #読み込み停止時再実行用繰り返し
    while True:

        #再実行しすぎを防止
        loop_count += 1

        if loop_count >= 3:
            #エラーメッセージボックスを表示
            wx.MessageBox('3回失敗', 'Python')
            #エラーが続いたのでプログラムを終了
            sys.exit()

        try:
            #ダイアログの表示取得
            alert_text = Alert(driver).text

            #取得した文字列を表示
            print(alert_text)

            #ダイアログのOKを選択
            Alert(driver).accept()

            time.sleep(1)

            #whileを抜ける
            break

        except:
            print("読み込みエラー")

極稀に読み込みエラーダイアログ表示されずにページ遷移してしまう。

 

csv読み込み後にダイアログが表示されずにページ遷移した場合、

try: で設定した Alert(driver).text が取得できずエラーになるので

except: のコードが実行される。

except: には break を記述していないので while のループが働いて自動再実行の為に繰り返し。

 

 エラー3回目にはメッセージボックスを表示させてプログラムを終了したい。

 

以下記事を参考にエラーメッセージを表示させるメッセージボックスを設定。

wxPythonでメッセージボックス表示に関する詳しい記事がなかなかみつからなかったので苦戦した、ありがたいw

python-minutes.blogspot.com

プログラムを終了させたいので

以下記事を参考にしてエラーが出た場合に終了を設定。 

uxmilk.jp

 正しくcsvファイルが読み込まれた場合、ダイアログが表示させる。

ダイアログの内容を表示して、ダイアログのOKを選択している。

読み込み完了のブラウザ表示メッセージを取得して改行をなくす
    #ブラウザに表示されたメッセージを取得
    fin_massege = driver.find_element_by_class_name("massege")
    fin_massege_str = fin_massege.text #文字列として変数に代入
    #複数行の場合改行を半角スペースに置換して1行に、行末に改行
    fin_massege2 = csv_list[i].rstrip() + fin_massege_str.replace("\n"," ") + "\n"
    print(fin_massege2)

.find_element_by_class_name("*") で要素を変数に代入。

そのままだとエラーになるので .text を使用して文字列のみを別の変数に。

読み込ましたcsvファイル名と表示メッセージを結合して改行を半角スペースに置換

完了ログをテキストに残す
    #完了ログ用テキストを開いて追記
    fin_massege_txt = open('./finmassege.txt', 'a')
    fin_massege_txt.write(fin_massege2)
    fin_massege_txt.close()

完了ログを記録したいテキストを同じディレクトリに用意しておく。

finmassege.txt として、追記モードで開いて書き込み、からの閉じる処理。

再実行したときに重複アップロードを防ぐ為にリスト編集
    #読み込みが完了したcsvをテキストから削除して上書き(実際には作り直し)
    csv_list_file = open('./csvlist.txt', 'r') #読み込み専用で開く
    csv_list2 = csv_list_file.readlines() #行ごとにリスト化
    del csv_list2[0] #1行目にあたるリスト0番目を削除
    csv_list_file = open('./csvlist.txt', 'w') #書き込み専用で開く(この時にテキストファイルは空白になる)
    csv_list_file.writelines(csv_list2) #0番目を削除したリストをテキストファイルに
    csv_list_file.close() #テキストファイルを終了

途中でプログラムが停止した場合等の"念のため"csv一覧のテキストファイルを1行目から削除する。

 

読み書き専用の r+ や w+ でファイルを開くと開いた段階でテキストファイルの中身が消えてしまった・・・。

なんでや・・・w

 

なので一度読み取り専用で開いて、行ごとにリストに格納。

1行目にあたるリスト0番目を削除して、テキストファイルを書き込み専用で開く。

書き込み専用で開いてリストで全上書き。

.close()と同時に上書き保存。

 

r+ と w+ と a+ の違いがわからん、難しい/(^o^)\

繰り返しの為に初期化
    #繰り返しの為の初期化
    alert_text = ""

Pythonにも変数の初期化って必要・・・?

エラー繰り返しの表示でかしい可能性があるので変数初期化

いま考えると他にも初期化しないといけないような変数あるやん・・・w

\(^o^)/

ブラウザを閉じてメッセージボックスを表示
#ブラウザを閉じる
driver.close()

#完了メッセージボックスを表示
wx.MessageBox('完了', 'おっPython')

繰り返しが終了するのでブラウザを閉じる。

エラー時と同じ要領でメッセージボックスを表示。

 

おっPython

 

初のPythonプログラミング頑張った!

おおう・・・プログラムも記事も長くなった・・・w

ExcelVBAからIE操作したことはあるけど、Python安定力ハンパない。

 

あとVisual Studio Code すごいわw

書きやすいしデバックしやすいしw

デバック時に上に戻れたらもっといいのになー……

 

誰か添削してくれませんか(`;ω;´)

1人でプログラム書いてると良いコードなのか悪いコードなのかがわからないんです。

動けばいい!っていう方もいらっしゃるとも思いますが、書くなら良いコードを書きたいなーとw

Pythonプログラマー先輩のみなさま、どうでしょうか・・・?

 

あと一緒にPython勉強してくれる方お友達になってください!w 

 

 

 とにかくまだまだ勉強することは多そう

次はなに作ろうかなー

 

ありがとう