書籍「退屈なことはPythonにやらせよう」を教本にした「投資家のためのプログラミング勉強会(投プロ)」第5回目です。第1回〜第4回までは以下の項目を学びながら、指定した銘柄コードの関連サイトを一気に開いてくれる「一発くん」アプリを開発しました。
第1回:変数とは
第2回:文字列の結合、print()関数、input()関数
第3回:条件分岐
第4回:リスト、forループ
本日は、教本の第1部5章に沿って下記の内容を学んでいきましょう。
- 辞書型変数(キーと値をセットで管理できる変数型)
- 関数とは(組み込み関数と独自関数)
今回から「一発くん」とは別の新しいアプリを作っていきます。機能としては、自分がウォッチしたい米国株の様々な情報を自動的に収集をしてくれるアプリです。アプリ名は「アメカブくん」です(^^)
アメカブくん第一弾は、指定したティッカーに関する米国サイトのニュースを収集すると同時に翻訳してくれるアプリを作っていきます。イメージはこんな感じです。(最後のニュースが非常に気になる...)
辞書型はその名の通り、キーと対になる値を定義できる型です。
例えば「銘柄コード」と「会社名」のように値をセットで管理したいケースにはこの辞書型を使うのが常道です。
実際の記載はこのように書きます。
1 |
stock = {"8058": "三菱商事","2914": "JT","8591": "オリックス","MO": "Altria Group","PM": "Philip Morris"} |
{キー:値, キー:値 …. } というようにキーと値をコロンで対にして全体を波括弧{}で囲みます。
これで、変数stockに銘柄コードと会社名をセットにした変数のできあがりです。まさに辞書ですね。
さっそく試してみましょう。キーに対する値を得るにはget()関数を使います。
1 2 3 4 |
company = stock.get("8591")
print(company)
company = stock.get("PM")
print(company) |
いかがでしたか?キーに対する値が表示されましたか?
ちなみにキーの部分に変数stockの中に存在しないキーをいれてget()を呼び出したらどうなるでしょうか?
1 2 |
company = stock.get("TEAM")
print(company) |
さらに、stock変数の宣言時に、キーを重複して定義したらどのようになりましたか?
1 2 |
stock = {"8058": "三菱商事", "8058": "JT", "8591": "オリックス"}
print(stock) |
このように、色々と試して動きを見ながら辞書型の特徴を掴んでいきましょう。
プログラミングは書いてあることをなぞるだけではなく、手を動かして色々試してみることが理解への早道です!
プログラミングはエラーになってもパソコンが壊れるわけではないので、安心してどんどん間違えましょう。
トライアンドエラーが多いほど、つまり間違える数が多いほど学習が進んでいる証拠です。
そしてプログラミングの間違いは、一度直せば二度と同じことを繰り返しません。
当たり前ですがプログラミングは書いた通りにしか動きませんので、人間のように指示した内容と異なる動きはしません。
これは修正後の確認コストがゼロであることを意味しており、ものすごいメリットです。
もうひとつ、辞書型で使える関数keys()をみていきましょう。
keys()関数は辞書型変数のキーの全てをリスト型で返してくれる関数です。
1 2 |
stock = {"8058": "三菱商事", "8058": "JT", "8591": "オリックス"}
keys = stock.keys() |
上記は変数keys に辞書型stockに存在する全てのキーをセットしています。
変数keysはリスト型なので、全てのキーを表示するには以下のように書くのでしたね。
1 2 3 4 |
stock = {"8058": "三菱商事", "8058": "JT", "8591": "オリックス"}
keys = stock.keys()
for k in keys:
print(k) |
これがわからない場合は前回の復習をしてくださいね。教本では4.1のリストの項目を見てください。
ちなみに前回学習したリストは角カッコ[]で囲むのでした。
1 |
stock_codes = ["2914", "8058", "PM", "MO"] |
辞書型もリストと同様に複数の値をセットできますが、使い方はまったく異なりますね。
これらの違いは自分で説明できるようにしておきましょう。
また、リストは文字列だけではなく「辞書型変数」を値としてセットできますよ。
例えば、東証一部の銘柄で、金融セクター、製造セクター、サービスセクターの銘柄を定義するとこんな感じです。
1 2 3 4 |
finance = {"8591": "オリックス", "7182":"ゆうちょ", "8303": "新生"}
manufacture = {"6183": "オークマ", "6104": "東芝機械", "6135": "牧野スライス"}
service = {"2121": "ミクシー", "2181": "パーソル"}
tosho = [finance, manufacture, service] |
辞書を値にもつリスト変数 tosho を定義しました。
ではこの中身を表示してみましょう。リストの値は添字でアクセスできるのでしたね。
1 2 3 4 5 6 |
finance = {"8591": "オリックス", "7182":"ゆうちょ", "8303": "新生"}
manufacture = {"6183": "オークマ", "6104": "東芝機械", "6135": "牧野スライス"}
service = {"2121": "ミクシー", "2181": "パーソル"}
tosho = [finance, manufacture, service]
stocks = tosho[2]
print(stocks) |
辞書型変数 service の中身を表示します。さらに service のキー”2181″を指定するとそれと対になっている企業名を表示します。
1 |
print(stocks.get("2181")) |
辞書型を値としてもつリストは慣れるまで頭がこんがらがるかもしれません。今回完全に理解できなくても徐々に慣れていきましょう。
さて、ここまで学習できたところで冒頭の「アメカブ」くんを開発していきましょう。
キーボードからティッカーコードを入力すると、銘柄名で米国のGoogle Newsを検索し、関連ニュースを取得します。さらに英語を日本語に翻訳して表示するアプリです。うーん、なかなか便利そうですね。
ニュースの検索や翻訳は中級編の範囲なのでここでは詳しく説明しませんが、プログラミングでこんなこともできるんだー、と知ってもらえればOKです。
以下は私の監視銘柄の一部です。
PEP / JNJ / PG / GIS / KO / MO / PM / BUD / CL / UL / XOM / GILD / T / HRL / IBM / XOM / V / OKTA / TEAM
これらを辞書型としてリスト変数us_stocksに入れていきましょう。キーはティッカー、値は会社名です。
1 |
us_stocks = {"PEP": "PepsiCo","JNJ": "Johnson & Johnson","PG": "Procter & Gamble","GIS": "General Mills",
"KO": "The Coca-Cola Co", "MO": "Altria Group", "PM": "Philip Morris International",
"BUD": "Anheuser Busch Inbev NV", "CL": "Colgate-Palmolive Company", "UL": "UNILEVER N.V. Common Stock",
"XOM": "Exxon Mobil Corporation","GILD": "Gilead Sciences","T": "AT&T","HRL": "Hormel Foods",
"V": "Visa","OKTA": "Okta","TEAM": "Atlassian"} |
では最初に、復習を兼ねて、前回作製した「一発くん」と同様に、キーボードからティッカーを入力をして、それが上記のリストにあるかどうかをチェックするロジックを作ってみましょう。入力したティッカーがリストにあれば「有効なティッカーです」なければ「有効なティッカーを入れてください」と表示するアプリにしてみましょう。
前回はforループでリスト内の銘柄コードと比較するチェックするロジックでした。
今回はリストの中に辞書型が入っていますので、キーボードからの入力値と辞書型のキーの値を比較する必要があります。
キーの値を全て取り出すにはkeys()という関数を使うのでした。では書いてみましょう(目安時間:15分)
1 2 3 4 5 6 7 8 9 10 11 |
us_stocks = {"PEP": "PepsiCo","JNJ": "Johnson & Johnson","PG": "Procter & Gamble","GIS": "General Mills", "KO": "The Coca-Cola Co", "MO": "Altria Group", "PM": "Philip Morris International", "BUD": "Anheuser Busch Inbev NV", "CL": "Colgate-Palmolive Company", "UL": "UNILEVER N.V. Common Stock", "XOM": "Exxon Mobil Corporation","GILD": "Gilead Sciences","T": "AT&T","HRL": "Hormel Foods", "V": "Visa","OKTA": "Okta","TEAM": "Atlassian"}
print("ティッカーコードを入れて下さい")
ticker = input()
keys = us_stocks.keys()
flag = True
for k in keys:
if ticker == k:
print("有効なティッカーです")
flag = False
break
if flag:
print("有効なティッカーをいれてください") |
さてどうでしたか? keys()関数はキーのリストを返しますので、forループを使って順番にそれと比較することでチェックできますね。
実は、辞書のキーの中にある値があるかをチェックするにはもっと簡単な方法があります。
1 2 3 4 5 |
flag = ticker in us_stocks.keys()
if flag:
print("有効なティッカーです")
else:
print("有効なティッカーをいれてください") |
以上たったの5行で同じことができてしまいます。随分すっきりしました。
” 文字列 in リスト型 変数 ” とすることで文字列がリスト型変数に含まれるかをTrue or Falseで返してくれるのです。
ここでひとつ関数について第1回のおさらいを兼ねて学習しましょう。
関数とはつまり中学生で習ったf(x) = a x + bの世界です。これだけで頭がクラクラしてしまう方もいるかもしれませんが、要するにxという値を入れた結果を返してくれるファンクションが関数です。
プログラミングの世界でも同じ関数という概念があります。
そして関数はあらかじめPythonによって用意された関数(組み込み関数)とプログラミングで独自に作成した関数があります。
前者はこれまで習ったlen()関数やget()関数です。(関数については教本の3.1も参照してみてください)
本日は以下の独自関数を作成しますが、中身については中級編で解説しますので、今日は何も考えずコピペしておけば大丈夫です。
- get_stock_news() :銘柄名を入れると、それに関連する英語のニュースをリストで返す関数
- translate_en_jp() :英文を入れると、それを日本語に翻訳して返す関数
なお、この関数を使うにあたっては、下記のライブラリをインポートしておく必要もありますので合わせてやっておきましょう。
> pip install requests
> pip install beautifulsoup4
これあっさり書いてしまいましたが、インポートのやり方はそれぞれの開発環境によって異なります。当勉強会では開発環境はPyCharmというフリーソフトを推奨しています。PyCharm自体のインストール方法やライブラリのインポート方法はググると沢山出てきますのでそちらを参照してください。リアル勉強会の場では環境セットアップからサポートもしたいと考えています。
ではさっそく2つの関数を使ってみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#------- ここからコピペする ----------# import urllib import urllib.parse from bs4 import BeautifulSoup import requests from time import sleep def get_stock_news(company): ret = [] googlenews = "https://news.google.com/search?q={}&hl=en-US&gl=US&ceid=US:en".format(urllib.parse.quote(company)) print(googlenews) r = urllib.request.urlopen(googlenews) html = r.read() sp = BeautifulSoup(html, "html.parser") for tag in sp.find_all("article"): url = tag.find("a").get("href") title = tag.find("span").getText() if url is None or title is "": continue if "article" in url: ret.append(title) if len(ret) == 10: break return ret def translate_en_jp(en): sleep(1) url = "https://translate.google.com/translate_a/single" headers = { "User-Agent": "GoogleTranslate/5.9.59004 (iPhone; iOS 10.2; ja; iPhone9,1)" } params = { "client": "it", "dt": ["t", "rmt", "bd", "rms", "qca", "ss", "md", "ld", "ex"], "dj": "1", "q": en, "tl": "ja" } res = requests.get(url=url, headers=headers, params=params) res = res.json() return f'{res["sentences"][0]["trans"]}' #------- ここまでコピペする ----------# us_stocks = {"PEP": "PepsiCo","JNJ": "Johnson & Johnson","PG": "Procter & Gamble","GIS": "General Mills", "KO": "The Coca-Cola Co", "MO": "Altria Group", "PM": "Philip Morris International", "BUD": "Anheuser Busch Inbev NV", "CL": "Colgate-Palmolive Company", "UL": "UNILEVER N.V. Common Stock", "XOM": "Exxon Mobil Corporation","GILD": "Gilead Sciences","T": "AT&T","HRL": "Hormel Foods", "V": "Visa","OKTA": "Okta","TEAM": "Atlassian"}
company_name = us_stocks.get("PM") news = get_stock_news(company_name) for n in news: print(n) for n in news: trans = translate_en_jp(n) print(trans) |
どうですか?
このget_stock_news()関数はGoogle Newsにアクセスして会社名で検索したニュースをリスト型変数に入れて返してくれる関数というわけです。
もう一つの関数translate_en_jp()はどうでしょうか?
newsはリスト型変数なのでそれをforループで取り出しながらこの関数で翻訳した結果を表示しています。下記は”TEAM”とキーボードから入れた場合の表示です。
アトラシアンは今後数週間でより高く指される
これが2月に買うべき私のトップストックです
ソフトウェア会社アトラシアンがインド事業を強化したいのはなぜですか
アトラシアン:美しいビジネスだが過大評価 – アトラシアン(ナスダック:チーム)
停止し、コラボレーションし、そして耳を傾けてください:マイクロソフトチームはアトラシアンの輝きを得ます
アトラシアン、クラウドターゲティングソフトウェア、Tech Teamsに移行
Atlassian:これらのレベルではまだ高価そう – Atlassian(NASDAQ:TEAM)
アトラシアンの株価は、収益と収益の最高見通しを受けて急上昇
Atlassian Corporation Plc – Cla – Consenusは9.4%の上昇見込みを示しています
アトラシアン:史上最高値を記録したリスキー
日本語が少々怪しいですが翻訳としてなかなかではないでしょうか?この関数はget_stock_news()関数で取得したニュースをGoogleの翻訳に渡して日本語の結果を返してくれています。
それでは2つの関数の動きを理解したところで、キーボードから入力したティッカーに関連するニュースを表示するアプリを作ってみましょう。
先ほど作製したティッカーが有効かをチェックするコードに2つの関数を追加してアメカブくんを仕上げていきましょう。
- ティッカーをキーボードで入力する
- ティッカーが有効かどうかをチェックする
- ティッカーと対になっている会社名を変数companyにセットする
- 変数companyをget_stock_news()関数に入れて、リスト変数newsに返り値をセットする
- リスト変数newsをforループで取り出してtranslate_en_jp()関数で翻訳した結果を表示する
プログラムの流れとしては以上となります。それでは Let’s coding time ♬ (目安時間:20分)
(最初にget_stock_news()関数とtranslate_en_jp()関数の2つをコピペしてから上記1〜5を実装してみてください)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
#------- ここからコピペする ----------# import urllib import urllib.parse from bs4 import BeautifulSoup import requests from time import sleep def get_stock_news(company): ret = [] googlenews = "https://news.google.com/search?q={}&hl=en-US&gl=US&ceid=US:en".format(urllib.parse.quote(company)) print(googlenews) r = urllib.request.urlopen(googlenews) html = r.read() sp = BeautifulSoup(html, "html.parser") for tag in sp.find_all("article"): url = tag.find("a").get("href") title = tag.find("span").getText() if url is None or title is "": continue if "article" in url: ret.append(title) if len(ret) == 10: break return ret def translate_en_jp(en): sleep(1) url = "https://translate.google.com/translate_a/single" headers = { "User-Agent": "GoogleTranslate/5.9.59004 (iPhone; iOS 10.2; ja; iPhone9,1)" } params = { "client": "it", "dt": ["t", "rmt", "bd", "rms", "qca", "ss", "md", "ld", "ex"], "dj": "1", "q": en, "tl": "ja" } res = requests.get(url=url, headers=headers, params=params) res = res.json() return f'{res["sentences"][0]["trans"]}' #------- ここまでコピペする ----------# print("検索したいニュースのティッカーコードを入れて下さい:") ticker = input() us_stocks = {"PEP": "PepsiCo","JNJ": "Johnson & Johnson","PG": "Procter & Gamble","GIS": "General Mills", "KO": "The Coca-Cola Co", "MO": "Altria Group", "PM": "Philip Morris International", "BUD": "Anheuser Busch Inbev NV", "CL": "Colgate-Palmolive Company", "UL": "UNILEVER N.V. Common Stock", "XOM": "Exxon Mobil Corporation","GILD": "Gilead Sciences","T": "AT&T","HRL": "Hormel Foods", "V": "Visa","OKTA": "Okta","TEAM": "Atlassian"}
flag = ticker in us_stocks.keys() if flag: print("ニュースを検索しています...") company = us_stocks.get(ticker) news = get_stock_news(company) for n in news: trans = translate_en_jp(n) print(trans) else: print("有効なティッカーをいれてください") |
どうでしょうか?ちゃんと動きましたか?
ここまでできるとかなりアプリっぽいことができるようになりました。
もちろん、ご自分の監視銘柄をリストに追加すれば、どんどん拡張できます。自分が決めたキーワードを含むかどうかをチェックする機構をいれても面白いかもしれませんね。
ちなみにこのTwitter botはこのようなプログラミングを駆使して作っています。
それでは本日はこのあたりで終わります!
次回は学習内容
- whileループで対話型アプリをつくる
- ファイル操作の基礎(HTMLファイルの作製)
こちらの本を教本にした「投資家のためのプログラミング勉強会(投プロ)」を主宰しています。
そもそもプログラミングとはなんぞや、Pythonを実行させる環境をどのように用意するか、などプログラミングにおける超基本的な内容が、我々のような非ソフトウェアエンジニア向けに分かりやすく記載されています。はじめの一歩にはこれ以上ない教材です(^^)