31年目のRealize

プログラミング、イラスト、家族の事を書いたりするブログにする予定

プログラミング修行中

何にしてもプログラミング

インフラからフロントエンドまで、色々できるようになりたいとは言っても、まずはプログラミングスキルが無いと転職もできない、ということで力を入れないといけない。

アウトプットしていく

年末から時間を見つけては競技プログラミングの問題を解いていました。 数をこなすのはいいけど、自分のコードを見直したり、レベル高い人のコードと比べたりして復習の時間も必要…ということでアウトプットしながら頭の中を整理していく習慣をつける!

今回のアウトプット

競技プログラミングとは別で、Udemyで購入したシリコンバレー流のpythonコードスタイルを学ぶ!という動画も視聴進めています。そちらもかなりインプットが溜まっているので、整理整理。

CSVファイルの読み込み、書き込み

よく使いそうな処理をピックアップして書いてみます。

configファイルでcsvファイルパスを指定

configparserパッケージを使ってみます。 まずは、config.iniファイルを作成。

import configparser

# ConfigParserクラスのオブジェクトを作成
config = configparser.ConfigParser()

# 辞書形式でカテゴリと各要素を指定
config['CSV_FILE'] = {
    'path': 'tmp/',
    'name': 'counter.csv',
}

# config.iniファイルを新規作成し、writeメソッドにオブジェクトを渡し書き込む
# ファイルのclose忘れを防止するため、withステートメントを使用している
with open('config.ini','w') as config_file:
    config.write(config_file)

これで出来上がったconfig.iniファイルの中身が以下。

[CSV_FILE]
path = tmp/
name = counter.csv

csvファイルの存在を確認、無ければ新規作成

CsvModelというクラスを作って、オブジェクト生成時に存在確認する。

class CsvModel():
    def __init__(self):
        self.csv_file = self.get_csv_file_path()
        
        # csvファイルが存在しなかったら新規作成
        if not os.path.exists(self.csv_file):
            pathlib.Path(self.csv_file).touch()
        
        self.header = [CSV_HEADER_NAME, CSV_HEADER_COUNT]

        # csvデータの格納領域を作っておく。
        # (keyがない場合、int型のデフォルト値(0)が設定される、defaultdictオブジェクト)
        self.data = collections.defaultdict(int)
        self.load_data()

get_csv_file_pathメソッドでは、configparserを使ってconfigファイルの内容を読み込み、csvのパスを返すようにしている。

    def get_csv_file_path(self):
        config = configparser.ConfigParser()
        config.read(CONFIG_FILE)
        return config['CSV_FILE']['path'] + config['CSV_FILE']['name']

また、load_dataメソッドでは、既にcsvファイルが存在していた場合、オブジェクト生成時にcsvの内容を読み込む。

    def load_data(self):
        with open(self.csv_file, 'r+') as csv_file:
            reader = csv.DictReader(csv_file)
            for row in reader:
                self.data[row[CSV_HEADER_NAME]] = int(row[CSV_HEADER_COUNT])
        return self.data

csvファイルにデータを書き込む

csvパッケージのDictWriterを使うと簡単!

    def save(self):
        with open(self.csv_file,'w+') as csv_file:
            # DictWriterを使うと、辞書形式でcsvファイルに書き込める
            writer = csv.DictWriter(csv_file,fieldnames=self.header)
            writer.writeheader()
            for name, count in self.data.items():
                writer.writerow({
                    CSV_HEADER_NAME: name,
                    CSV_HEADER_COUNT: count
                })

csvファイルに書き込むデータを作成

csvのカラムNAMEを指定したら、対応するCOUNTカラムの値が増えていくメソッドを作成。

    def increment(self, name):
        self.data[name] += 1
        self.save()

ではこれを使ってcsvファイルに書き込もう!

import csvmodel

csv_file = csvmodel.CsvModel()
csv_file.increment('rabbit')
csv_file.increment('cat')
csv_file.increment('dog')
csv_file.increment('rabbit')

結果は…

NAME,COUNT
rabbit,2
cat,1
dog,1

できました!

動画の演習内容をもとに自分なりにカスタマイズしたけど、色々と歪な設計になってしまったような気がするorz

オブジェクト指向的なコーディングも鍛えなきゃ…。

一応、読み込みも確認のため、別のオブジェクト生成してみる。

csv_file2 = csvmodel.CsvModel()
csv_file2.increment('rabbit')
csv_file2.increment('cat')
csv_file2.increment('rabbit')
csv_file2.increment('rabbit')

NAME,COUNT
rabbit,5
cat,2
dog,1

あってます。

家族が増えました

全然関係ないですが、癒しのため。

新たな危機感

再起動中…

4ヶ月振りに更新です。 なんとなくモチベ下がってからそのままゲームにハマり、仕事も忙しくなり、なんとなく充実して危機感も薄れてしまったのかなーと分析…。

9月の成果物です

英雄伝説 閃の軌跡Ⅳより

そしてゲームクリアに60時間。

ゲーム楽しいけど時間が吸い取られます…。

目標を再設定

いつか仕事で使えるよう、プログラミングのスキルアップを目指し勉強してきたけど、自分と会社の方針のギャップが広がっているのを感じた11月末。

この会社ではエンジニアとしての仕事は出来ない!と判断し、次のキャリアに向けて どこに行っても戦えるようなスキルを身につける!というのが新たな目標です。

身につけたいスキル

フロントエンドからバックエンド、インフラ周りも触れるのが理想。 (フルスタックエンジニアと言うらしい)

vue.js

javascriptフレームワーク。最近のトレンドらしく、フロントエンジニアの求人を見ているとよく見かけるので、抑えておきたいなと思っています。Djangoはどうなんだろう…正直javascriptフレームワークの違いが良く分からないので、そこも勉強!

ここで勉強中。

https://www.udemy.com/learn-vuejs/

python

バックエンドのロジックは書けるようになっておきたい。Javaは実戦経験無いけどそれなりにできる(ハズ)なので、pythonを継続で。 ロジックの修行として競技プログラミングを勧められたので、↓のサイトでちまちまやってます。

AtCoder

上位プログラマーのコード見てると心が折れそうなほど理解できない…。

Docker + Kubernetes

仮想マシンとは違う、一つのマシン上にアプリ+インフラを仮想的な領域(コンテナ)で 実行することができる技術を便利に活用できるアプリケーションたち。 まだまだこいつが何者なのかは理解できてません。 ↓の書籍で勉強中。

Docker/Kubernetes 実践コンテナ開発入門

AmazonWebService

有名なクラウドサービスはいくつかありますが、ここに勝てるものはもういないのでは…。 簡単に仮想マシンやネットワーク、DBも1人で構築出来てしまう。 インフラでは必須のスキルだと思ってます。

動画見ながら、一年間の無料枠+一部有料機能使って勉強中。

https://www.udemy.com/aws-14days/learn/v4/content

3月末までにやること

インフラからフロントエンドまで、一通り作ってみようと思います。

…さすがに独学で一人だと厳しいので会社の先輩に協力もらいながら 何か便利なWebサービスを作って、公開、運用するのが目標です!

それを武器に、次のステップに進みたい。

リフレッシュからの復帰待ち

お盆休みで頭真っ白

先週は仕事も休みで、帰省などなどしていました。お勉強のモチベが戻るまでちょっと時間かかりそうですね。

どうやったら戻って来るのか?( ̄◇ ̄;)

いい感じの一枚

旅立ちの予感…!

時間があったので羽田空港国際線ターミナルの展望デッキに行きました。 美味しそうなご飯屋がたくさんあり、こっちで食べれば良かったと後悔。

血小板ちゃん

はたらく細胞より

赤血球や白血球など、細胞を擬人化した漫画のアニメ化。人間の身体の中で起こっていることが分かりやすく表現されている。

久々にイラストも描きました。 面白いのでオススメです。がん研究者もその表現の正確さを絶賛しているとかなんとか。

魚と格闘

妻が最近できた業務スーパーから送ってきた写真

三枚おろしに挑戦しようと思い、購入を依頼したところ、思ったより大きくてビックリ。

かなり苦戦したらしい。まさかこんなに大きいとは思わず…。

結構な大きさだったので、以前からやりたかった、一尾丸ごと使ってフルコースを実践!

妻と協力し、刺身、アラ汁、塩焼きを作成!

娘も塩焼きを美味しいと言っていたので大満足でした。

シメは漬け丼。

まとめ

次やるときまでに出刃包丁と刺身包丁を買おうと心に決めた、そんな休暇でした。

スクレイピングに挑戦

アウトプットが渋滞中

週一回の更新を目標にしていましたが、追い付かなくなってきました。

仕事の方も新しい試み(自分の中で)をやっていて、そちらも覚えるものが多く大変…。スクラム継続的インテグレーション(CI)などなど。

ただ、今までの仕事の仕方に比べると楽しいので苦ではないですけどね。仕事を楽しいと思う日が来るとは…!

自己学習では、自分が使いたいアプリを作るために必要なスクレイピングという技術について勉強中。 その経過について書きながら、頭の中を整理したい。

スクレイピングとは

WebページのHTML構造を解析し、任意の情報を抽出する技術です。 まず第一の目標として、市の施設予約システムからテニスコートの空き情報を取得するところまで作っていこうと思います。

そこで、pythonを使ったスクレイピングに使えるライブラリは次の2つ

urllib

URLを扱うライブラリ。 主に、URLを指定してリクエストを送信し、レスポンス情報を取得します。 その情報から、HTMLの要素を取り出したりするのに使います。 ただ、urllibよりはrequestsというライブラリの方がより高水準で使いやすく、お奨めらしい。

Beautiful Soup

面白い名前のライブラリ。「ふしぎの国のアリス」の中で出てくる詩が由来らしい。今度調べてみよう…。 HTMLを渡すと解析してくれます。

とりあえずやってみる

まずは小手調べに、自分が利用しているシステムのトップページのURLを指定して「title」要素を抽出してみる。

from bs4 import BeautifulSoup
import urllib.request as req

# URLを指定(一応マスキング)
url = "https://xxxxxxxxxxxxxxxxx"
# URLを開き、レスポンスを取得
res = req.urlopen(url)
# レスポンス情報からHTMLを解析
soup = BeautifulSoup(res, "html.parser")
# "title"要素を抽出
title = soup.select_one("title").string
print("title = ", title)

結果は↓

title =  施設予約システム

こうでました! あとは、select_one("title")で引数として渡している「title」の部分を他の要素で指定してあげれば割とすぐできるのでは?

…この結果を得られた時はそう思っていました…。

JavaScriptの壁

抽出したい対象の要素を知るために、ターゲットとなるシステムのHTML構造を見てみます。

f:id:altrlz:20180814001116p:plain

さっきは「施設予約システム」が抽出されたので、上の「title」が取れていたようです。 frame内の「title」を取るには、frame要素のsrc属性に指定してあるURIをくっつけたら良い…?

title =  表示できません

うーむ、URLをブラウザで直打ちするとタイトルが「処理選択」になるから、title要素もそうなってるハズなのに違う文字列が抽出されるのは何故だ…。

Beautifulsoupで解析した結果を以下のコードで表示して、HTML構造がどうなっているか見てみよう。

print(soup.prettify())

その結果を抜粋

<html>
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
  <meta content="no-cache" http-equiv="Cache-Control"/>
  <meta content="0" http-equiv="Expires"/>
  <meta content="ja" http-equiv="Content-Language"/>
  <title>
   表示できません
  </title>
  <link href="../style/yoyacky_1_3.css" rel="stylesheet" type="text/css"/>
  <script language="javascript">
   function Window_OnUnload(){
}
  </script>
 </head>
 <body bgcolor="#FFCC99" link="#000000" onunload="Window_OnUnload()" text="#000000" vlink="#000000">
 </body>
</html>
<!--<font style="font-size:13pt;">-->
<font class="SerchMiddleBold_font">
 接続が制限時間切れです。
 <br/>
 ブラウザを閉じて処理をやり直してください。
 <br/>
 <br/>
 閉じるボタンが使用できない場合は、
 <br/>
 ブラウザの閉じるボタンを使用して画面を閉じてください。
 <br/>
 <input alt="この画面を閉じる" name="btn_close" onclick="window.top.close();return false;" src="../image/window_close.jpg" type="image" value="閉じる"/>
</font>

表示できなかったパターンのHTMLが返ってきている。 body要素の属性にonloadでJavaScript指定してたりするから、画面操作しないとダメなんだろうか…。

JavaScriptも慣れてないから時間かけないとと厳しいなぁ。

次のアプローチ

このような場合のアプローチとして、Webブラウザ経由でのスクレイピング方法もあります。 そこで使えるのが、Webブラウザを自動操作させるSeleniumと、画面無しでコマンドラインから利用できるWebブラウザのPhantomJS

Seleniumは今仕事でも使おうとしているし、一石二鳥! という訳でまたインプットのお時間が始まります。先は長そうだ。

RedisとBootstrapとGitHub

役立つオープンソースソフトウェアたち

Djangoフレームワークを使ってWebアプリを作ってきましたが、これで捗るのはWebアプリの基本的な部分のみ。ただそれだけでも自分がコーディングする量は大幅に少なくなり大助かりですが!

今回のアプリでは、その他にもRedisを使ってデータを保存したり、Bootstrapを使ってページのデザインを綺麗にしたりと…世の中にはこんなに便利なソフトウェアやフレームワークがあったのかとビックリ。

プログラミングを勉強する!と言いながら始めましたが、実際、基本的な文法や標準ライブラリの使い方を覚えた後、こういったものを使い始めてからが本番なんだなーと感じているところです。

今回使った便利なツールたち

ライブラリやフレームワークOSSオープンソースソフトウェア)やWebサービスなどなど色々な言葉はありますが、ひっくるめてツールと呼ぶことにします。ちょっと脳のメモリが不足気味…。

Redis

インメモリDBという種類のデータベースで、メモリ上にデータを格納するためRDBよりも高速にアクセス可能。永続性もあるらしい。 キー・バリュー型で、キー(key)を指定してバリュー(value)を取り出すシンプルな構造。

↓のように、手札の情報や所持金、ベット額を保存するのに使っています。 f:id:altrlz:20180729233513p:plain

Bootstrap

Twitter社が開発した、CSSデザインのフレームワークらしい。 CSSのクラスが準備されていて、HTMLファイル内でクラスを指定すると、自分でCSSをコーディングすることなく見栄えがいい画面を作ることが可能!

↑に貼った質素な画面が、少しのコーディングで↓のようになります!これはすごい。(カードは画像ファイルです)

f:id:altrlz:20180730234735p:plain

GitHubとGist

GitHub

GitHubは開発者向けのWebサービスで、無償でソースコードを格納するリポジトリを作成し、公開できるものです。OSSもこのサービス上にリポジトリが公開されていて、世界中の開発者達が一緒に開発したりできるという素晴らしいサービス。開発者達のSNSという表現をよく聞きます。

僕もアカウントを作ってみました。 メニューが全部英語なので、慣れるまで時間かかりそう…。

github.com

Gist

GitHubのサービスの一つで、ソースコードを1ファイル単位で管理できる。

これが地味に役に立ちました。

今回、ブラックジャックのアプリ部分はiOSpythonistaというアプリでコーディングしていて、WebアプリはPCで仮想OS上のエディタでコーディングしていました。

Pythonista 3

Pythonista 3

  • omz:software
  • 仕事効率化
  • ¥1,200

そこで、iphone→PC間のソースの受け渡しがめんどくさいなーと思ってpythonistaをポチポチしていたところ、GitHubのキャラクターっぽいシルエットを発見!

そこからGistにアップロードして、仮想OSからgit cloneしてソースをゲットするという技を身に付けることができました! (↓のリンクから見れます)

main.py · GitHub

広がっていく風呂敷

pythonでアプリを作る、というところから様々なツールを知ることができましたが、まだまだ使えるとは言えないレベル。自分が使いたいアプリを作る段階で、こういうツールを選定し、実装していくことで自分のものにしていきたい!と思った1週間でした。

Web画面の作り方

フレームワークの流れ

覚えたこと。 DjangoでのWebアプリ画面の作り方。

  1. templatesディレクトリ配下にWeb画面の基礎部分となるhtmlファイルを作成する。

  2. htmlファイルに対するhttpリクエストの対応をview.pyに記述する。

  3. 対象のhtmlファイルが呼ばれる際のURLパターンをurls.pyに記述する。

htmlファイル

記述としては↓のような感じ。(body部を抜粋)

<body>
  <form action="" method="POST" >
    {% csrf_token %}
    <p>記号<br>
      <select name="suit">
    <option value="H">Heart</option>
    <option value="D">Dia</option>
    <option value="S">Spade</option>
    <option value="H">Clov</option>
      </select>
    </p>
    <p>数字<br>
    <select name="rank">
      {% for i in rank_list %}
      <option value={{i}}>{{i}}</option>
      {% endfor %}
    </select>
    </p>
    <p>
      <input type="submit" value="送信">
    </p>
  </form>

画面はこうなる。

f:id:altrlz:20180722232058p:plain

通常のhtmlの記述に加えて、{% %}で囲まれた部分にDjangoが用意したpythonっぽいロジックを記述できたり、view.pyとの変数のやり取りができたりします。

なお、templatesディレクトリ自体をDjangoが認識するために、setting.pyに今回作成したアプリの情報を記載する必要がある。

INSTALLED_APPS = [
    'firstApp', #←これ#
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

view.py

記述はこんな感じ。

def form_card(request):
        if request.method =='GET':
                rank_list=[]
                for i in range(1,14):
                        rank_list.append(str(i))
                dictionary = {'rank_list':rank_list}

                dictionary.update(csrf(request))
                return render(request, 'select_card.html', dictionary)
        
        if request.method == 'POST':
                suit = request.POST['suit']
                rank = request.POST['rank'].zfill(2)
                dictionary = {'suit':suit, 'rank':rank}
                print(suit,rank)
                return render(request, 'display_card2.html', dictionary)

form_card関数が呼ばれたら、この処理が動く。 最終的にはrender関数で遷移先のhtmlファイルを決定し、dictionaryの部分にhtml内で使用する変数などなどを格納して受け渡しする。

ちなみに、dictionary.update(csrf(request))Djangoが用意してくれているセキュリティ対策で、CSRFクロスサイトリクエストフォージェリ)という攻撃を防ぐ機能を準備してくれている!

フレームワークって…いいね…。

urls.py

正規表現を使って、URLのパターンと、呼び出す関数の紐づけを行う。

urlpatterns = [
    url(r'^form_card/$',views.form_card),
]

ここで記述する関数名と、view.pyに定義した関数名が違って何度もDjango先生に怒られました…。そして削られていく時間。

ちなみに送信ボタン押すと

対応するトランプのカードが表示されます。

f:id:altrlz:20180722234236p:plain

画面作成の基本的な流れはこんなところですかね。 次はDjangoでデータを保管したりする動作を覚えて、最後にブラックジャックを動かす!

…もうちょっと進めるペース上げたいけど、8月、9月は誘惑が多くて更に時間が削られることが想定されます。

  • 8月~9月末までの誘惑

www.fantasylife.jp

  • 9月末~の誘惑

www.falcom.co.jp

これらの壁をどう乗り切って行くかが鍵。 目標を見失わないようにせねば。

Djangoに触れてみる

再スタート

ひとまず心のモヤモヤも晴れ、やっと本筋に戻ることができました。心なしか、以前よりテキスト読みやすくなった気がします。

たぶん気のせい。

仮想OS上でWebサーバを動かす

閑話休題(使ってみたかっただけ)

3週間も経ってどこまでやったかあやふやですが、確かWin10のPC上の仮想マシンにCentOS7をインストールするところまでやっていました。

Webサーバソフトをインストール

CentOSにWebサーバ機能を持たせます。 Webサーバといえば、apacheが有名で、今読んでいるテキストもそれを導入しています。

しかし最近はnginx(エンジンエックス)というソフトが普及してきているらしく、今後主流になりそうなので、こちらを入れてみました。

apacheには「C10k問題」という、1つのWebサーバにクライアントが1万台接続すると、動作が重くなってしまう問題があります。

その点nginxは軽量でかつ1つのプロセスで複数のリクエストを処理する「イベント駆動モデル」であり、クライアント台数が1万台を超えても余裕で動く。

…という特徴があるので、ユーザ数が多いWebシステムにおいて利点があります。

そんなでかいシステム作れませんが、流行りに乗っておきたい。

インストール自体は簡単で、CentOSに含まれているyumコマンドで一発!

  1. rootユーザで、/etc/yum.repos.d/nginx.repoファイルを作成し、以下の内容で保存。これで、yumコマンドで参照するリポジトリが追加される。

    [nginx]

    name=nginx repo

    baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/

    gpgcheck=0

    enabled=1

  2. そして、yum install nginxコマンドを実行!終わり!
  3. 一応、バージョン確認コマンドnginx -vで、インストール成功しているのを確認。

やっとDjango

やっとDjango(ジャンゴ)に戻ってきました。 Webサーバの準備はできたので、そこに乗せるWebアプリを作っていきます。

pythonをインストールした際についでに入っているpipツールでDjanoをインストールできました。yumpython版ってところですかね?

プロジェクト作成

ここから、Webアプリ開発に便利なフレームワークを使っていきます。

django-admin startproject プロジェクト名のコマンドでプロジェクト用ディレクトリが作成され、その中に部品達が生成されます。 中でもmanage.pyというpythonファイルの部品が、アプリを作るための各種雛形ファイルを作ってくれたり、開発用の簡易サーバを起動したりしてくれるみたいです。

  • python manage.py runserverでサーバ起動。(ポートは8000番)
  • python manage.py startapp アプリ名でアプリ用雛形作成。

Webアプリ用の雛形ファイル

主要なものをメモメモ。

view.py

画面に何を表示させるか、どんな処理をするかを記述する。

apps.py

アプリケーションの設定を記述する。

models.py

データベース関係のファイル。

admin.py

管理画面の設定を記述する。

urls.py(これは自作)

URLと、呼び出される処理の関係を記述する。

今週はこんなところ。

今後の予定

今読んでいる本をマスターするまでは、と思っていましたが衝動買いしてしまった。

以前の投稿で書いた、直近で欲しいアプリを作るための技術「スクレイピング」(Webサイトのデータを取得するもの)について記述があったのでつい…。

altrlz.hateblo.jp

積み本が増えないように早く進めなければ…。