ローイングファンのプログラミング日記

ボート競技やプログラミングについて書きます

Ubuntu18.04にPostgreSQL10.5をインストール

2020-11-07追記
WSL2 Ubuntu20.04にPostgreSQL13をインストールしたので記事を投稿した
WSL2上のUbuntu20.04にPostgreSQL13をインストール - ローイングファンのプログラミング日記
(追記終わり)

目次


はじめに

前につくったUbuntu環境にPostgreSQLをインストールした。
参考にしたページは次のとおり。
今回の環境に応じてそれぞれをアレンジしてインストールおよび設定をした。

インストールする際に参考にしたページ

PostgreSQL Home > Download > Linux Ubuntu
LINUX DOWNLOADS (UBUNTU)
https://www.postgresql.org/download/linux/ubuntu/

PostgreSQL Wiki
Apt
https://wiki.postgresql.org/wiki/Apt

WEB ARCH LABO
PostgreSQL 10 を Ubuntu 16.04 LTS にインストールする手順
https://weblabo.oscasierra.net/postgresql10-ubuntu1604-install/

設定の際に参考にしたページ

CentOS7.3にPostgreSQL9.6.3をインストールしてみた
https://qiita.com/uhooi/items/44ed9370740c7521dce4

PostgreSQLリポジトリを追加

PostgreSQLリポジトリを追加する。

$ sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'


信頼キーの取得と追加。

$ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -


Aptの更新とシステムのアップグレードをする。

$ sudo apt update
$ sudo apt upgrade


PostgreSQL10のインストール

PostgreSQL10とpgadmin4をインストールする。

$ sudo apt -y install postgresql-10 pgadmin4


自動起動の設定をする。

$ sudo systemctl enable postgresql


インストールできたか確認する。

$ psql --version

psql (PostgreSQL) 10.5 (Ubuntu 10.5-1.pgdg18.04+1)


成功。

ロール設定

このままだとデフォルトで用意されているpostgresユーザーでしか操作できない。
vagrantユーザーのロールをつくってvagrantユーザーでも操作できるようにする。
*この辺はよく理解できていない。要勉強。

PostgreSQLサーバーを起動してpsqlコマンドを試す。

$ sudo systemctl start postgresql
$ psql -l

psql: FATAL: role "vagrant" does not exist


やはりvagrantユーザーでは操作できない。

ロールをつくっていく。
まずpostgresユーザーでログインする。

$ sudo -u postgres psql

psql (10.5 (Ubuntu 10.5-1.pgdg18.04+1))
Type "help" for help.
postgres=#


ロールをつくる。

postgres=# create role vagrant with login createdb;

CREATE ROLE


postgresユーザーのパスワードを変更する。

postgres=# alter user postgres password 'postgres';

ALTER ROLE


ログアウトしてvagrantユーザーからpsqlコマンドがつかえるか試す。

postgres=# \q
$ psql -l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(3 rows)


操作できた。

サーバーを停止する。

$ sudo systemctl stop postgresql


今回の環境

ホストOS
macOS 10.13.6
Windows10

ゲストOS
Ubuntu18.04

Ubuntu18.04にRuby2.5.1をインストール``

前回つくったUbuntu環境にRuby2.5.1をインストールした。
参考にしたのは@nyanyamoさんの記事。

centOS7にrbenvとruby2.5.1いれたよ
https://qiita.com/nyanyamo/items/952823ca044859232d82

目次


Gitの確認

今回の環境ではすでにGitがインストール済だった。

git --version

git version 2.17.1


なのでこのまま使用。

rbenvのインストール

rbenvをGitHubからインストールする。

git clone https://github.com/sstephenson/rbenv.git ~/.rbenv


パスを通す

.bash_profileをつくって次の2行を書き込む。

echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile


書き込んだらターミナル/Puttyを再起動するか次のコマンドで設定を有効にする。

source ~/.bash_profile


ruby-buildのインストール

ruby-buildをGitHubからインストールする。

git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
sudo ~/.rbenv/plugins/ruby-build/install.sh


その他必要なシステムのインストール

その他必要なシステムをインストールする。
今回の環境だとbzip2gccの2つで大丈夫だった。

sudo apt install bzip2 gcc


Rubyのインストール

準備ができたのでRubyをインストールする。
今回はRuby2.5.1をインストールした。

rbenv install 2.5.1
rbenv global 2.5.1


バージョン確認。

ruby -v

ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]


インストール成功。

Rubyのバージョンアップ

あらたに新しいバージョンのRubyをインストールする場合はrbenvとruby-buildをアップデートする。

rbenvのアップデート
cdコマンドで移動

cd ~/.rbenv


gitで最新版をpull

git pull


ruby-buildのアップデート

cdコマンドで移動

cd ~/.rbenv/plugins/ruby-build


gitでpull

git pull


インストールできるバージョンの確認

rbenv install -l


インストール

rbenv install 2.5.3


バージョン切り替え

rbenv global 2.5.3


確認

ruby -v


ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]



次回はPostgreSQL10をインストールする。

今回の環境

ホストOS
macOS 10.13.6
Windows10

ゲストOS
Ubuntu18.04

macOS10とWindows10にUbuntu18環境をつくった

この前はCentOS環境をつくったので今回はUbuntu18.04環境をつくった。
Ubuntu環境をつくった理由はHerokuがUbuntuをつかっているから。

Heroku Stacks
https://devcenter.heroku.com/articles/stack

目次


事前準備

環境をつくるには次のソフトが必要。

今回はMyUbuntu18というディレクトリをつくり、その中に環境をつくった。

環境構築の概略

概略は次のとおり。

Boxを選ぶ

今回はVagrantのWebサイトで推薦しているBento boxesの中からbento/ubuntu-18.04を使った。

Vagrant
https://www.vagrantup.com/

Top > Docs > Boxes #Official Boxes
recommend Bento boxes
bento/ubuntu-18.04

環境の初期化とBoxの設定

まずディレクトリに移動する。

cd MyUbuntu18


bento/ubuntu-18.04の説明のNewタブにあるコードを使って初期化する。

vagrant init bento/ubuntu-18.04


ディレクトリの中にVagrantfileがつくられるので、これを書きかえる。
ipアドレスが書かれた行のコメントマークを削除してコードを有効にする。
必要に応じてipアドレスを変更する。

修正前

# config.vm.network "private_network", ip: "192.168.33.10"


修正後
**は任意に設定

config.vm.network "private_network", ip: "192.168.33.**"


Vagrantfileを書きかえたらVagrantを起動する。
そうするとBoxの設定がはじまりUbuntu環境ができあがる。

vagrant up


Boxの設定が終わったらPuttyをつかって仮想環境に接続する。
(Macターミナルの場合はそのままvagrant sshコマンドで接続できる。)
Puttyを立ち上げ、初期画面でアカウント名vagrantを入力。
パスワードを求められるので同じくvagrantと入力。
これでvagrantユーザーでログインできる。

最初のログイン時にシステムのアップデートをしておく。
UbuntuのパッケージシステムはAPT。
まずaptをアップデートする。

sudo apt update


次にaptで管理されているシステムをアップグレードする。

sudo apt upgrade


これでもろもろがupgradeされる。


次回はRuby2.5.1のインストールについて。

今回の環境

ホストOS
macOS 10.13.6
Windows10

ゲストOS
Ubuntu18.04

CentOS7にPostgreSQL10をインストール

CentOS7.5にPostgreSQL10.4をインストールした。

目次


インストール

インストールはPostgreSQLのWebサイトにしたがっておこなった。

PostgreSQL Top
https://www.postgresql.org/

TopページにあるDownloadリンクをクリック。
Red Hat family Linuxの中にあるCentOSをクリックするとインストールの解説ページに移る。

https://www.postgresql.org/download/linux/redhat/

解説ページで環境を選択していく。
今回選択した環境は次のとおり。
PostgreSQLのversionは10を選択。
platformはCentOS 7を選択。
architectureはx86_64を選択。
環境を選択すると環境にあったコマンドが表示されるのでそのとおりに実行していく。

f:id:rowingfan:20180730115137p:plain

インストールの概略は次のとおり。

  • PostgreSQL Yum Repositoryをインストール
  • RepositoryからPostgreSQLをインストール
  • postgres serverをインストール
  • データベースを初期化する
  • 起動設定をする


実際にインストールする。
MacPCはターミナル、WindowsPCはPuttyから操作した。
インストール中に確認がある場合はy(Yes)と答えて続行する。

The PostgreSQL Yum Repositoryをインストール

[vagrant@localhost ~]$ sudo yum install https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm


The PostgreSQL Yum RepositoryからPostgreSQLをインストール

[vagrant@localhost ~]$ sudo yum install postgresql10


serverをインストール

[vagrant@localhost ~]$ sudo yum install postgresql10-server


initializeする

[vagrant@localhost ~]$ sudo /usr/pgsql-10/bin/postgresql-10-setup initdb


サーバ起動時に自動でPostgreSQLも起動する設定をする
パスワードをきかれたらVagrantのパスワードを入力

[vagrant@localhost ~]$ systemctl enable postgresql-10


PostgreSQLを起動する

インストールが成功したら実際に使ってみる。
起動と停止のやりかたは次のページを参考にしました。

WEB ARCH LABO
PostgreSQL 10 を CentOS 7 に yum インストールする手順
https://weblabo.oscasierra.net/postgresql10-centos7-install/

起動
パスワードをきかれたらVagrantのパスワードを入力する。

[vagrant@localhost ~]$ systemctl start postgresql-10


起動したらデフォルトで用意されているpostgresデータベースにログインする。

[vagrant@localhost ~]$ sudo -u postgres psql -U postgres


ログインできると次の表示が出る。

psql (10.4)
Type "help" for help.
postgres=#


操作してみる。
データベース一覧を表示

postgres=# \l


                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(3 rows)

表示できた。

データベースからログアウトする。

postgres=# \q


ロールの作成

初期設定のままだとvagrantユーザーでpsqlコマンドが使えない。
試してみる。

[vagrant@localhost ~]$ psql -l


vagrantロールがないというエラー表示が返ってくる。

psql: FATAL:  role "vagrant" does not exist


vagrantユーザーからcreatedbもできない。

[vagrant@localhost ~]$ createdb test


同じくエラー表示

createdb: could not connect to database template1: FATAL:  role "vagrant" does not exist


vagrantユーザーで操作できるように設定する。
設定に際し次のページを参考にしました。

macVagrant + VirtualBox + UbuntuでPhoenixFrameworkの開発環境を整えてみた
https://qiita.com/matken11235/items/78edd09fa421b6da4e38

PostgreSQL
Top > Documentation > Manuals > PostgreSQL 10 CREATE ROLE SQL Commands
https://www.postgresql.org/docs/10/static/sql-createrole.html

PostgreSQL 10.4文書
パート3 サーバの管理
第21章 データベースロール
https://www.postgresql.jp/document/10/html/user-manag.html

まずpostgresユーザーでpostgresデータベースにログインする。

[vagrant@localhost ~]$ sudo -u postgres psql -U postgres


vagrantロールをつくる。

postgres=# create role vagrant with login createdb;


成功すると次の表示が返ってくる。

CREATE ROLE


postgresユーザーのパスワードを変更したほうが良いそうなので変更する。

postgres=# alter user postgres password 'postgres';


成功すると返答がある。

ALTER ROLE


ロールができたらvagrantユーザーから操作できるか試す。
一旦postgresデータベースからログアウト。

postgres=# \q


vagrantユーザーからpsqlコマンドを試す。
データベースの一覧表を表示する。

[vagrant@localhost ~]$ psql -l


                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
(3 rows)


一覧表が返ってきた。
設定がうまくいったようなのでデータベースをつくる。

[vagrant@localhost ~]$ createdb test


何も返ってこないので確認してみる。

[vagrant@localhost ~]$ psql -l


                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 test      | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
(4 rows)


成功していた。
今度はテーブルをつくる。
まずtestデータベースにログイン。

[vagrant@localhost ~]$ psql test


表示が次のようになる。

psql (10.4)
Type "help" for help.

test=>


テーブル作成。

test=> create table tests (crewname varchar(30));


返答がある。

CREATE TABLE


確認してみる。

test=> \dt


         List of relations
 Schema |  Name  | Type  |  Owner
--------+--------+-------+---------
 public | tests | table | vagrant
(1 row)

テーブル作成も成功。

ログアウトする。

test=> \q


停止

PostreSQLを停止。
パスワードをきかれたらVagrantのパスワードを入力

[vagrant@localhost ~]$ systemctl stop postgresql-10


感想

環境によって扱い方の違いがあるので難しい。
知識が浅いのが原因。
OSやPostgreSQLのユーザーの意味がわかっていない。
PostgreSQLのroleがわかっていない。
少しずつでも理解していきたい。

今回の環境

CentOS 7.5
(ホストOS: Windows10, macOS 10.13.5)
Vagrant 2.1.2
PostgreSQL 10.4

WindowsPCに仮想環境をつくった

WindowsPCにCentOS環境をつくった。
ホストOSはWindows10
ゲストOSはCentOS6.8とCentOS7.5

目次


参考にした情報

仮想環境を構築するためにドットインストールのレッスンを参考にした。

ドットインストール/Vagrant入門
https://dotinstall.com/lessons/basic_vagrant

ドットインストール/ローカル開発環境の構築[Windows編]
https://dotinstall.com/lessons/basic_localdev_win_v2

ドットインストール/ローカル開発環境の構築[macOS編]
https://dotinstall.com/lessons/basic_localdev_mac_v2

レッスンに従うだけであっさり構築できた。

CentOS7のインストール

ドットインストールのレッスンではOSがCentOS6.8と少し古かった。そこでCentOS7環境を追加してみた。

まずPowerShellから操作。
仮想環境用のディレクトリを作成してそこへ移動

>mkdir CentOS7
>cd CentOS7


BoxはVagrantのWebサイトで勧めているbentoを選択。

Vagrant
https://www.vagrantup.com/

Vagrant Top > Docs > Boxes とページを進むとOfficial Boxesの中でBento boxesが勧められている。

For other users, we recommend the Bento boxes. The Bento boxes are open source and built for a number of providers including VMware, Virtualbox, and Parallels. There are a variety of operating systems and versions available.


リンク先にある一覧からbento/centos-7.5を選択。
bento/centos-7.5に関する説明のNewタブに初期設定の仕方が書かれている。
それを実行するとVagrantfileが作成されてBoxがインストールされる。
コマンドは次の2行。

>vagrant init bento/centos-7.5
>vagrant up


コマンドを実行したらつくられたVagrantfileをテキストエディタで開く。
ipアドレスが書かれた行のコメントマークを削除。
今回の場合は2つ目の仮想マシンなのでipアドレス192.168.33.10から192.168.33.11に変更。
変更したらファイルを保存する。

Vagrantfile

#修正前
# config.vm.network "private_network", ip: "192.168.33.10"

#修正後
config.vm.network "private_network", ip: "192.168.33.11"


VagrantをリロードしてVagrantfileの修正を有効にする。

>vagrant reload


CentOS7にRubyをインストール

この先はPuttyで操作する。
Puttyを立ち上げてVagrantにログインする。

今回はCentOS7.5にRuby2.5.1をインストールした。
インストールの大まかな流れは次のとおり。

  • Gitをインストールする
    • yumをつかってインストール
  • rbenvをインストールする
    • GitをつかってGitHubからクローン
  • Rubyをインストールする
    • rbenvをつかってインストール


まずyumアップデート。

sudo yum -y update


この先は@nyanyamoさんの記事を参考にRubyをインストールした。
参考というかそのままであっさりインストールできました。

centOS7にrbenvとruby2.5.1いれたよ
https://qiita.com/nyanyamo/items/952823ca044859232d82

インストール後はCyberduckをつかってディレクトリやファイルを管理。


これでWindowsPCでも前回書いたコードが動かせるようになった。

手続き型のコードをオブジェクト指向型のコードに書きかえる

ボートレース(レガッタ)の結果をボートクラブ別に検索できるコードを前に書いた。

ローイングファン version1 - ローイングファンの日記

このコードが手続き型だったのでオブジェクト指向型に書きかえてみた。
(2018-07-20修正 コードの実行部分にwhile文を追記)
目次


ローイングファンver1.0から1.1へ

今回書きかえた際、クローリング先のURLはあらかじめコードに仕込むようにした。
例として2017年全日本軽量級選手権の女子舵手なしクォドルプルと男子エイトのURLを登録した。

日本ボート協会 大会情報
第39回全日本軽量級選手権大会
女子舵手なしクォドルプル
https://www.jara.or.jp/race/2017/2017lightweight_w4x.html

男子エイト
https://www.jara.or.jp/race/2017/2017lightweight_m8+.html

<注意>


WindowsPCでレース結果の検索をためしたい場合はWebアプリ版を使ってください。
ローイングファン
https://rowingfan.herokuapp.com/

ローイングファンver1.1のコード

rowingfan_ver1_1.rb

require 'open-uri'

class RaceinfoCollector
    def initialize
        @raceInfoUrls = [ #行末のカンマを忘れずに
            "https://www.jara.or.jp/race/2017/2017lightweight_w4x.html",
            "https://www.jara.or.jp/race/2017/2017lightweight_m8+.html"
        ]
        @guidances = { #行末のカンマを忘れずに
            intro: "レース(レガッタ)情報をクローリングします。",
            yes: "つづける場合は 1 を入力",
            no: "中止する場合は 2 を入力",
            yesOrNo: "半角(1or2): ",
            wait: "クローリング中です。\n#{@raceInfoUrls.size}秒おまちください。",
            seeYou: "See you ...",
            decoHyphen: "----------"
        }
    end

    def crawl_results
        puts @guidances[:decoHyphen]
        puts @guidances[:intro]
        puts @guidances[:yes]
        puts @guidances[:no]
        puts @guidances[:decoHyphen]
        print @guidances[:yesOrNo]
        reply = gets.chomp.to_i
        if reply == 1
            puts @guidances[:wait]
            #全レース結果が入る配列を作成
            raceinfos_all = []
            @raceInfoUrls.each do |url|
                # HTMLをよみこむ
                # :utf-8オプションをつけないとバイト列になる
                opened_html = open("#{url}","r:utf-8")
                html_by_event = opened_html.read
                opened_html.close
                sleep(1) #<重要!>クローリングの間隔をあける

                #シングルスカル種目のクルー名にある余計なタブを削除
                html_by_event.gsub!(/<br.?\/><small>/,'')
                html_by_event.gsub!(/<\/small>/,'')

                # データを取得する
                # 大会名、年代、種目名(タグ付き)
                /<h1 class=\"title\">第\d+(?<tag_tourname>.+)大会<\/h1>/ =~ html_by_event
                /<a href=\"(?<tag_year>\d\d\d\d).+><i class=\"glyphicon glyphicon-file\"><\/i>/ =~ html_by_event
                /<div class=\"panel-heading\">(?<tag_event>.+)の組合せと結果<\/div>\n/ =~ html_by_event
                #レース記号(タグ付き)
                /\Ahttps:\/\/www.+\/(?<tag_urlyear>\d\d\d\d)(?<tag_urltour>.+)_(?<tag_urlevent>.+).html\z/ =~ url
                
                #---id情報---
                #RaceNo, 発艇日時, 組別
                raceno_array = html_by_event.scan(/Race No:\s(\d+)<\/div>/)
                starttime_array = html_by_event.scan(/発艇時刻:<\/b>\s(\d+\/\d+\s\d+:\d+)<\/div>/)
                group_array = html_by_event.scan(/<b>組別:<\/b> <a href=\"\d+.+_tt.html.day\d+_\d+_\d+\">(.+)<\/a><\/div>/)
                
                #---順位別情報---
                #順位, クルー名
                rank_array = html_by_event.scan(/<tr>\n.*<td class=\"text-right\">(\d?)<\/td>/)
                crew_array = html_by_event.scan(/<td class=\"crew\">(.*)<\/td>/)
                #ラップ500, 1000, 1500, 2000
                lap500_array = html_by_event.scan(/<td class=\"crew\">.*<\/td>\n.*<td class=\"text-center\">(\d*:?\d*.?\d*)<\/td>\n/)
                lap1000_array = html_by_event.scan(/<td class=\"crew\">.*<\/td>\n.+<\/td>\n.*<td class=\"text-center\">(\d*:?\d*.?\d*)<\/td>\n/)
                lap1500_array = html_by_event.scan(/<td class=\"text-center\">(\d*:?\d*.?\d*)<\/td>\n.*<td class=\"text-center\">.*<\/td>\n.*<td class=\"text-right\">\d*<\/td>\n/)
                lap2000_array = html_by_event.scan(/<td class=\"text-center\">(\d*:?\d*.?\d*)<\/td>\n.*<td class=\"text-right\">\d*<\/td>\n/)
                #レーンNo, 備考
                laneno_array = html_by_event.scan(/<td class=\"text-right\">(\d?)<\/td>\n.*<td class=\"qualify\">.*<\/td>\n/)
                qualify_array = html_by_event.scan(/<td class=\"qualify\">(.*)<\/td>\n/)

                #id情報の融合 レースNoを基準にしてレース日時,組別の行と列を入れ替える
                #=> [ [ [RaceNo1], [5/10 8:00], [予選A] ], [ [RaceNo2], [5/10 8:20], [予選B] ], [ [RaceNo3], [5/10 8:40,予選C] ], ....]
                identifiers = raceno_array.zip(starttime_array,group_array)

                #id情報に年, 大会名, 種目名を追加する
                identifiers.each do |identifier|
                    identifier.insert(1,tag_event)
                    identifier.insert(0,tag_year,tag_tourname,)
                    identifier.flatten!
                end

                #順位を基準にして,クルー名,ラップタイム,ゴールタイム,レーンNo,備考の行と列を入れ替える
                #=> [ [ [1], [crew], [500], [1000], [1500], [2000], [LaneNo], [備考] ], [ [2],....], [ [3],....] ]
                infos_by_rank = rank_array.zip(crew_array, lap500_array, lap1000_array, lap1500_array, lap2000_array, laneno_array, qualify_array)

                #1レース分の順位別情報を入れる配列を作成
                infos_rank1_6 = []
                #すべての順位別情報が入る配列を作成
                infos_rank1_6_all = []
                count = 0
                infos_by_rank.each do |info_by_rank|
                    count += 1
                    info_by_rank.flatten!
                    #6着の情報の次で配列を空にする
                    infos_rank1_6 = [] if count % 6 == 1
                    #1着から6着を1セットの配列にする
                    infos_rank1_6 << info_by_rank
                    #1着から6着が1セットになった配列を一つの配列に格納していく
                    infos_rank1_6_all << infos_rank1_6 if count % 6 == 0
                end

                #id情報と順位別レース結果の行と列を入れ替える
                #入れ替え後、ブロックに渡して配列に格納する
                identifiers.zip(infos_rank1_6_all) do |infos|
                    raceinfos_all << infos.flatten!
                end
            end #//@raceInfoUrls.each do |url|

            return raceinfos_all
        else
            puts ""
            puts @guidances[:seeYou]
            exit
        end #//if reply == 1
    end #def crawl_results
end

class RaceInfoManager
    attr_writer :race_results
    def initialize
        @race_results = []
        @guidances = { #行末のカンマを忘れずに
            intro: "ボートクラブ別にレース結果を検索します。",
            enterClubname: "ボートクラブの名称を入力してください。\n名称: ",
            hit: "レースを表示します。",
            tocsv: "CSVファイルをつくりました。",
            unhit: "見つかりませんでした。",
            decoHyphen: "----------"
        }
    end

    def find_race
        puts @guidances[:decoHyphen]
        puts @guidances[:intro]
        print @guidances[:enterClubname]
        gotten_clubname = gets.chomp
        found_races = []
        @race_results.each do |race_result|
            if  /.*#{gotten_clubname}[A-Z]?\)?\z/i =~ race_result[7]  ||  
                /.*#{gotten_clubname}[A-Z]?\)?\z/i =~ race_result[15] ||  
                /.*#{gotten_clubname}[A-Z]?\)?\z/i =~ race_result[23] ||  
                /.*#{gotten_clubname}[A-Z]?\)?\z/i =~ race_result[31] ||  
                /.*#{gotten_clubname}[A-Z]?\)?\z/i =~ race_result[39] ||  
                /.*#{gotten_clubname}[A-Z]?\)?\z/i =~ race_result[47]
                found_races << race_result
            end
        end
        return found_races
    end

    def display_race_results(found_races)
        unless found_races.size == 0
            puts @guidances[:decoHyphen]
            print "#{found_races.size}"
            puts @guidances[:hit]
            puts @guidances[:decoHyphen]
            sleep(1.5)
            found_races.each do |race_result|
                #年, 大会名の出力
                puts "#{race_result[0]}#{race_result[1]}"
                #RaceNo, 種目, 組別, 日時の出力
                puts "RaceNo #{race_result[2]} #{race_result[3]} #{race_result[5]}\n#{race_result[4]}"
                #順位, クルー名, 2000mタイム, 備考の出力
                puts "#{race_result[6] }#{race_result[7] } #{race_result[11]} #{race_result[13]}" if race_result[7] != ""
                puts "#{race_result[14]}#{race_result[15]} #{race_result[19]} #{race_result[21]}" if race_result[15] != ""
                puts "#{race_result[22]}#{race_result[23]} #{race_result[27]} #{race_result[29]}" if race_result[23] != ""
                puts "#{race_result[30]}#{race_result[31]} #{race_result[35]} #{race_result[37]}" if race_result[31] != ""
                puts "#{race_result[38]}#{race_result[39]} #{race_result[43]} #{race_result[45]}" if race_result[39] != ""
                puts "#{race_result[46]}#{race_result[47]} #{race_result[51]} #{race_result[53]}" if race_result[47] != ""
                puts @guidances[:decoHyphen]
            end   
        else
            puts @guidances[:decoHyphen]
            puts @guidances[:unhit]
            puts @guidances[:decoHyphen]
        end #//unless found_races.size == 0
    end

    def write_csv(found_races)
        unless found_races.size == 0
            found_races.each do |race_result|
                #CSVファイル名につける記号を作成する
                case race_result[1]
                when "全日本軽量級選手権"
                    tourname_mark = "lightweight"
                when "全日本大学選手権"
                    tourname_mark = "incolle"
                when "全日本選手権"
                    tourname_mark = "alljapan"
                when "全日本新人選手権"
                    tourname_mark = "freshperson"
                end
                case race_result[3]
                    when "女子シングルスカル"
                        event_mark = "w1x"
                    when "男子シングルスカル"
                        event_mark = "m1x"
                    when "女子ダブルスカル"
                        event_mark = "w2x"
                    when "男子ダブルスカル"
                        event_mark = "m2x"
                    when "女子舵手なしペア"
                        event_mark = "w2-"
                    when "男子舵手なしペア"
                        event_mark = "m2-"
                    when "男子舵手つきペア"
                        event_mark = "m2+"
                    when "女子舵手なしクォドルプル"
                        event_mark = "w4x"
                    when "女子舵手つきクォドルプル"
                        event_mark = "w4x+"
                    when "男子舵手なしクォドルプル"
                        event_mark = "m4x"
                    when "男子舵手なしフォア"
                        event_mark = "m4-"
                    when "女子舵手つきフォア"
                        event_mark = "w4+"
                    when "男子舵手つきフォア"
                        event_mark = "m4+"
                    when "女子エイト"
                        event_mark = "w8+"
                    when "男子エイト"
                        event_mark = "m8+"
                end
                File.open("#{race_result[0]}_#{tourname_mark}_#{event_mark}.csv","a:shift_jis") do |csv|
                    csv.write "#{race_result[0]}#{race_result[1]} RaceNo #{race_result[2]}\n#{race_result[3]} #{race_result[5]}\n#{race_result[4]}\n"
                    csv.write "rank,crew,500m,1000m,1500m,2000m,lane,remarks\n"
                    csv.write "#{race_result[6] },#{race_result[7] },#{race_result[8] },#{race_result[9] },#{race_result[10]},#{race_result[11]},#{race_result[12]},#{race_result[13]},\n"
                    csv.write "#{race_result[14]},#{race_result[15]},#{race_result[16]},#{race_result[17]},#{race_result[18]},#{race_result[19]},#{race_result[20]},#{race_result[21]},\n"
                    csv.write "#{race_result[22]},#{race_result[23]},#{race_result[24]},#{race_result[25]},#{race_result[26]},#{race_result[27]},#{race_result[28]},#{race_result[29]},\n"
                    csv.write "#{race_result[30]},#{race_result[31]},#{race_result[32]},#{race_result[33]},#{race_result[34]},#{race_result[35]},#{race_result[36]},#{race_result[37]},\n"
                    csv.write "#{race_result[38]},#{race_result[39]},#{race_result[40]},#{race_result[41]},#{race_result[42]},#{race_result[43]},#{race_result[44]},#{race_result[45]},\n"
                    csv.write "#{race_result[46]},#{race_result[47]},#{race_result[48]},#{race_result[49]},#{race_result[50]},#{race_result[51]},#{race_result[52]},#{race_result[53]},\n"
                    csv.write "\n"
                end #//File.open
            end #//found_races.each do |race_result|
            puts ""
            puts @guidances[:tocsv]
        end #//unless found_races.size == 0
    end
end

#----ここからコードの実行-----
infoCollector = RaceinfoCollector.new
infoManager = RaceInfoManager.new

#crawllerを実行してレース結果を入手する
#crawlで入手したレース結果をinfoManagerに取り込む
result_collections = infoCollector.crawl_results
infoManager.race_results = result_collections

while true
    #クラブ名とマッチするレースを検索する
    #見つけた結果を表示してCSVファイルをつくる
    found_races = infoManager.find_race
    infoManager.display_race_results(found_races)
    infoManager.write_csv(found_races)
    puts ""
    puts "検索をつづける場合は 1 を入力"
    puts "検索を終了する場合は 2 を入力"
    print "半角(1or2): "
    reply = gets.chomp.to_i
    if reply != 1
        exit
    end
end


実行結果

結果をターミナルに表示させる

女子舵手なしクォドルプル、男子エイトともに優勝している明治大学で検索を試してみる。

まず適当なディレクトリをつくり、その中にRubyコードのファイルを保存する。

ターミナルでコードファイルが保存されているディレクトリに移動しておく。

コードを実行する。

ruby rowingfan_ver1_1.rb


確認表示が出るので12を入力する。

----------
レース(レガッタ)情報をクローリングします。
つづける場合は 1 を入力
中止する場合は 2 を入力
----------
半角(1or2):  


ボートクラブ名の入力を求められるので検索したいボートクラブ名を入力する。
今回は明治大学と入力。

半角(1or2): 1
クローリング中です。
2秒おまちください。
----------
ボートクラブ別にレース結果を検索します。
ボートクラブの名称を入力してください。
名称: 


検索結果がターミナルに表示されCSVファイルが種目ごとにつくられる。

ボートクラブ別にレース結果を検索します。
ボートクラブの名称を入力してください。
名称: 明治大学
----------
8レースを表示します。
----------
2017全日本軽量級選手権
RaceNo 39 女子舵手なしクォドルプル 予選C組
05/26 13:48
1着 明治大学 07:12.79 →Semi-Final
2着 立命館大学 07:22.76 
3着 早稲田大学 07:26.72 
----------
2017全日本軽量級選手権
RaceNo 111 女子舵手なしクォドルプル 準決B組
05/28 10:52
1着 仙台大学 07:01.51 →Final A
2着 明治大学 07:01.76 →Final A
3着 富山国際大学 07:04.14 →Final B
4着 日本体育大学A 07:15.03 →Final B
----------
2017全日本軽量級選手権
RaceNo 129 女子舵手なしクォドルプル 決勝
05/28 15:40
1着 明治大学 07:07.20 
2着 法政大学A 07:10.52 
3着 仙台大学 07:12.14 
4着 立命館大学 07:17.54 
----------
2017全日本軽量級選手権
RaceNo 45 男子エイト 予選A組
05/26 14:36
1着 一橋大学A 06:17.28 →Semi-Final
2着 明治大学B 06:26.61 
3着 早稲田大学 06:26.93 
4着 一橋大学C 06:45.94 
----------
2017全日本軽量級選手権
RaceNo 46 男子エイト 予選B組
05/26 14:44
1着 明治大学A 06:04.48 →Semi-Final
2着 東京大学 06:22.25 
3着 日本大学 06:25.30 
4着 成蹊大学 06:27.95 
----------
2017全日本軽量級選手権
RaceNo 91 男子エイト 敗復B組
05/27 15:10
1着 東京大学 06:26.79 →Semi-Final
2着 早稲田大学 06:29.00 →Semi-Final
3着 明治大学B 06:29.45 
4着 一橋大学C 06:48.27 
5着 慶應義塾大学 06:54.51 
----------
2017全日本軽量級選手権
RaceNo 114 男子エイト 準決A組
05/28 11:16
1着 明治大学A 06:08.44 →Final A
2着 東京大学 06:13.42 →Final A
3着 日本大学 06:16.40 →Final B
4着 一橋大学B 06:24.66 →Final B
----------
2017全日本軽量級選手権
RaceNo 133 男子エイト 決勝
05/28 16:30
1着 明治大学A 06:07.50 
2着 仙台大学 06:12.84 
3着 一橋大学A 06:18.60 
4着 東京大学 06:29.16 
----------

CSVファイルをつくりました。


CSVファイルを表計算アプリで開く

検索結果をターミナルに表示したあと種目ごとにCSVファイルがつくられる。
文字エンコーディングはShift-JISに設定してある。
ファイル名の書式は次の通り。

年_大会名(記号)_種目名(記号).csv


CSVファイルを表計算アプリで開いたところは次の通り。

2017_lightweight_w4x.csv

f:id:rowingfan:20180719071034p:plain

感想

オブジェクト指向型でコードを書くとメンテナンスがしやすくなる。
拡張もしやすい。データベースやTwitterと連動させればWebアプリ版ローイングファンになる。

今回のコードはRuby2.5.1 Windows環境では動かなかった。getsで取得する日本語処理のしかたがわからなかった。
解決したらコードを修正する予定。
そろそろWindowsPCに仮想環境をつくりたい。

今回の実行環境

macOS 10.13.5
Ruby 2.5.1p57

CentOS 7.5
Ruby 2.5.1p57

疑似乱数を発生させるrand

randは疑似乱数を発生させるメソッド。
今回はrandメソッドを使ってツイートの定型文に変化をつける。

目次


randを使う理由

レース(レガッタ)情報をツイートする

ローイングファンではボートレース(レガッタ)の結果をツイートしている。
Twitterライブラリを利用したツイートのしかたは前に書いた。

Twitterライブラリ
https://rowingfan.hatenablog.jp/entry/2018/05/22/120000

レース結果のツイートは次のようなもの。





似たような内容のツイートはTwitterのアカウント停止処分をうける?

はじめの頃は表題部分を定形にしていた。そうしたところ何度もアカウント停止処分を受けた。
どうやら書式が同じだと内容は違っていてもスパム扱いされるようだ。
(すべて次のような同じ文の表題をつけるとスパム扱いされる?)

2018 ボート全日本軽量級 結果


そこで次の例のように語順を変えた表題をいくつか用意して、ツイートごとに不規則に利用するよう改良した。

例(実際はもっと種類がある)

2018 全日本軽量級(ボート) 結果
2018 ボート全日本軽量級 結果
ボート全日本軽量級2018の結果


改良してからアカウント停止をうけていない。

randの使い方

randのリファレンスマニュアル

randのリファレンスマニュアルは次のとおり。

Karnelモジュール > rand
https://docs.ruby-lang.org/ja/latest/method/Kernel/m/rand.html

書式

rand(max)
rand(range)


引数max,rangeには数値が入る。
max、rangeが整数の場合は整数が返ってくる。

#次の2つとも 0,1,2 いずれかの整数を不規則に返す
p rand(3)
p rand(0..2)


randを使ったコード

テストコードを書く。

randtest.rb

class TweetTitle
    def initialize
        @titles = [
            "2018 全日本軽量級(ボート) 結果",
            "2018 ボート全日本軽量級 結果",
            "ボート全日本軽量級2018の結果"
        ]
    end

    def tweet_title
        puts @titles[rand(@titles.size)]
    end
end

5.times do
    TweetTitle.new.tweet_title
end


コードの説明

  • TweetTitleクラスをつくる
    • initializeメソッドで表題の配列を初期化する
    • tweet_titleメソッドをつくる
      • randメソッドを使って配列のインデックスを不規則につくる
      • sizeメソッドを使ってrandの引数を@titlesの要素数にする
  • timesメソッドでtweet_titleメソッドを繰り返す(今回は5回)


実行結果

ターミナル/PowerShellを使ってコードを実行する。

ruby randtest.rb


実行結果

2018 ボート全日本軽量級 結果
ボート全日本軽量級2018の結果
2018 全日本軽量級(ボート) 結果
ボート全日本軽量級2018の結果
2018 全日本軽量級(ボート) 結果


表題が不規則に出力された。
この仕組を使って不規則な表題をつぶやいている。

今回の実行環境

macOS 10.13.5
Windows10 Home 1803
Ruby 2.5.1p57