[Python] 261 subprocessモジュール1 日付を出力

[macOS Catalina 10.15.7]

Bashのコマンドで日付を出力させてみました。

今日の日付は特に問題ないですが、3日後の書き方でドハマりしました。

とりあえず出力できましたが、他にスマートな書き方がないのであればこの使い方ではBash&macOSは却下です。

Zshにすれば普通になるのでしょうか。

import subprocess
from subprocess import PIPE
import datetime

# 今日の日付 Bash
com_date = subprocess.run("date +%y%m%d", shell=True, stdout=PIPE, stderr=PIPE, text=True)
date = com_date.stdout

print(date)

# 今日の日付 Python
date_today = datetime.date.today()
date_today_str = date_today.strftime('%y%m%d')

print(date_today_str)

# 3日後の日付 Bash 時差+9-72=-63 このスクリプトは可読性低い
com_date_3 = subprocess.run("env TZ=JST-63 date +%y%m%d", shell=True, stdout=PIPE, stderr=PIPE, text=True)
date_3 = com_date_3.stdout

print(f'date_3 {date_3}')

# 3日後の日付 Python
days3 = datetime.timedelta(days = 3)
date_days3 = date_today + days3
date_days3_str = date_days3.strftime('%y%m%d')

print(f'date_days3_str {date_days3_str}')
--------------------------------------------------

出力
--------------------------------------------------
210527
210527
date_3 210530
date_days3_str 210530

[Python] 260 chromedriverのバージョン管理 Homebrew編

[macOS Catalina 10.15.7]

これまではseleniumが動かなくなるたびにGoogle Chromeのサイトから最新のchromedriverをダウンロードして配置していましたが、あまりにも非効率なのでHomebrewのchromedriverを使うことにしました。

以下、関連コマンド等を記しておきます。

chromedriverのインストール

brew install chromedriver

# .bash_profileに追記
export PATH="/opt/homebrew/bin:$PATH"

# インストール先の例(オリジナル)
/usr/local/Caskroom/chromedriver/[Chromeのバージョン番号]/chromedriver
/opt/homebrew/Caskroom/chromedriver/[Chromeのバージョン番号]/chromedriver

# エイリアス配置先の例
/usr/local/bin/chromedriver
/opt/homebrew/bin/chromedriver

brewのインストール先を確認

brew --prefix

chromedriverの最新バージョンと導入有無の確認

brew info chromedriver

chromedriverのアップデート(毎日crontabで定期実行)

brew upgrade chromedriver

Pythonコード内の記述

from selenium import webdriver

driver = webdriver.Chrome()

[Python] 259 pyenv 2.0.0に関する警告

pyenvを2.0.0にバージョンアップするとターミナル起動時に以下の警告が表示されるようになりました。

WARNING: `pyenv init -` no longer sets PATH.
Run `pyenv init` to see the necessary changes to make to your configuration.

調べたところpyenvコマンドのオプションが変更になったようです。

.bash_profileを以下のように変更すると警告は出なくなりました。3行目だけ手を入れてます。

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"

ちなみに以前はこのように記述していました。

eval "$(pyenv init -)"

[Python] 258 pyenv仮想環境にanacondaを導入

これまで簡単なコードの検討にはIDLEの対話モードを使っていましたが、jupyterも便利そうなので試してみることにしました。

以下、pyenv仮想環境へのanaconda導入過程です。anacondaのjupyterを使うと主要なライブラリをインストールする手間がかかりません。

macOSでは現時点で最新のanaconda3-2021.05をインストールします。

# pyenv仮想環境にanaconda3-2021.05をインストール
pyenv install anaconda3-2021.05

# pyenvに入っているPythonのバージョンを確認する
pyenv versions
[出力]
  system
  3.7.4
  3.8.2
  3.8.3
  3.8.5
  3.8.6
  3.9.0
* 3.9.2 (set by /Users/[ユーザ名]/.pyenv/version)
  anaconda3-2021.05

# anacondaを使う専用ディレクトリnotebookを作成しカレントディレクトリを移動させる
cd ~/notebook

# notebookディレクトリでのみanacondaを使うように設定する
pyenv local anaconda3-2021.05

# anacondaで使えるPythonのバージョンを確認する
python -V
[出力]
Python 3.8.8

# jupyterを起動する
jupyter-notebook

[Python] 257 空のディレクトリを削除する 類例

前記事で紹介したコードの”glob.glob”が同語の繰り返しで何となく野暮ったいので少し表現を変えてみました。

importが1行増えますが、こちらの方が私の好みです。

import shutil,os
from glob import glob

dir_l = [dir for dir in glob('親ディレクトリのパス/*') \
if os.path.isdir(dir)]]
print(dir_l)

for dir in dir_l:
    file_l = [file for file in glob(dir + '/*')]
    print(file_l)
    if len(file_l) == 0:
        shutil.rmtree(dir)

[Python] 256 空のディレクトリを削除する

備忘のためメモ書き。

同じ階層にファイルがあっても削除されません。

import glob,shutil,os

dir_l = [dir for dir in glob.glob('親ディレクトリのパス/*') \
if os.path.isdir(dir)]]
print(dir_l)

for dir in dir_l:
    file_l = [file for file in glob.glob(dir + '/*')]
    print(file_l)
    if len(file_l) == 0:
        shutil.rmtree(dir)

[Python] 254 CSVファイルのリスト化

Excelで作成したCSVファイルの先頭にBOM(byte order mark)が付いていたのでこれを削除する方法も併せて以下に記します。

with open(CSVファイルのパス,encoding='utf-8-sig') as f:
    reader = csv.reader(f)
    l = [row for row in reader]

# ネストになっているため平滑化
keys = [e for ele in l for e in ele]
print(keys)

以下のコードでも可能ですが、野暮ったい感じになります。

with open(CSVファイルのパス) as f:
    reader = csv.reader(f)
    l = [row for row in reader]

keys = [e.replace('\ufeff','') for ele in l for e in ele]
print(keys)

[Python] 253 リストのCSVファイル化

ネスト(入れ子)になっていない普通のリストのCSVファイル化です。

ネストになったリストはよくCSV化していましたが、普通のリストは意外と扱っていませんでした。

writerowをwriterowsにすると、文字列が1字ずつバラバラになります。

datetime_now = datetime.datetime.now()
datetime_now_str = datetime_now.strftime('%y%m%d%H%M')
filename = f"/{datetime_now_str}_{key}.csv"

with open(filename, "w", encoding="shift_jis") as f:
    writer = csv.writer(f)
    writer.writerow(list)

ネストになったリストの場合は以下の通りです。

with open(filename, "w", encoding="shift_jis") as f:
    writer = csv.writer(f, lineterminator='\n')
    writer.writerows(list)

[Python] 252 スクレイピング イディオム集

知識の整理も兼ねてまとめてみました。

seleniumによるURL取得

from selenium import webdriver

driver = webdriver.Chrome()

driver.get("URL")

selenium ヘッドレスモード

from selenium.webdriver.chrome.options import Options

option = Options()
option.add_argument('--headless')
driver = webdriver.Chrome('/usr/local/bin/chromedriver',options=option)

selenium 要素をクリック

driver.find_element_by_xpath("XPATH").click()

selenium 要素が現れるまで30秒待機

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

WebDriverWait(driver,30).until(EC.presence_of_element_located((By.ID, "ID")))

selenium 要素がクリックできるまで30秒待機

WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.ID, "ID")))

selenium 文字列を入力

driver.find_element_by_xpath("XPATH").send_keys("STRING")

selenium 要素の文字列を取得

textA = driver.find_element_by_xpath("XPATH").text

selenium 他のタブへ移動

handle_array = driver.window_handles
driver.switch_to.window(handle_array[NUMBER])

selenium カーソルでホバリング

from selenium.webdriver.common.action_chains import ActionChains

actions = ActionChains(driver)
actions.move_to_element(driver.find_element_by_xpath("XPATH")).perform()