シェルスクリプトでもできなくはないですが、私の知る限りでは対話式Pythonが最速です。
カテゴリー: Python
[macOS] Pythonの開発環境構築 非pyenv
[Mac mini M1, macOS Big Sur 11.6.5]
Big SurにてPythonの開発環境を一から再構築してみました。pyenvは使わず、公式サイトからダウンロードしたPython3.10.4固定です。
ディレクトリ読み込みの優先順位は.bash_profileで設定しています。最初はpipがどこにも見当たらず少し焦りました。結局pip3をファイル名変更したシンボリックリンクとして使っています。
export PATH="/Library/Frameworks/Python.framework/Versions/3.10/bin"
export PATH=$PATH:"/usr/local/bin"
export PATH=$PATH:"/usr/bin"
export PATH=$PATH:"/bin"
# python
# /usr/local/binに3.10.4のシンボリックリンクを作成
ln -s /Library/Frameworks/Python.framework/Versions/3.10/bin/python3 /usr/local/bin/python
# pip
# /usr/local/binにpip3のシンボリックリンクを作成
ln -s /Library/Frameworks/Python.framework/Versions/3.10/bin/pip3 /usr/local/bin/pip
ファイル名を変えない場合は.bash_profileに以下の記述を追加します。
alias python="python3"
alias pip="pip3"
SIP(System Integrity Protection)を解除しても/usr/binのファイルを入れ替えることができないので、/usr/local/binに配置しました。
設定前後のpythonおよびpipファイルは以下のようになります。実効ファイルの配置ディレクトリ(色付きセル)はwhichコマンドで確認しました。
[無線] 03 PythonでADIFファイル作成 後編
[macOS Catalina 10.15.7]
前回の続きです。
eQSLサイトに移動局コールサインを登録しているかどうかを確認し、登録していなければ末尾なしのコールサインへeQSLカードを送付するようADIFファイルを書き換える、といった内容です。
VBAでも同様の作業ができるかどうか検証したいところですが、Mac版Excelではスクレイピングができないので気が向けばWindows版Excelで試してみます。
<前編からの続き>
driver = webdriver.Chrome()
window_num = 1
for i,call in enumerate(call_l):
print(call)
print(f'コールサイン文字数 {len(call)}')
if len(call) == 8:
# eQSlサイトのURLを取得
driver.get("https://www.eqsl.cc/QSLcard/Home4G.cfm")
WebDriverWait(driver,30).until(EC.presence_of_element_located((By.XPATH, "/html/body/div[2]/form[2]/font/input[2]")))
# 検索窓にコールサインを入力する
driver.find_element_by_xpath("/html/body/div[2]/form[2]/font/input[1]") \
.send_keys(call)
tm.sleep(1)
# 検索ボタンをクリックする
driver.find_element_by_xpath("/html/body/div[2]/form[2]/font/input[2]") \
.click()
# 新しいウィンドウへ遷移する
handle_array = driver.window_handles
driver.switch_to.window(handle_array[window_num])
WebDriverWait(driver,30).until(EC.element_to_be_clickable((By.XPATH, "//*[@id='CFForm_1']/input[2]")))
# 検索結果の文字列を取得する
text = driver.find_element_by_xpath("/html/body/center/h2/font").text
print(text)
# 検索結果にnotおよびyetが含まれていたらコールサインの末尾2文字を削除しADIFデータを書き換える
# 検索結果例:"JA3AAA/3 is not registered yet"
if 'not' in text and 'yet' in text:
new_str1 = data_l[i].replace('<CALL:8>','<CALL:6>')
new_str2 = new_str1[:14] + new_str1[16:]
print(new_str2)
# ADIFデータを置き換える
data_l[i] = new_str2
window_num +=1
# ブラウザを閉じる
driver.quit()
# AGIFデータを改行コードで連結する
data_l2 = '\n'.join(data_l)
# ヘッダとAGIFデータを結合する
header = '<PROGRAMID:6>HAMLOG\n<ADIF_Ver:5>3.1.0\n<EOH>\n'
final = header + data_l2
# 結合したデータをadiファイル(プレーンテキスト)に変換する
filename2 = f"/adif/{datetime_now_str}_adif.adi"
with open(filename2, "w", encoding="shift_jis") as f2:
f2.write(final)
# 前編で作成したCSVファイルを削除する
os.remove(filename)
作成されたADIFファイルの一例です。
<PROGRAMID:6>HAMLOG
<ADIF_Ver:5>3.1.0
<EOH>
<CALL:6>JA3AAA<QSO_DATE:8:D>20210602<TIME_ON:4>0611<BAND:2>2m<MODE:2>FM \
<RST_SENT:3>59+<RST_RCVD:0><QSL_SENT:1>Y<QSL_SENT_VIA:1>E<QSLMSG:6>CU 73! \
<APP_EQSL_AG:1>Y<GRIDSQUARE:4>AA00<EOR>
<CALL:6>JZ3ZZZ<QSO_DATE:8:D>20210602<TIME_ON:4>0730<BAND:4>70cm<MODE:2>FM \
<RST_SENT:3>59+<RST_RCVD:0><QSL_SENT:1>Y<QSL_SENT_VIA:1>E<QSLMSG:6>CU 73! \
<APP_EQSL_AG:1>Y<GRIDSQUARE:4>AA00<EOR>
[無線] 02 PythonでADIFファイル作成 前編
[macOS Catalina 10.15.7]
Excelの自作HAMLOGからADIFファイルを作成するPythonコードを書きました。openpyxlモジュールは使わずpandasで処理しています。
このADIFファイルをeQSLのサイトにアップロードすると自動的にeQSLカードが交信相手へ送付されます。
交信時刻は世界標準時(-9時間)に変換しています。
移動局の場合はコールサインの末尾にスラッシュとエリア番号を付記しますが、このコールサインがサイトに登録されているかどうかを検索確認して、なければ末尾なしのコールサインでeQSLカードを作成するようにしました。この内容は後編で紹介します。
チェックをつけた交信ログを抽出して一旦CSVファイルに変換していますが、データフレームのままでも可能なはずです。機会があればコードを書きます。
変数timeとtimeモジュールがダブったので、後者をtmとしました。
import pandas as pd
import csv,os
import time as tm
from datetime import datetime, timezone
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# 自作HAMLOGを読み込む
df = pd.read_excel('HAMLOG.xlsx', index_col=0)
print(df)
# ADIF列にチェックを入れている行を抽出(ADIF_BLがTRUE(=1))
df2 = df[df['ADIF_BL'] == 1]
# 抽出した行の0-7列目を取り出す
df3 = df2.iloc[:,0:7]
print(df3)
# 作成日時を付加したCSVファイル名を作成
datetime_now = datetime.now()
datetime_now_str = datetime_now.strftime('%y%m%d%H%M')
filename = f"/temp/{datetime_now_str}_adif_pre.csv"
# データフレームをCSVファイルに変換
with open(filename, mode="w", encoding="cp932", errors="ignore") as f:
df3.to_csv(f ,index=None)
# CSVファイルを読み込む
with open (filename, mode="r", encoding="shift_jis") as f:
reader = csv.reader(f)
data_l =[]
call_l = []
for i,row in enumerate(reader):
if i != 0:
# コールサイン部の作成
call = f'<CALL:{len(row[0])}>{row[0]}'
callsign = row[0]
print(callsign)
call_l.append(callsign)
# 日付と時刻の文字列を結合して日時にする
dtime = f'{row[1]} {row[2]}'
print(dtime)
# 日時の文字列を時刻に変換する
jst_time = datetime.strptime(dtime, '%Y-%m-%d %H:%M:%S')
print(jst_time)
# 時刻を世界標準時に変換し、さらに文字列に変換する
utc_time = jst_time.astimezone(timezone.utc)
utc_str = utc_time.strftime('%Y%m%d%H%M')
# 世界標準時を日付と時刻に分割し、ADIF仕様に書き換える
date = f'<QSO_DATE:8:D>{utc_str[:8]}'
time = f'<TIME_ON:4>{utc_str[8:]}'
print(date)
print(time)
# バンド部の作成
band = f'<BAND:{len(row[5])}>{row[5]}'
print(band)
# モード部の作成
mode = f'<MODE:{len(row[6])}>{row[6]}'
print(mode)
# RSTレポート部の作成
his = f'<RST_SENT:{len(row[3])}>{row[3]}'
print(his)
# その他QSL関連等の部分を作成
etc = '<RST_RCVD:0><QSL_SENT:1>Y<QSL_SENT_VIA:1>E<QSLMSG:6>CU 73! \
<APP_EQSL_AG:1>Y<GRIDSQUARE:4>PM74<EOR>'
# 全てのADIF仕様を結合する
all = call + date + time + band + mode + his + etc
# データリストに追加する
data_l.append(all)
print(data_l)
print(call_l)
<後編へ続く>