UdemyでPythonを勉強した結果を残すブログ。

40歳でプログラミング始めて転職までいけるのかを実録してみます。

DAY36 めちゃくちゃ下げた米国の個別株の理由をニュースで知るアプリを作る!

DAY35抜かしちゃったけどAPIの呼び出しの練習なので、

DAY36に飛んで実践。

 

後日やるけど試したかったのでスクレイピングもつけています。

今回はスクレイピング部分の説明はなしでやります。

 

米国株の値動きがわかるAPIから今日と昨日の価格を取得して、

暴落していたらその理由がないかニュースAPIでニュースを検索して表示する、

というようなツールを作ります。

 

暴落しても全体の地合いで個別でニュースがない場合もありますが。。。

 

 

では始めます。

 

from get_company_name import get_company_name
import requests
#dotenv-templete
import os
import datetime as dt
from dotenv import load_dotenv
from os.path import join, dirname
load_dotenv(verbose=True)
dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)
#dotenv-templete

STOCK_NAME = input("Type Company Code eg.TSLA : ")
STOCK_API = os.getenv("STOCK_API")
STOCK_ENDPOINT = "https://www.alphavantage.co/query"
NEWS_API = os.getenv("NEWS_API")
NEWS_ENDPOINT = "https://newsapi.org/v2/everything"

today_news = dt.datetime.today()
today_news = today_news.strftime("%Y-%m-%d")

company_name = get_company_name(STOCK_NAME)
print(company_name)

 

最初の2行はAPIjsonを取得するためのrequestsと、

yahooファイナンスから英語の企業名を取得するスクレイピングの自作コードをインポートしてます。

 

次はAPI関連の情報で、STOCK_NAMEはinputで自分が気になる会社コードを

入れられるようにしています。

 

today_news部分は今日の日付を取得してNEWS APIのパラメータに合わせたフォーマットに変換しています。

 

 

APIで株価データを取得するコーディング

def get_stock_price():
params = {
"function": "TIME_SERIES_DAILY",
"symbol": STOCK_NAME,
"apikey": STOCK_API,
}
url = STOCK_ENDPOINT
r = requests.get(url, params=params)
data = r.json()["Time Series (Daily)"]
data_list = [value for (key,value) in data.items()]
today_data = float(data_list[0]["4. close"])
yesterday_data = float(data_list[1]["4. close"])

if today_data <= yesterday_data * 0.9:
print("OMG! why?")
get_stock_news()
else:
print("Keep it!")

 

url=をエンドポイントとしてリクエストし、paramsに必要事項を入力して

データをもらっています。

パラーメーターはAPIのドキュメントに書いてあります。

 

www.alphavantage.co

とりあえずrequiredだけやっとけば最低限の価格は取得できます。

取得したjsonを内包記述でリスト変換し、今日と機能の終値だけを取得します。

 

今回は今日の終値が昨日の終値より10%以上下げた時に、

ニュースを取得するという機能を実装しています。

 

ニュースを取得する機能の実装

def get_stock_news():

params = {
"q": company_name,
"from": today_news,
"apikey": NEWS_API,
"language": "en",
"searchIn": "title",
}
response = requests.get(NEWS_ENDPOINT, params=params)
response.raise_for_status()
data = response.json()
if data["articles"] == []:
print("no news...")
else:
article_source = data["articles"][0]["source"]["name"]
article_title = data["articles"][0]["title"]
article_url = data["articles"][0]["url"]
print(f"{article_source} : {article_title} - {article_url}")

get_stock_price()

 

こちらはNEWS APIを使います。

newsapi.org

 

同じようにドキュメントを見てパラメータをparamsにいれていきます。

入力例を見た方がわかりやすいかと思います。

sourcesではニュースサイトの指定もできるので、たとえばCNNだけから取得するということも可能。

 

取得がもしできなかったり空の場合は no news...と表示し、

あった場合は取得したjsonからメディア名・ニュースタイトル・リンク先を

アウトプットするようにしています。

 

 

クラッチにしてはちゃんと機能したものが作れたので気分がいいです笑

 

APIを使ったデータ解析になれてきたら、

yahooファイナンス日本株apiでfor で全部の株のデータ取得して

解析とかしてみたいな。

 

Gitはこちら。

 

github.com

 

 

pythonとphpの記述比較

pythonの基礎的な記述方法は覚えたつもりなので、

phpの方も少しさらってみると用途は違うものの少しアレンジすれば

phpもできるんじゃなかろうかと思い違いをまとめてみた。

javascriptも基本かじってきているのでそれも後日復習する予定。

 

変数の定義

python = 0
$php = 0;
PHPは最初に$をつけ、最後に";"をつける

 

記述方法

PHP<?php ?>の中に記述する

 

リストの記述

numbers = [1, 3, 5]
$numbers = array(1, 3, 5)

 

コンソールに出力する方法

print("hello")

 

phpは複数ある(めんどくさい)
echo "hello";
print_r($hello) 配列やオブジェクトの値を出力
print("hello") 1つだけ出力
var_damp($now)

 

ifの記述

if a > b or a = 4:
    b = 0
elif a < b and b = 3:
    c = 0
else:
    pass

 

<?php 
    if (a > b) || a = 4 {
        b = 0
    }
    else if (a < b) && b = 3 {
        c = 0
    }
?>
場合によってhtmlを差し込みたい場合は
<?php if (a > b): ?>
<p> 上の記述の時のみ表示する</p>
<?php else if (a < b): ?>
<p> 上の記述の時のみ表示する2</p>
<?php else: ?>
<p> 上の記述の時のみ表示する3</p>
<?php endif; ?>

 

whileの記述

a = 0
while a < 5 :
    a += 1
    print(a)

 

<?php
$a = 0;
while ($a < 5) {
    $a += 1;
    echo $a;
}
?>
phpはdo-while というwhileの使い方もある
<?php
do {
    $a = mt_rand(1,5);
    $b = mt_rand(1,5);
    $c = mt_rand(1,5);
    $abc = $a + $b + $c;
    if ($abc == 6) {
        echo "finish!\n";
        break;
    }
}
    while (TRUE);
    echo "抜け出せた3つの数字は{$a}、{$b}、{$c}";
?>

 

for文の記述

for i in range(5):
    print(f"{i}回")

 

<?php
    for ($i=1; $i< 6; $i++){
        echo "{$i}回\n";
    }
?>

 

ランダムな整数の出力方法

import random
random_num = random.randint(1, 30)
print(random_num)
hp
<?php
    $random_num = mt_rand(1, 30);
    echo $random_num
?>

 

for文の入れ子記述

 


for i in range(6):
    for j in range(6):
        print(f"{i}-{j} | ", end="")
    print("")

 

<?php
    for ($i=0; $i<=3; $i++) {
        for ($j=0; $j<=5; $j++){
            echo "{$i}-{$j}" . " | ";
        }
        echo PHP_EOL;
    }
?>

 

ユーザー定義関数

def sample(n):
    add = n * 2
    return add

print (sample(11))

 

<?php
    function sample ($n) {
        $add = $n * 2;
        return $add;
    }
    echo sample(10)
?>

 

処理の中断・break・continue

numbers = [5, 10, 15, 25, -10, 40, 5]
total = 0
total2 = 0
for i in numbers:
    if i > 0:
        total += i
    else:
        print("-があったので中断します")
        break
print(total)

 

<?php
    $numbers = array(5, 10, 15, 25, -10, 40, 5);
    $count = count($numbers);
    $total = 0;
    $total2 = 0;
    for ($i = 0; $i < $count; $i++){
        $value = $numbers[$i];
        if ($value < 0){
            echo "-がありましたが計算せず続けます\n";
            continue;
        }
        $total += $value;
    }
    echo $total;
    echo PHP_EOL;
    
    for ($i = 0; $i < $count; $i++){
        $value = $numbers[$i];
        if ($value < 0){
            echo "-があったので中断します\n";
            break;
        }
        $total2 += $value;
    }
    echo $total2;
?>

 

引数の個数を限定しない記述方法

python *argsを使う
def team(team_name, *members):
    print(team_name)
    print(members)

team("peach","angela","nick","mark")

 

php ...を使う
<?php
    function team($team_name, ...$members) {
        echo $team_name . "\n";
        print_r($members);
    }

    team("peach","angela","nick","mark")
?>

 

 

用途以外の大まかな違いは、

phpは毎回<?php ~ ?>をいれる

変数には$がつく

関数はpython = def , php = function

な感じですね。

 

pythonのコードがすっきりして書きやすいのを再確認しました。

変数とか毎回$つけんのめんどくさい…笑

 

DAY34 APIでデータを自動的に取得して毎回質問の違うクイズアプリを作る!

今回はかなり難しくてできなかったのでいい復習になった。

それぞれの機能をわけて1つのアプリとして作ります。

 

今回はDAY17でやったクイズアプリを、コンソールではなく

tkinterGUIを使ってより遊びやすくするアプリを作成します。

 

また質問もTRIVIA APIから毎回取得して

毎回違う問題を出すようにします。

 

opentdb.com

 

UIはこんな感じ。

 

 

 

APIからデータを取得するファイルを作成する

data.py

import requests

params = {
"amount": 10,
"category": 18,
"difficulty": "easy",
"type": "boolean"
}
response = requests.get("https://opentdb.com/api.php", params=params)
response.raise_for_status()
response = response.json()
quiz_list = response["results"]

今回のAPIはキーも要らず簡単なものなので、シンプルに。

requestsでapiのエンドポイントにアクセス。

raise_for_statusをすることでアクセスエラーが起きた時にどのエラーかを教えてくれるようにしています。

問題なかったらjson()でjsonフォーマットに。

quiz_listで余計な部分は飛ばして整形しています。

 

クイズ内容を質問・答えのセットとしたオブジェクトとして管理する

整形したjsonをアプリで出力しやすくするためにオブジェクト化します。

クイズモデルとして1つのクラスを作成します。

 

quiz_model.py

class Question:

def __init__(self, q_text, q_answer):
self.text = q_text
self.answer = q_answer

これはjsonの中にあるクイズ内容と答えをセットにするテンプレみたいなものを作っています。

 

main.py

from data import quiz_list
from quiz_model import Question

quiz_bank = []

for quiz in quiz_list:
q_text = quiz["question"]
q_ans = quiz["correct_answer"]
new_quiz = Question(q_text, q_ans)
quiz_bank.append(new_quiz)

quiz = QuizMachine(quiz_bank)

起動ファイルでjsonデータとモデルデータをインポートして、

for文で1つずつ質問と答えをとりだし、new_quizでオブジェクト化をして

quiz_bankのリストに入れていきます。

 

最後のQuizMachineでは整形したデータを取得して

クイズゲームを担当する機能で、次に実装していきます。

 

 

 

クイズを扱う機能のファイルを作成する

quiz_machine.py

import html


class QuizMachine:

def __init__(self, quiz_bank):
self.question_number = 0
self.score = 0
self.quiz_bank = quiz_bank
self.current_question = None

def still_has_questions(self):
return self.question_number < len(self.quiz_bank)

def next_question(self):
self.current_question = self.quiz_bank[self.question_number]
self.question_number += 1
q_text = html.unescape(self.current_question.text)
return f"Q.{self.question_number}: {q_text}"

def check_answer(self, user_answer):
correct_answer = self.current_question.answer
if user_answer.lower() == correct_answer.lower():
self.score += 1
return True
else:
return False

QuizMachineというクラスを作ります。

 

整形したデータはmain.pyでさらに出題しやすいように抽出されたデータを作るのですが、

そのデータからクイズを出す機能を作ります。

主に

  • データを取得する
  • スコアの設定
  • データがある分次々と出題する
  • 正解かを判断する

です。

上から説明すると、init部分では初期状態として、スコアと取得したデータ、今何問目かを初期化します。selfの次にquiz_bankがある通り、このクラスを使う時は()にquiz_bankを入れることで機能します。

 

still_has_questionは取得したデータの数を数えて、その分だけ数を出力するもの。

出力されなかったらクイズ終了の表示をUIのファイルがする予定。

 

next_questionでは初期値のquestion_numberのリストの内容を取得してから1を足して

質問内容を出力しています。

これをすることでリストとしては0番目の内容が見た目は1番目として見せることができます。

 

htmlをインポートしているのは、質問の中には &quot;+= 1&quot のように

ウェブサイト上で表記するための記号がある場合があります。

それをpython上でもきちんと表示されるように変換するためのファンクション = unescapeを使うためにインポートしています。

 

UIを作成する

 

design.py

 

from tkinter import *
from quiz_machine import QuizMachine

THEME_COLOR = "#efefef"


class QuizUI:

def __init__(self, quiz_brain: QuizMachine):
self.quiz = quiz_brain

self.window = Tk()
self.window.title("Quizzler")
self.window.config(padx=20, pady=20, bg=THEME_COLOR)

self.score_label = Label(text="Score: 0", fg="#333", bg=THEME_COLOR)
self.score_label.grid(row=0, column=0, columnspan=2)

self.canvas = Canvas(width=300, height=250, bg="white")
self.question_text = self.canvas.create_text(
150,
125,
width=280,
text="Some Question Text",
fill="#333",
font=("Arial", 20, "italic")
)
self.canvas.grid(row=1, column=0, columnspan=2, pady=50)

true_image = PhotoImage(file="images/maru.png")
self.true_button = Button(image=true_image, highlightthickness=0, command=self.true_pressed)
self.true_button.grid(row=2, column=0)

false_image = PhotoImage(file="images/batsu.png")
self.false_button = Button(image=false_image, highlightthickness=0, command=self.false_pressed)
self.false_button.grid(row=2, column=1)

self.get_next_question()

self.window.mainloop()

 

UIにQuizMachineをインポートすることでUIファイルでQuizMachineの機能が使えるようになります。

innitに(self, quiz_brain: QuizMachine)を入れて、

self.quiz = quiz_brainを入れることで継承ができます。

 

あとはtkinterの今まで使った機能と同じ感じ。

丸ボタンを押すとtrue_pressed、バツボタンでfalse_pressedという機能を発火します。

 

一通りのUIができたので、最後にクイズを取得する機能 = get_next_question()を入れて

innit部分は終了。

 

次に、UI上の変化として

  • クイズが残っていればクイズを表示する
  • 丸ボタンを押すとTrue、バツボタンを押すとFalseを返す
  • 答えと合っていればスコアを+1にする
  • 背景を正解の色(丸なら青、バツなら赤)に変化する。

を実装していきます。

 

design.py


def get_next_question(self):
self.canvas.config(bg="white")
if self.quiz.still_has_questions():
self.score_label.config(text=f"Score: {self.quiz.score}")
q_text = self.quiz.next_question()
self.canvas.itemconfig(self.question_text, text=q_text, fill="#333")
else:
self.score_label.config(text=f"Final Score: {self.quiz.score}")
self.canvas.itemconfig(self.question_text, text=f"Quiz is End!\nYour Score is {self.quiz.score}", fill="#333")
self.true_button.config(state="disabled")
self.false_button.config(state="disabled")

def true_pressed(self):
self.give_feedback(self.quiz.check_answer("True"))

def false_pressed(self):
is_right = self.quiz.check_answer("False")
self.give_feedback(is_right)

def give_feedback(self, is_right):
if is_right:
self.canvas.config(bg="blue")
self.canvas.itemconfig(self.question_text, fill="#fff")
else:
self.canvas.config(bg="red")
self.canvas.itemconfig(self.question_text, fill="#fff")
self.window.after(1000, self.get_next_question)

 

self.quiz.機能 は、QuizMachineに記述したdefの機能を読み込ませています。

一番最初に背景を白に設定しているのは答えを押した後に背景が青か赤になってしまっているのでそれをクリアするためです。

最初にstill_has_questionsを使うことでクイズがあるかどうかを判断しています。

そこからクイズがあればテキストをnext_question()を起動して

return として出力している Q1: クイズ のテキストをq_text の変数に格納し、

クイズ表示部分に表示をしています。

 

 

true_pressed, false_pressedはcheck_answer()を起動して

True,またはFalseを入れることで

correct_answer と同じかどうかをチェックしてあっていたらスコア+1でTrueを返す、

間違っていたらFalseを返します。

という機能にしています。

 

自分の答えが合っていると+1をしてTrueを返す quiz.check_answerですが、

Falseの時だけ is_rightという機能が付いています。

それは下のgive_feedbackの部分で正解だったら青背景、間違っていたら赤背景にするためです。

 

 

UI部分もできたのでmain.pyの最後にUIのクラスを追加して出来上がり。

 

ファイルを行き交う継承とか結構ややこしい。。。

 

Gitはこちら

github.com

sourcetree で git がプッシュできなくなってたけど解決した

udemyのレッスン途中からなぜかpushできなくなって

あきらめてsourcetree使うのやめてターミナルからやってたんだけど

 

plaza.rakuten.co.jp

 

こちらの記事を見てようやく解決した。

 

トークンをとって、gitのアドレスのhttp://の後にいれて、@をつける

そのあとに残りのgitアドレスを追加。

 

https://ghp_tokenhogehoge@github.com/user_name/リポジトリ名).git

 

な感じ。

DAY33 APIからデータをもらってISSが頭上に来た時にメールして知らせるアプリを作る!

今回のレッスンはAPIを呼び出してデータを取得し、

自分のプログラムに活用する練習としてISSが見えそうな時にメールをする簡易アプリを作成します。

 

 

このサイトの時間帯近くにメールが送られると思います。

lookup.kibo.space

 

 

ではやってみます。

このコードの流れは

  • 日の出日の入り時間をAPIで取得し、変数に入れる
  • ISSが自分の場所から見えそうな場所になるのを確認する
  • 時刻が夜かつISSが見えそうな場合にメールを送る

 

こんな感じです。

 

今回使うAPIを2つ紹介しておきます。

 

日の出日の入りのわかるAPI

sunrise-sunset.org

 

緯度と経度を

https://api.sunrise-sunset.org/json

の後ろにパラメーターで入れることで日の出日の入りをjsonで出力してくれます。

 

api.open-notify.org

 

ISS LOCATION NOWのリンクで常に今どこにいるかが緯度経度でjson出力されます。

 

 

 

まずこのサイトとかで自分の場所の緯度経度を取得します。

user.numazu-ct.ac.jp

 

今回は大阪駅を観測場所にしています。

 

準備から。

 

 

import time

import requests
import datetime
import smtplib

import os
from os.path import join, dirname
from dotenv import load_dotenv
dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)
password = os.environ.get("PASSWORD") # 環境変数
my_email = os.environ.get("MY_EMAIL")

LAT = 34.700836
LON = 135.493179
params = {
"lat": LAT,
"lon": LON
}

 

今回もセキュリティとか実務も考えて環境変数を使っています。

dotenvはターミナルでpip install python-dotenv でインストールします。

requestsはapiからデータを取得する際に使うモジュール。

 

paramsは日の出日の入りの時間をapiから取得する際にいるリストです。

ISSの緯度経度の時にも使うため固定変数として格納しています。

 

 

夜の時間に限定した機能を実装


def night_time():
now = datetime.datetime.now()
response2 = requests.get(url="https://api.sunrise-sunset.org/json", params=params).json()
sunset_hour = response2["results"]["sunset"].split(":")[0]
sunrise_hour = response2["results"]["sunrise"].split(":")[0]
if now.hour > int(sunset_hour) or now.hour < int(sunrise_hour):
return True

 

夜じゃないと見えないので、夜だけの条件をファンクションとしています。

datetimeで今の日付を取得し、apiで日の出日の入り時間を取得しています。

●時だけわかればいいので、splitで:のつくところで分けて最初の数字だけ取得します。

 

今の時間が24時間換算で日の入り時刻よりあと、日の出時刻より前であれば

1つ目の上件が当てはまる= Trueというようにしています。

 

 

ISSが見える場所ならTrueを出力する機能を実装


def iss_overhead():
response = requests.get(url="http://api.open-notify.org/iss-now.json").json()
iss_lat = float(response["iss_position"]["latitude"])
iss_lon = float(response["iss_position"]["longitude"])
if LAT - 3 <= iss_lat <= LAT + 3 and LON - 3 <= iss_lon <= LON + 3:
return True

 

apiからjsonで取得したデータを緯度と経度の変数で格納したあと、

現在地とISSの緯度経度の差異が+-3の範囲でならTrueというようにしています。

 

60秒ごとにプログラムを回して該当したらメールを送る


while True:
time.sleep(60)
if night_time() and iss_overhead():
with smtplib.SMTP("smtp.gmail.com", port=587) as connection:
connection.starttls()
connection.login(user=my_email, password=password)
connection.sendmail(
from_addr=my_email,
to_addrs=my_email,
msg=f"Subject:find ISS!\n\nLook Up!")
break

 

whileを使って、2つの条件が重なったらメールを送るようにしています。

レッスンではbreakがなかったので、breakなかったら該当の時間になったら

1分ごとにメールが送られるんじゃないか?と思ったのですがどうなんでしょう。

テストしていないのでわかりませんが…

 

一応今回はPCで起動した場合でのコーディングですが、

毎日このプログラムを起動させるのであれば前回記事に書いた

pythonanywhereに登録するとPCを起動させずともクラウド上で動いてくれます。

 

Gitはこちら。

github.com

 

 

 

 

クラウドで自動でpythonを起動してくれるサービス pythonanywhere

www.pythonanywhere.com

 

毎日自分でPCを開かなくても勝手にpythonを起動してくれるクラウドサービスです。

 

自動メール送信のレッスン時に使ったので別個で投稿。

 

今回は自動メール送信のファイルをアップロードしてみます。

go-python.hatenablog.com

 

 

 

アカウントを作って、Filesにファイルを入れて(1つずつなのが若干面倒だが)

 

consoleで.pyを起動してきちんと起動するか確認する。

 


最後にtaskで日付を設定する。


時間はUTC(世界協定時間)なので、日本だと9時間早いので

日本時間に合わせたかったらUTCの時間 +9 で設定。

 

無料分では1つしかできないので、勉強がてら練習するくらいですね。

 

環境変数も使える

consoleで環境変数を設定できます。

help.pythonanywhere.com

 

オフィシャルでの設定方法ですが、ざっくり言うとconsoleで

echo "export SECRET_KEY=sekritvalue" >> .env
echo "export OTHER_SECRET=somethingelse" >> .env

で.envにPCで設定した変数を入れ込みます。(""はいらない)

また同じくconsoleで

pip install --user python-dotenv

を入力してモジュールもインストールします。

 

あとはファイルをアップロードしたパスが違っていれば調整すれば使えます。

 

 

DAY32 csvに登録された人の誕生日の日に自動でメールを送るアプリを作る!

今回はsmtplibというモジュールを使って

python上からメールを送るレッスン。

 

pythonはライブラリのインポートが簡単で使いやすいですね。

(他の言語は知らないけども)

 

ついでに、Gitなどでアップする時に間違えて大事な情報とかもアップしないように

.envを使った環境変数を使ったコーディングもしていきます。

 

環境変数とは…

https://wa3.i-3-i.info/word11027.html

 

ここのリンクでざっくりわかりますが、さらにざっくり言うならば

python上の変数ではなく、使っているPCのos上で作られる変数。

なのでpythonファイルに直接大事な情報はコーディングしなくても動かせます。

 

 

自動メール送信アプリの流れはこちら

  • 誕生日や名前、メアドを入力したcsvをインポートする
  • 今日と誕生日を参照して、今日が誕生日の人がいたらメールを送る
  • メールは毎年同じにならないようにランダムにメールテンプレートを作る

 

smptモジュールは型を覚えるだけ

go-python.hatenablog.com

 

ちょうどこのレッスンを最初に受けた時に覚えとこうと思って書いたtips。

これは環境変数使ってない直書きなので公開の際には使えないけど。。

 

 

コーディングしていきます。

 

import smtplib
import datetime as dt
import pandas as pd
import random

import os
from os.path import join, dirname
from dotenv import load_dotenv

dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)
password = os.environ.get("PASSWORD") # 環境変数の値をAPに代入
my_email = os.environ.get("MY_EMAIL")

now = dt.datetime.now()
data = pd.read_csv("birthdays.csv")
data_dic = data.to_dict(orient="records")

 

import os〜("MY_EMAIL")のコードは先ほど言っていた環境変数を使うモジュールで、

普通環境変数を使う時はターミナルを使ってやるのだけども

検索してみたらこれが出てきたので、これならプロジェクトごとに環境変数管理しやすいし見やすいしいいじゃんと思って採用しています。

 

こちらを参考にしました。

qiita.com

 

あとは今日を取得するためにdatetime、レターのテンプレをランダムに取得するためにrandomモジュールをインポートしています。

 

pandasでcsvを整形して辞書型リストにフォーマットしています。

 

csvの入力例はこんな感じ

name,email,year,month,day
dad,dad-sample@emailadmin.com,1961,5,10

 

今日が誕生日の人を確認して該当するならメールを送る


for i in range(len(data_dic)):
if now.month == data_dic[i]["month"] and now.day == data_dic[i]["day"]:
with open(f"letter_templates/letter_{random.randint(1,3)}.txt") as mail_temp:
letter = mail_temp.read().replace("[NAME]", data_dic[i]["name"])
with smtplib.SMTP("smtp.gmail.com", port=587) as connection:
connection.starttls()
connection.login(user=my_email, password=password)
connection.sendmail(
from_addr=my_email,
to_addrs=data_dic[i]["email"],
msg=f"Subject:Happy Birthday!\n\n{letter}")
else:
print("Not birthday")

 

forでリストの中にある人を全部見ていき、

月と日が同じであればメールテンプレをランダムで取得し、

replaceで[NAME]の部分をcsvのnameに入れている名前に変更。

 

次にメールを開いて型通りに入力していきます。

smtpのサーバーは今回はgmailにしています。gmailにしている場合、port=587がないと正常に動かなかったので入れています。

 

詳しく知りたい方はこちら

qiita.com

 

誕生日が該当しない場合はNot birthdayというのを出力しますが、

特になくてもいいです。

 

 

今回はこれだけ。Gitはこちらです。

github.com