おぴよの気まぐれ日記

おぴよの気まぐれ日記

岡山やプログラミング、ファッションのこと、子育てや人生、生き方についての備忘録。

【Rails環境構築】bundle installでエラーになる時の対処法!

こんにちは。opiyoです。

  • 昨日まで普通に動いていたのに
  • 教科書、本と通りに設定しているはずなのに
  • 何もしてないのに動かないぞー

って経験無いでしょうか?

僕も昨日新しくMacが手に入ったのでRails環境をローカルに構築して今作っているRailsアプリを動かそうとしたら...


2時間近くはまってしまいました。

元々使ってたMacと全く同じ設定のはずなのに何故動かないんだーって状況でした。

どうにかこうにか解決する事が出来たので、その方法について共有できればと思います。

エラーが出た時に「どうすれば良いか」が分からなくて諦めてしまう。ってのが結構あると思うのですが答えは必ずエラーの中に書かれている ので頑張ってGoogle翻訳使って一つずつ解決していくのが大事だと思いますので僕がどうやって進めていったのかのログです。

動かしたいRailsアプリについて

僕の場合は、こんな感じ。

$ ruby -v
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin15]

$ rails -v
Rails 5.1.4

bundle installができない

$ bundle install

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /Users/tnakano/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/pg-0.21.0/ext
/Users/tnakano/.rbenv/versions/2.5.0/bin/ruby -r ./siteconf20180125-28967-e942ot.rb extconf.rb
checking for pg_config... no
No pg_config... trying anyway. If building fails, please try again with
 --with-pg-config=/path/to/pg_config
checking for libpq-fe.h... no
Can't find the 'libpq-fe.h header
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/Users/tnakano/.rbenv/versions/2.5.0/bin/$(RUBY_BASE_NAME)
    --with-pg
    --without-pg
    --enable-windows-cross
    --disable-windows-cross
    --with-pg-config
    --without-pg-config
    --with-pg_config
    --without-pg_config
    --with-pg-dir
    --without-pg-dir
    --with-pg-include
    --without-pg-include=${pg-dir}/include
    --with-pg-lib
    --without-pg-lib=${pg-dir}/lib

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Users/tnakano/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/extensions/x86_64-darwin-16/2.5.0-static/pg-0.21.0/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Users/tnakano/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/pg-0.21.0 for inspection.
Results logged to /Users/tnakano/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/extensions/x86_64-darwin-16/2.5.0-static/pg-0.21.0/gem_make.out

An error occurred while installing pg (0.21.0), and Bundler cannot continue.
Make sure that `gem install pg -v '0.21.0'` succeeds before bundling.

In Gemfile:
  pg

これだけ見ても何が何だか分からないですよね。 ですが諦めずに良く良く表示されたメッセージを見てください。

ポイントは最後辺りのMake sure thatgem install pg -v '0.21.0'succeeds before bundling.ですね。

直訳するとバンドルの前にgem install pg -v '0.21.0'が成功していることを確認してください。`になります。

じゃー次にgem pgって何だってなると思いますので、これを調べてみるとPostgreSQLにアクセスするために必要なことだと分かります。

「あっそもそもPostgreSQLインストールしてねーじゃん」ってことに僕は気づきましたので、PostgreSQLをインストールします。

postgresqlをインストールする

$ brew install postgresql
==> Installing postgresql

PostgreSQLがインストール出来たので、もっかいbundle install実行!

$ bundle install
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /Users/tnakano/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/rmagick-2.16.0/ext/RMagick
/Users/tnakano/.rbenv/versions/2.5.0/bin/ruby -r ./siteconf20180125-42802-14ohnoi.rb extconf.rb
checking for clang... yes
checking for Magick-config... no
checking for pkg-config... yes
Package MagickCore was not found in the pkg-config search path.
Perhaps you should add the directory containing `MagickCore.pc'
to the PKG_CONFIG_PATH environment variable
No package 'MagickCore' found
checking for outdated ImageMagick version (<= 6.4.9)... *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/Users/tnakano/.rbenv/versions/2.5.0/bin/$(RUBY_BASE_NAME)

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Users/tnakano/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/extensions/x86_64-darwin-16/2.5.0-static/rmagick-2.16.0/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Users/tnakano/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/rmagick-2.16.0 for inspection.
Results logged to /Users/tnakano/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/extensions/x86_64-darwin-16/2.5.0-static/rmagick-2.16.0/gem_make.out

An error occurred while installing rmagick (2.16.0), and Bundler cannot continue.
Make sure that `gem install rmagick -v '2.16.0'` succeeds before bundling.

In Gemfile:
  rmagick

おーエラーの内容が変わりましたね。一歩前進です。

次にエラーになっている原因を探すと、さっきと同じようなメッセージが出ていますね。

Make sure thatgem install rmagick -v '2.16.0'succeeds before bundling.これを直訳するとバンドルする前にgem install rmagick -v '2.16.0'が成功していることを確認してください。ってなります。

同じようにgem rmagickを調べて解決方法を探します。するとImagemagickってのをインストールしないといけないっぽいですね。

という感じで表示されたメッセージを良く読んで、エラー文をそのままGoogleさんに聞くと同じように悩んで解決したって記事がいっぱい見つかると思うので一つずつ試していきます。

imagemagickがインストールできない

$ brew install imagemagick
==> Installing imagemagick

Imagemagickがインストール出来たので、もっかいbundle install実行します。

$ bundle install
.
.
.
checking for outdated ImageMagick version (<= 6.4.9)... no
checking for presence of MagickWand API (ImageMagick version >= 6.9.0)... no
checking for Ruby version >= 1.8.5... yes

またエラーになりますね。

なんだかこの辺りが怪しそうなので、色々調べてみるとImageMagickのバージョンが7系だとダメみたい。

$ convert --version
Version: ImageMagick 7.0.7-22 Q16 x86_64 2018-01-22 http://www.imagemagick.org

うん。ダメぽ。

$ brew uninstall imagemagick
Uninstalling /usr/local/Cellar/imagemagick/7.0.7-22... (1,527 files, 23.3MB)
$ convert --version
-bash: /usr/local/bin/convert: No such file or directory

うん。削除できてるっぽいですね。

$ brew install imagemagick@6
==> Downloading https://homebrew.bintray.com/bottles/imagemagick@6-6.9.9-34.sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring imagemagick@6-6.9.9-34.sierra.bottle.tar.gz
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local,
because this is an alternate version of another formula.

If you need to have this software first in your PATH run:
  echo 'export PATH="/usr/local/opt/imagemagick@6/bin:$PATH"' >> ~/.bash_profile

For compilers to find this software you may need to set:
    LDFLAGS:  -L/usr/local/opt/imagemagick@6/lib
    CPPFLAGS: -I/usr/local/opt/imagemagick@6/include
For pkg-config to find this software you may need to set:
    PKG_CONFIG_PATH: /usr/local/opt/imagemagick@6/lib/pkgconfig

==> Summary
🍺  /usr/local/Cellar/imagemagick@6/6.9.9-34: 1,472 files, 22.8MB
$ convert --version
-bash: /usr/local/bin/convert: No such file or directory

あれっなんだ。おかしいぞ。 もっかい見直してみる。

This formula is keg-only, which means it was not symlinked into /usr/local,
because this is an alternate version of another formula.

If you need to have this software first in your PATH run:
  echo 'export PATH="/usr/local/opt/imagemagick@6/bin:$PATH"' >> ~/.bash_profile

For compilers to find this software you may need to set:
    LDFLAGS:  -L/usr/local/opt/imagemagick@6/lib
    CPPFLAGS: -I/usr/local/opt/imagemagick@6/include
For pkg-config to find this software you may need to set:
    PKG_CONFIG_PATH: /usr/local/opt/imagemagick@6/lib/pkgconfig

この辺りがエラーだろう。とりあえず翻訳だー

この式はkeg-onlyであり、/ usr / localにシンボリックリンクされていないことを意味し、
これは別の式の代替バージョンであるためです。

PATHでこのソフトウェアを最初に実行する必要がある場合:
  echo 'export PATH = "/ usr / local / opt / imagemagick @ 6 / bin:$ PATH"' >>〜/ .bash_profile

ふむふむ。パスが通ってないってことだと思うので...

$ echo 'export PATH="/usr/local/opt/imagemagick@6/bin:$PATH"' >> ~/.bash_profile
$ source .bash_profile

もっかいimagemagickをインストール

$ brew uninstall imagemagick@6
$ brew install imagemagick@6
$ convert --version
Version: ImageMagick 6.9.9-34 Q16 x86_64 2018-01-22 http://www.imagemagick.org

よしよし。これで6.9になったのでもっかい

$ bundle install
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /Users/tnakano/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/rmagick-2.16.0/ext/RMagick
/Users/tnakano/.rbenv/versions/2.5.0/bin/ruby -r ./siteconf20180125-47095-pm8xl8.rb extconf.rb
checking for clang... yes
checking for Magick-config... yes
checking for outdated ImageMagick version (<= 6.4.9)... no
checking for presence of MagickWand API (ImageMagick version >= 6.9.0)... no
Package MagickWand was not found in the pkg-config search path.
Perhaps you should add the directory containing `MagickWand.pc'
to the PKG_CONFIG_PATH environment variable
No package 'MagickWand' found
Package MagickWand was not found in the pkg-config search path.
Perhaps you should add the directory containing `MagickWand.pc'
to the PKG_CONFIG_PATH environment variable
No package 'MagickWand' found
Package MagickWand was not found in the pkg-config search path.
Perhaps you should add the directory containing `MagickWand.pc'
to the PKG_CONFIG_PATH environment variable
No package 'MagickWand' found
Package MagickWand was not found in the pkg-config search path.
Perhaps you should add the directory containing `MagickWand.pc'
to the PKG_CONFIG_PATH environment variable
No package 'MagickWand' found
.
.
An error occurred while installing rmagick (2.16.0), and Bundler cannot continue.
Make sure that `gem install rmagick -v '2.16.0'` succeeds before bundling.

In Gemfile:
  rmagick

くそーダメぽ。

もっかいエラーと睨めっこしてみるとPKG_CONFIG_PATHってのがNo言われてる。 これを設定すれば良いのか?

$ echo 'export PKG_CONFIG_PATH="/usr/local/opt/imagemagick@6/lib/pkgconfig"' >> ~/.bash_profile
$ source .bash_profile

今度こそ〜神様〜

$ bundle install
Installing rmagick 2.16.0 with native extensions
.
.
Bundle complete! 26 Gemfile dependencies, 95 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

できたー!!!!!

まとめ

ハマるポイントとしては

  • imagemagicは6系をインストールする必要がある!
  • インストールされた6系に対してパスを通してあげる必要がある
  • エラーをよく読む!

答えはいつも「エラー」にある!

英語大事...

初心者でも30分で出来た!MacにRails開発環境を作ってみた

こんばんは。opiyoです。

プログラマの勉強をしていて最初につまずくポイントは環境構築じゃないでしょうか?

今はCloud9とかWeb上で勉強できるサイトなどが当たり前になってきているので、作るきっかけは無いかもしれないですがエンジニアとして働いていく上で環境構築はきっと出来た方がいいはずです!

新しく会社に入った時を想像すると最初にやる仕事はきっと、渡されたMacに携わるプロジェクトの環境を構築する事だと思います。

という事で、今日は1から作業してみたいと思います。

このMacについて

  • OS X El Capitan(10.11.6)

Homebrewインストール

Homebrewは、Macでソフトウェアの導入を単純化するパッケージ管理システムだと。 これをインストールすることbrew hogeみたいな感じで簡単に色々なソフトウェアをダウンロードできる。

インストール方法は、ターミナルに以下のコマンドを貼り付けて実行する

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
.
.
.
==> Installation successful!

どんなバージョンが入っているかはbrewコマンドに-vオプション付けます。

$ brew -v
Homebrew 1.5.2

brewコマンドのパスを設定します

$ echo 'export PATH=/usr/local/bin:$PATH' >> .bash_profile
$ source .bash_profile

brewの最新バージョンを取得する場合はupdateします

$ brew update

これ以外にも沢山の事が出来るので操作方法をチェックするにはhelpで確認してみましょう!

$ brew help
Example usage:
  brew search [TEXT|/REGEX/]
  brew (info|home|options) [FORMULA...]
  brew install FORMULA...
  brew update
  brew upgrade [FORMULA...]
  brew uninstall FORMULA...
  brew list [FORMULA...]

Troubleshooting:
  brew config
  brew doctor
  brew install -vd FORMULA

Developers:
  brew create [URL [--no-fetch]]
  brew edit [FORMULA...]
  https://docs.brew.sh/Formula-Cookbook.html

Further help:
  man brew
  brew help [COMMAND]
  brew home

gitインストール

gitは、ソースコードのバージョン管理の仕組みです。 gitは普段仕事でも使っているのですが、インストールとか設定とか全然覚えていないので復習

インストールは先程のbrewコマンドを使って行います。 ついでにメールアドレスの設定も行います。  ※メールアドレスだけ設定しておけばgithubpushした際にgithubがよしなに解釈してくれます。

$ brew install git 
$ git --version
git version 2.16.1

$ git config --global user.email email@example.com

githelpを使うと使い方が出てきます。

$ git --help
usage: git [--version] [--help] [-C <path>] [-c name=value]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]

These are common Git commands used in various situations:

start a working area (see also: git help tutorial)
   clone      Clone a repository into a new directory
   init       Create an empty Git repository or reinitialize an existing one

work on the current change (see also: git help everyday)
   add        Add file contents to the index
   mv         Move or rename a file, a directory, or a symlink
   reset      Reset current HEAD to the specified state
   rm         Remove files from the working tree and from the index

examine the history and state (see also: git help revisions)
   bisect     Use binary search to find the commit that introduced a bug
   grep       Print lines matching a pattern
   log        Show commit logs
   show       Show various types of objects
   status     Show the working tree status

grow, mark and tweak your common history
   branch     List, create, or delete branches
   checkout   Switch branches or restore working tree files
   commit     Record changes to the repository
   diff       Show changes between commits, commit and working tree, etc
   merge      Join two or more development histories together
   rebase     Reapply commits on top of another base tip
   tag        Create, list, delete or verify a tag object signed with GPG

collaborate (see also: git help workflows)
   fetch      Download objects and refs from another repository
   pull       Fetch from and integrate with another repository or a local branch
   push       Update remote refs along with associated objects

rbenvインストール

rbenvは複数のRubyのバージョンを切り替えて使う為の環境を提供してくれる。 プロジェクトによってバージョンが違う事があるからこれで管理するそうだ。

インストール方法は、先程のbrewを使う。 この時に、ruby-buildというRubyをインストールするプラグインも合わせてインストールする

$ brew install rbenv ruby-build

rbenvコマンドにパスを設定する

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

pathを設定する際に出てくる「$HOME」という奴は環境変数って奴です。 環境変数はプログラムの検索先を変数に入れて、毎回長いpathを打つのを省略してくれます。 今回であればrbenvの実行ファイルが格納されているディレクトリをPATHに追加しています。

Rubyインストール

次にインストール可能なRubyのバージョン一覧を表示する

¥ rbenv install --list

するとずらーっと表示されるので、最新のバージョンをインストールします。

今回であれば、2.5.0ですかね。

  2.3.6
  2.4.0-dev
  2.4.0-preview1
  2.4.0-preview2
  2.4.0-preview3
  2.4.0-rc1
  2.4.0
  2.4.1
  2.4.2
  2.4.3
  2.5.0-dev
  2.5.0-preview1
  2.5.0-rc1
  2.5.0
  2.6.0-dev
$ rbenv install 2.5.0

これが結構時間かかる。 で、終わったらインストールしたバージョンを使いますよーって宣言する

$ rbenv global 2.5.0
$ ruby -v
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin16]

ちなみにインストールしているバージョンを調べたい時は

$ rbenv versions
  system
* 2.5.0 (set by /Users/tnakano/.rbenv/version)

*が付いているのが今使われているrubyのバージョンです。

Railsインストール

では、最後にRailsをインストールします。

Railsプロジェクトを作りたい場所に移動してからインストール

$ cd ~/rails
$ gem install rails

bundler(Rubyのライブラリを管理するツール)のインストール

$ gem install bundler

インストールした内容を反映

$ rbenv rehash
$ source ~/.bash_profile

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

$ rails -v
Rails 5.1.4

これで準備が整いましたー

せっかくなので、動く所までやってみよう。

Railsプロジェクト作成

¥ rails new sample
¥ cd sample
¥ rails s

rails s コマンドでwebサーバが起動するので、ブラウザを開いて「localhost:3000」にアクセスすると……

あっという間にRailsアプリが完成です。

Atom

最後に、開発エディタについてですが会社では皆RubyMineを使っているのですが無料のAtomを使いたいと思います。

インストール方法は、こちらからダウンロードするだけ。

https://atom.io/

まとめ

こんな感じで何もエラーにさえならなければ30分くらいで簡単に出来ると思いますので、皆様も是非Macに開発環境を作ってみると良いと思います。

お前何言ってんだよってのがありましたらご教授いただけますと幸いです。

【Ruby on Rails】スクレイピングで簡単にmeta情報を取得するgem metainspector

こんばんわ。エンジニアに夢を描くopiyoです。

最近はずっとスクレイピングについて触れることが多いのですが、こんな経験ないですか?

ブログ書く時とかurl貼り付けるだけで引用文が作成されるけど、あれどうやってんだ?

まさにこういう奴↓↓

opiyotan.hatenablog.com

多分ですが、これもスクレイピングで情報を引っ張ってきているはずなのです。

この情報を簡単に取得できちゃうgemを見っけたので今日は、それについて。

使う準備

こちらは、おなじみGemfileに`metainspector'を記述します。

gem 'metainspector'

こちらも、おなじみbundle installします。

$ bundle install

使い方

はてなブログのトップページにある記事から情報を取得したいと思います!

広島県 VS EM研究機構 - warbler’s diary

※なんだかお堅いサンプルになってしまいしたが...利用させて頂きます。ありがとうございます。

概要=descriptionを取得する

やり方は非常に簡単で取得したデータに対してdescriptionメソッドを呼ぶだけ。

meta = MetaInspector.new("http://warbler.hatenablog.com/entry/2018/01/24/011739")
puts meta.description
.
.
.
広島県からEM菌の水質浄化効果を否定する内容の報告書が出された事に対して、EM研究機構が抗議をしていました。 ・EM菌の培養液は有機物と栄養塩類が高濃度に含まれることから「河川等の汚染源になり得る」という実験結果を報告した福島県に対しても、EM研究機構を含むEM推進側が抗議をしていた事については、既に本ブログで報告して…

画像を取得する

こちらも非常に簡単で取得したデータからimages.bestするだけ。

meta = MetaInspector.new(url)
puts meta.images.best
.
.
.
=> "https://cdn-ak.f.st-hatena.com/images/fotolife/w/warbler/20180124/20180124001356.png"

その他

その他にも色々な情報を簡単に取得できるので、ざらっと書いてみます。

$ rails c
> meta.url
=> "http://warbler.hatenablog.com/entry/2018/01/24/011739"

> meta.host
=> "warbler.hatenablog.com"

> meta.head_links
=> [{:rel=>"canonical", :href=>"http://warbler.hatenablog.com/entry/2018/01/24/011739"}, {:rel=>"shortcut icon", :href=>"https://cdn.image.st-hatena.com/image/favicon/0c16e66ee260e69eb13510af1e9878996b545656/version=1/https:%2F%2Fcdn.user.blog.st-hatena.com%2Fcustom_blog_icon%2F36385751%2F1514183975459583"}, {:rel=>"icon", :sizes=>"192x192", :href=>"https://cdn.image.st-hatena.com/image/square/7fdc8aba078df5faff51cf50422005a5085822ff/backend=imagemagick;height=192;version=1;width=192/https:%2F%2Fcdn.user.blog.st-hatena.com%2Fcustom_blog_icon%2F36385751%2F1514183975459583"}, {:rel=>"alternate", :type=>"application/atom+xml", :title=>"Atom", :href=>"http://warbler.hatenablog.com/feed"}, {:rel=>"alternate", :type=>"application/rss+xml", :title=>"RSS2.0", :href=>"http://warbler.hatenablog.com/rss"}, {:rel=>"alternate", :type=>"application/json+oembed", :href=>"http://hatenablog.com/oembed?url=http://warbler.hatenablog.com/entry/2018/01/24/011739&format=json", :title=>"oEmbed Profile of 広島県 VS EM研究機構"}, {:rel=>"alternate", :type=>"text/xml+oembed", :href=>"http://hatenablog.com/oembed?url=http://warbler.hatenablog.com/entry/2018/01/24/011739&format=xml", :title=>"oEmbed Profile of 広島県 VS EM研究機構"}, {:rel=>"author", :href=>"http://www.hatena.ne.jp/warbler/"}, {:rel=>"stylesheet", :type=>"text/css", :href=>"https://cdn.blog.st-hatena.com/css/blog.css?version=16c4f762d17230c5653ead590e78f5c1c08b8f84&env=production"}, {:rel=>"stylesheet", :type=>"text/css", :href=>"http://blog.hatena.ne.jp/-/blog_style/6653586347156021977/567bb7d3aa205029bfc477b21f9e4dc351ef5eee"}]

> meta.feed
=> "http://warbler.hatenablog.com/rss"

> meta.title
=> "広島県 VS EM研究機構 - warbler’s diary"

> meta.links.raw
=> ["#", "http://warbler.hatenablog.com/", "http://warbler.hatenablog.com/archive/2018/01/24", "http://warbler.hatenablog.com/entry/2018/01/24/011739", "https://www.emro.co.jp/information/04_HH/", "http://www.pref.aomori.lg.jp/kenminno-koe/24K23.html", "http://b.hatena.ne.jp/entry/http://warbler.hatenablog.com/entry/2018/01/24/011739", "https://twitter.com/share", "http://warbler.hatenablog.com/entry/2018/01/23/235522", "http://warbler.hatenablog.com/archive/2018/01/23", "http://warbler.hatenablog.com/entry/20150227/1425057866", "http://warbler.hatenablog.com/archive/2015/02/27", "http://warbler.hatenablog.com/archive/2013/09/03", "http://warbler.hatenablog.com/entry/20130903/1378217975", "http://warbler.hatenablog.com/entry/20130712/1373632961", "http://warbler.hatenablog.com/archive/2013/07/12", "http://warbler.hatenablog.com/entry/20130428/1367131822", "http://warbler.hatenablog.com/archive/2013/04/28", "http://warbler.hatenablog.com/about", "http://blog.hatena.ne.jp/guide/pro", "http://warbler.hatenablog.com/archive", "http://warbler.hatenablog.com/entry/2017/12/02/235126", "http://warbler.hatenablog.com/entry/2017/11/06/113739", "http://warbler.hatenablog.com/entry/2017/09/06/223001", "http://warbler.hatenablog.com/archive/category/EM%E9%96%A2%E4%BF%82", "http://warbler.hatenablog.com/archive/category/%E7%92%B0%E5%A2%83%E5%95%8F%E9%A1%8C", "http://warbler.hatenablog.com/archive/category/%E7%A7%91%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E7%92%B0%E5%A2%83", "http://warbler.hatenablog.com/archive/category/%E7%A0%94%E7%A9%B6%E4%B8%8D%E6%AD%A3", "http://warbler.hatenablog.com/archive/category/%E8%AA%A4%E3%81%A3%E3%81%9F%E7%B5%B1%E8%A8%88", "http://warbler.hatenablog.com/archive/category/%E3%83%8B%E3%82%BB%E7%A7%91%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E6%94%BE%E5%B0%84%E7%B7%9A", "http://warbler.hatenablog.com/archive/category/%E3%83%9E%E3%82%B9%E3%82%B3%E3%83%9F", "http://warbler.hatenablog.com/archive/category/%E5%B2%A1%E5%B1%B1%E5%A4%A7%E4%BA%8B%E4%BB%B6", "http://warbler.hatenablog.com/archive/category/%E6%9B%B8%E8%A9%95", "http://warbler.hatenablog.com/archive/category/%E9%A3%9F%E5%93%81", "http://warbler.hatenablog.com/archive/category/%E5%81%A5%E5%BA%B7", "http://warbler.hatenablog.com/archive/category/%E3%83%9B%E3%83%A1%E3%82%AA%E3%83%91%E3%82%B7%E3%83%BC", "http://warbler.hatenablog.com/archive/category/%E6%8D%8F%E9%80%A0%E8%AB%96%E6%96%87", "http://warbler.hatenablog.com/archive/category/%E7%99%BA%E9%81%94%E9%9A%9C%E5%AE%B3", "http://warbler.hatenablog.com/archive/category/%E5%8C%BB%E7%99%82", "http://warbler.hatenablog.com/archive/category/%E9%9B%91%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E7%B5%B1%E8%A8%88", "http://warbler.hatenablog.com/archive/category/%E8%A6%AA%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E6%95%99%E8%82%B2", "http://blog.hatena.ne.jp/register?via=200227", "http://hatenablog.com/guide", "http://hatenablog.com/", "http://www.hatena.ne.jp/faq/report/blog?target_label=warbler&target_url=http%3A%2F%2Fblog.hatena.ne.jp%2Fgo%3Fblog%3Dhttp%253A%252F%252Fwarbler.hatenablog.com%252Fentry%252F2018%252F01%252F24%252F011739&location=http%3A%2F%2Fblog.hatena.ne.jp%2Fgo%3Fblog%3Dhttp%253A%252F%252Fwarbler.hatenablog.com%252Fentry%252F2018%252F01%252F24%252F011739"]

> meta.links.http
=> ["http://warbler.hatenablog.com/entry/2018/01/24/011739", "http://warbler.hatenablog.com/", "http://warbler.hatenablog.com/archive/2018/01/24", "https://www.emro.co.jp/information/04_HH/", "http://www.pref.aomori.lg.jp/kenminno-koe/24K23.html", "http://b.hatena.ne.jp/entry/http://warbler.hatenablog.com/entry/2018/01/24/011739", "https://twitter.com/share", "http://warbler.hatenablog.com/entry/2018/01/23/235522", "http://warbler.hatenablog.com/archive/2018/01/23", "http://warbler.hatenablog.com/entry/20150227/1425057866", "http://warbler.hatenablog.com/archive/2015/02/27", "http://warbler.hatenablog.com/archive/2013/09/03", "http://warbler.hatenablog.com/entry/20130903/1378217975", "http://warbler.hatenablog.com/entry/20130712/1373632961", "http://warbler.hatenablog.com/archive/2013/07/12", "http://warbler.hatenablog.com/entry/20130428/1367131822", "http://warbler.hatenablog.com/archive/2013/04/28", "http://warbler.hatenablog.com/about", "http://blog.hatena.ne.jp/guide/pro", "http://warbler.hatenablog.com/archive", "http://warbler.hatenablog.com/entry/2017/12/02/235126", "http://warbler.hatenablog.com/entry/2017/11/06/113739", "http://warbler.hatenablog.com/entry/2017/09/06/223001", "http://warbler.hatenablog.com/archive/category/EM%E9%96%A2%E4%BF%82", "http://warbler.hatenablog.com/archive/category/%E7%92%B0%E5%A2%83%E5%95%8F%E9%A1%8C", "http://warbler.hatenablog.com/archive/category/%E7%A7%91%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E7%92%B0%E5%A2%83", "http://warbler.hatenablog.com/archive/category/%E7%A0%94%E7%A9%B6%E4%B8%8D%E6%AD%A3", "http://warbler.hatenablog.com/archive/category/%E8%AA%A4%E3%81%A3%E3%81%9F%E7%B5%B1%E8%A8%88", "http://warbler.hatenablog.com/archive/category/%E3%83%8B%E3%82%BB%E7%A7%91%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E6%94%BE%E5%B0%84%E7%B7%9A", "http://warbler.hatenablog.com/archive/category/%E3%83%9E%E3%82%B9%E3%82%B3%E3%83%9F", "http://warbler.hatenablog.com/archive/category/%E5%B2%A1%E5%B1%B1%E5%A4%A7%E4%BA%8B%E4%BB%B6", "http://warbler.hatenablog.com/archive/category/%E6%9B%B8%E8%A9%95", "http://warbler.hatenablog.com/archive/category/%E9%A3%9F%E5%93%81", "http://warbler.hatenablog.com/archive/category/%E5%81%A5%E5%BA%B7", "http://warbler.hatenablog.com/archive/category/%E3%83%9B%E3%83%A1%E3%82%AA%E3%83%91%E3%82%B7%E3%83%BC", "http://warbler.hatenablog.com/archive/category/%E6%8D%8F%E9%80%A0%E8%AB%96%E6%96%87", "http://warbler.hatenablog.com/archive/category/%E7%99%BA%E9%81%94%E9%9A%9C%E5%AE%B3", "http://warbler.hatenablog.com/archive/category/%E5%8C%BB%E7%99%82", "http://warbler.hatenablog.com/archive/category/%E9%9B%91%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E7%B5%B1%E8%A8%88", "http://warbler.hatenablog.com/archive/category/%E8%A6%AA%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E6%95%99%E8%82%B2", "http://blog.hatena.ne.jp/register?via=200227", "http://hatenablog.com/guide", "http://hatenablog.com/", "http://www.hatena.ne.jp/faq/report/blog?target_label=warbler&target_url=http://blog.hatena.ne.jp/go?blog=http%253A%252F%252Fwarbler.hatenablog.com%252Fentry%252F2018%252F01%252F24%252F011739&location=http://blog.hatena.ne.jp/go?blog=http%253A%252F%252Fwarbler.hatenablog.com%252Fentry%252F2018%252F01%252F24%252F011739"]

> meta.links.internal
=> ["http://warbler.hatenablog.com/entry/2018/01/24/011739", "http://warbler.hatenablog.com/", "http://warbler.hatenablog.com/archive/2018/01/24", "http://warbler.hatenablog.com/entry/2018/01/23/235522", "http://warbler.hatenablog.com/archive/2018/01/23", "http://warbler.hatenablog.com/entry/20150227/1425057866", "http://warbler.hatenablog.com/archive/2015/02/27", "http://warbler.hatenablog.com/archive/2013/09/03", "http://warbler.hatenablog.com/entry/20130903/1378217975", "http://warbler.hatenablog.com/entry/20130712/1373632961", "http://warbler.hatenablog.com/archive/2013/07/12", "http://warbler.hatenablog.com/entry/20130428/1367131822", "http://warbler.hatenablog.com/archive/2013/04/28", "http://warbler.hatenablog.com/about", "http://warbler.hatenablog.com/archive", "http://warbler.hatenablog.com/entry/2017/12/02/235126", "http://warbler.hatenablog.com/entry/2017/11/06/113739", "http://warbler.hatenablog.com/entry/2017/09/06/223001", "http://warbler.hatenablog.com/archive/category/EM%E9%96%A2%E4%BF%82", "http://warbler.hatenablog.com/archive/category/%E7%92%B0%E5%A2%83%E5%95%8F%E9%A1%8C", "http://warbler.hatenablog.com/archive/category/%E7%A7%91%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E7%92%B0%E5%A2%83", "http://warbler.hatenablog.com/archive/category/%E7%A0%94%E7%A9%B6%E4%B8%8D%E6%AD%A3", "http://warbler.hatenablog.com/archive/category/%E8%AA%A4%E3%81%A3%E3%81%9F%E7%B5%B1%E8%A8%88", "http://warbler.hatenablog.com/archive/category/%E3%83%8B%E3%82%BB%E7%A7%91%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E6%94%BE%E5%B0%84%E7%B7%9A", "http://warbler.hatenablog.com/archive/category/%E3%83%9E%E3%82%B9%E3%82%B3%E3%83%9F", "http://warbler.hatenablog.com/archive/category/%E5%B2%A1%E5%B1%B1%E5%A4%A7%E4%BA%8B%E4%BB%B6", "http://warbler.hatenablog.com/archive/category/%E6%9B%B8%E8%A9%95", "http://warbler.hatenablog.com/archive/category/%E9%A3%9F%E5%93%81", "http://warbler.hatenablog.com/archive/category/%E5%81%A5%E5%BA%B7", "http://warbler.hatenablog.com/archive/category/%E3%83%9B%E3%83%A1%E3%82%AA%E3%83%91%E3%82%B7%E3%83%BC", "http://warbler.hatenablog.com/archive/category/%E6%8D%8F%E9%80%A0%E8%AB%96%E6%96%87", "http://warbler.hatenablog.com/archive/category/%E7%99%BA%E9%81%94%E9%9A%9C%E5%AE%B3", "http://warbler.hatenablog.com/archive/category/%E5%8C%BB%E7%99%82", "http://warbler.hatenablog.com/archive/category/%E9%9B%91%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E7%B5%B1%E8%A8%88", "http://warbler.hatenablog.com/archive/category/%E8%A6%AA%E5%AD%A6", "http://warbler.hatenablog.com/archive/category/%E6%95%99%E8%82%B2"] 

使い方はgithubにサンプルが乗ってますので、是非ご覧ください。

github.com

まとめ

何か困った時は先ずは調べてみることで、簡単に実装できるgemがいっぱいあるのでRubyは楽しいですね。

今日は、そんな感じです。

【Rails】NokogiriじゃなくてMechanize gemで簡単スクレイピング!

先日Nokogiriを使ったWebスクレイピング方法を紹介しましたが、もっと簡単に出来るgemを見つけたのでご紹介。

opiyotan.hatenablog.com

その名はMechanize

利用する準備

gemのインストール

gem 'mechanize'
$ bundle install

スクレイピング先のサイト情報を取得

今回も「はてなブログ」を使ってやってみたいと思います。

先ずは「はてなブログ」の情報を取得します。

class Mechanize
  url = "http://hatenablog.com/"

  agent = Mechanize.new
  page = agent.get(url)
end

使い方

titleを取得する

  puts page.search('title’)
$ rails runner lib/mechanize.rb

<title>Hatena Blog</title>

タグの中身になるテキストを取得する

  title = page.search('title')

  title.each do |ti|
    puts ti.inner_text
  end
$ rails runner lib/mechanize.rb

Hatena Blog

aタグのリンクurlを取得する

classを指定したい時は、.hogehogeのように指定すればok!

  entry_a = page.search('a.serviceTop-entry-img-a')
  entry_a.each do |a|
    puts a.get_attribute(:href)
  end
.
.
.
  # こうしてもやってることは、同じ
  entry_a = page.search('div.serviceTop-entry > a')
$ rails runner lib/mechanize.rb
Running via Spring preloader in process 18370
http://moognyk.hateblo.jp/entry/2018/01/23/080000
http://blog.jnito.com/entry/2018/01/23/075856
http://barzam154.hatenablog.com/entry/2018/01/22/205222
http://ibaya.hatenablog.com/entry/2018/01/23/111105
http://bandaicandy.hateblo.jp/entry/build22
http://www.netlorechase.net/entry/2018/01/22/080000
http://www.hinata-family.com/entry/2018/01/23/064657
http://www.bitco-salaryman.com/entry/2018/01/22/194205
http://zoweb.hatenablog.com/entry/2018/01/22/093904
http://www.beikokukabu.xyz/entry/02
http://hobby-diary.hatenablog.com/entry/2018/01/19/204839
http://www.daij1n.info/entry/2018/01/18/021528
http://www.lean-style.com/entry/fashionfortune
http://www.kandosaori.com/entry/2018/01/16/171030
http://www.black-gamer.com/entry/KITTE_pancake
https://www.hotpepper.jp/mesitsu/entry/kinniku/18-00007
http://osyobu-osyobu-3889.hatenadiary.jp/entry/the_shutter_is_released14
http://www.hoshinokiiro.com/entry/20180122/recipe/tukurioki-and-hotcook
http://www.megamouth.info/entry/2017/01/19/053801
https://srdk.rakuten.jp/entry/2017/01/19/110000
http://mistclast.hatenablog.com/entry/2017/01/22/110637

該当する情報を1件だけ取得したい場合は、atを使います。

  puts page.at('div.serviceTop-entry > a').get_attribute(:href)
$ rails runner lib/mechanize.rb
Running via Spring preloader in process 19231
http://blog.jnito.com/entry/2018/01/23/075856

aタグのテキストとリンクを全部取得する

  entry_a = page.links
  entry_a.each do |a|
    puts a.text
    puts a.href
  end
$ rails runner lib/mechanize.rb

http://hatenablog.com/
雪の日のユキヒョウ&オオカミ:東京が大雪だったので多摩動物公園に行ってきた
http://moognyk.hateblo.jp/entry/2018/01/23/080000
I AM A DOG
http://moognyk.hateblo.jp/entry/2018/01/23/080000
かねてより念願だった、雪の日の動物園に行ってきましたよ! 雪の動物園がずっと見たかった 雪の降る動物園はいつもと違う景色が観られて楽しいだろうな… と思…
http://moognyk.hateblo.jp/entry/2018/01/23/080000
・
・
・

現在のURLを取得する

agent.page.uri.to_s

descriptionを取得する

こちらが苦戦中。metainspectorというgemを使えば取得できることは分かったのですが、上と同じような感じで取得することが出来ない。

  puts page.at(':og:description’)
  puts page.at('meta[:og:description]’)
  puts page.at('meta[property=:og:description]')
  puts page.at('meta[property=":og:description"]')
  puts page.at('meta[name=":og:description"]')

うーん。全部ダメ。どうすればいいのか解決できず..

metainspectorというgemについては、また紹介します。

まとめ

簡単にスクレイピング出来ることが分かりました。

データさえ取得できてしまえば、後はどのように使うかだけなので色々面白いことが出来そうですね。

今日はこんな感じです。

【Ruby】Nokogiriを使って「はてなブログ」をスクレイピングする!

こんばんは。エンジニアになれるか不安なopiyoです。

今日はWebサイトの情報を取得することが出来る、Webスクレイピングという技術をRubyでやってみます!

Webスクレイピングとは

Webサイトの情報を取得する技術ってイメージですが、wikipediaでちゃんと調べてみました。

ウェブスクレイピング(英: Web scraping)とは、ウェブサイトから情報を抽出するコンピュータソフトウェア技術のこと。ウェブ・クローラー[1]あるいはウェブ・スパイダー[2]とも呼ばれる。 通常このようなソフトウェアプログラムは低レベルのHTTPを実装することで、もしくはウェブブラウザを埋め込むことによって、WWWのコンテンツを取得する。

nokogiriのインストール

Gemfilenokogiriを記述します。

# Gemfile
gem 'nokogiri'

ターミナルで、いつも通りbundle installします

$ bundle install

スクレイピング実行するプログラム

class Scrape
  url = 'http://b.hatena.ne.jp/ctop/it'

  charset = nil

  opt = {}
  opt['User-Agent'] = "I Love Ruby"

  html = open(url, opt) do |f|
    charset = f.charset
    f.read
  end

  doc = Nokogiri::HTML.parse(html, nil, charset)
  doc.css('h1').each do |node|
    p node.text
    p node["href"]
  end
end

はまりポイント

503エラーが発生する事があるのだが、原因はUser-Agentが定義されていない。

$ rails runner lib/scrape.rb
Running via Spring preloader in process 14182
/Users/taku/.rbenv/versions/2.4.1/lib/ruby/2.4.0/open-uri.rb:363:in `open_http': 503 Service Temporarily Unavailable (OpenURI::HTTPError)

User-Agentってのは、そのアクセスした端末が何を使っているのかが定義されていてアプリ側では、この設定を見て「こいつはIEだ」とか「こいつはスマホだ」とか判断したりします。 例えばこんな感じ

  • Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
    • Mac OS X
    • Chrome

で、サイトによってはこのUser-Agentが定義されていないとエラーになってしまうらしいので、一緒に渡してやる。

スクレイピングしてみる

ここからが本題ですね。

データを取得する際に、どの情報を取得するのか定義してやります。

上のサンプルを例に幾つかやってみます。取得先は、はてなブックマークのテクノロジー一覧ページです。

はてなブログから「h1」に定義されているテキストを取得

  doc.css('h1').each do |node|
    p node
    p node.text
  end
$ rails runner lib/scrape.rb
#<Nokogiri::XML::Element:0x3fc3eed74b04 name="h1" children=[#<Nokogiri::XML::Element:0x3fc3eed74820 name="a" attributes=[#<Nokogiri::XML::Attr:0x3fc3eed747bc name="href" value="/">] children=[#<Nokogiri::XML::Element:0x3fc3eed74244 name="span" children=[#<Nokogiri::XML::Text:0x3fc3eed74064 "はてなブックマーク">]>]>]>
"はてなブックマーク"

はてなブログの各記事「h3」に定義されているテキストを取得(記事の一覧)

  doc.css('h3.hb-entry-link-container').each do |node|
    p node.text
  end
$ rails runner lib/scrape.rb
"コミュ力もリーダーシップもいらない。Googleが考える、本当に“優秀な人材“とは"
"Googleの画像認識APIを基に、好きな画像を学習させて認識機能を簡単にカスタ..."
"質問箱が暴露「4万人以上が自作自演」 ⇒ 反発を受けて実装した新機能とは?"
"最新版!Webページを作成する時のベースになる、最小限の構成で記述されたHT..."
"必見? Mozillaが提供しているユーザー環境週報がなにげに興味深い件につい..."
"Google ウェブマスター向け公式ブログ: ページの読み込み速度をモバイル検索..."
"はてなのアイコン設定したい"
"2月末に株式会社groovesを退職します - アジャイルSEの憂鬱"
"ネットでの誹謗中傷!書き込んだ人物を特定するための手順"
"\n      \n        Androidアーキテクチャことはじめ ― 選定する意味と、MVP、Clean Architecture、MVVM、Fluxの特徴を理解する - エンジニアHub|若手Webエンジニアのキャリアを考える!\n      \n    "
"\n      \n        フロントエンド開発に Babel も Webpack も必要ない ※ - KAYAC engineers' blog\n      \n    "
"\n      \n        Google ウェブマスター向け公式ブログ: ページの読み込み速度をモバイル検索のランキング要素に使用します\n      \n    "
"\n      \n        確率密度比推定まわりの書籍・解説記事・論文・ソフトウェアの各種情報まとめ - 備忘録\n      \n    "
"\n      \n        コード整形をStandardJSからPrettierに乗り換えたら捗った - 丁寧に手を抜く\n      \n    "
"\n      \n        大学を辞めたけど何も起こらなかった - 素人がプログラミングを勉強していたブログ\n      \n    "
"\n      \n        「ITをITで支援する」MSP事業者が、変革する開発・運用で果たす役割──スキルの価値が10年で消える世界においてエンジニアはどうあるべきか - GeekOut\n      \n    "
"\n      \n        プログラミングとUIデザインの境界、およびデザインの環境設定について – timakin – Medium\n      \n    "
"\n      \n        Golangでtestingことはじめ(1) - DeNA Testing Blog\n      \n    "
"\n      \n        ECS コンテナインスタンスをモニタリングするときは mackerel-agent v0.49.0 以上にすると良さそう - kakakakakku blog\n      \n    "
"\n      \n        IntelliJ IDEAで特定行のGitHub PRを開く\"Find Pull Request\" pluginがまじイノベーティブ - Islands in the byte stream\n      \n    "
"\n      \n        Perl で Compiler::CodeGenerator::LLVM を用いて LLVM IR を出力する - アルパカ三銃士\n      \n    "
"\n      \n        CodeStar で AWS Lambda + Golang の雛形をサクッと作成してみた - ソモサン\n      \n    "
"\n      \n        Kubernetes を利用したコンテナベース機械学習基盤の構築 - LIVESENSE Data Analytics Blog\n      \n    "
"\n      \n        Serverless Frameworkで静的サイトをBASIC認証付きでホスティングするためのボイラープレートを作った - Copy/Cut/Paste/Hatena\n      \n    "
"はてな、500 Startups Japanを通じたスタートアップ支援。サーバー監視サー..."
"Google、プログラミングができなくてもAIツールを作れる「AutoML」のα版提供..."
"「ITパスポート試験」83歳が合格 最年長記録更新 - ITmedia NEWS"
"ドミノ・ピザ、「20分保証」の宅配サービス (ITmedia ビジネスオンライン)..."
"AWS最先進ユーザーNetflix - 「サル軍団」にシステム障害を起こさせる、Netflixの驚異的なトラブル撲滅..."
"CPUの脆弱性対策パッチでSSDのランダムアクセスが大幅減速?影響をチェックしてみた - AKIBA PC Hotline!"
"word2vec(Skip-Gram Model)の仕組みを恐らく日本一簡潔にまとめてみたつもり - これで無理なら諦めて..."
"Microsoft 、VRを用いて実在する建物内で起こる災害を実際のスケールで走り..."
"Nintendo Switchを使ってロボットや楽器コントローラーなど様々なものを作れ..."
"任天堂、Switchと合体する“段ボールコントローラー”「Nintendo Labo」発売..."
"首元にのせるだけで周囲360度のパノラマムービー撮影が可能なウェアラブルカ..."
"15.5型ノート「VAIO S15」に追加モデル 店頭向けエントリー構成、新色のピ..."
"第8世代Coreと13.3型IGZO液晶を備えたスリムノート「Razer Blade Stealth」..."
"日本参入か? 中国OPPOが日本語Twitterアカウントを開設 - ITmedia Mobile"
"iPhoneでも使えるOfficeの手書き プレゼンにも便利 - 日経トレンディネット"

はてなブログの各記事「h3」に定義されているリンクURL

  doc.css('h3.hb-entry-link-container > a').each do |node|
    p node["href"]
  end
$ rails runner lib/scrape.rb
"http://www.huffingtonpost.jp/2018/01/16/piotr_a_23334437/"
"http://www.publickey1.jp/blog/18/googleapicloud_automl_vision.html"
"http://www.huffingtonpost.jp/2018/01/17/peing_a_23335512/"
"http://coliss.com/articles/build-websites/operation/work/html5-template-for-2018.html"
"https://forest.watch.impress.co.jp/docs/serial/yajiuma/1101696.html"
"https://webmaster-ja.googleblog.com/2018/01/using-page-speed-in-mobile-search.html"
"https://anond.hatelabo.jp/20180118015611"
"http://sinsoku.hatenablog.com/entry/2018/01/18/144408"
"https://sakuya-shougainenkin.com/slander"
"https://employment.en-japan.com/engineerhub/entry/2018/01/17/110000"
"http://techblog.kayac.com/pure-js-app"
"https://webmaster-ja.googleblog.com/2018/01/using-page-speed-in-mobile-search.html"
"http://tam5917.hatenablog.com/entry/2018/01/16/233057"
"http://craftzdog.hateblo.jp/entry/prettier-is-good"
"http://javascripter.hatenablog.com/entry/2018/01/18/033738"
"https://geek-out.jp/column/entry/2018/01/18/110000"
"https://medium.com/@timakin/3ee839874d19"
"http://swet.dena.com/entry/2018/01/16/211035"
"http://kakakakakku.hatenablog.com/entry/2018/01/17/124717"
"http://gfx.hatenablog.com/entry/2018/01/17/133457"
"http://codehex.hateblo.jp/entry/2018/01/16/221634"
"http://rohki.hatenablog.com/entry/2018/01/16/211941"
"http://analytics.livesense.co.jp/entry/2018/01/18/090000"
"http://k1low.hatenablog.com/entry/2018/01/18/085843"
"http://hatenacorp.jp/press/release/entry/2018/01/18/153000"
"http://www.itmedia.co.jp/news/articles/1801/18/news096.html"
"http://www.itmedia.co.jp/news/articles/1801/18/news090.html"
"https://headlines.yahoo.co.jp/hl?a=20180118-00000066-zdn_mkt-bus_all"
"http://itpro.nikkeibp.co.jp/atcl/column/17/122800596/010500003/"
"https://akiba-pc.watch.impress.co.jp/docs/sp/1101498.html"
"http://www.randpy.tokyo/entry/word2vec_skip_gram_model"
"https://kadenkaigi.com/entry/354850025"
"https://kadenkaigi.com/entry/354832865"
"https://kadenkaigi.com/entry/354831021"
"https://kadenkaigi.com/entry/354829845"
"https://kadenkaigi.com/entry/354862221"
"https://kadenkaigi.com/entry/354859010"
"https://kadenkaigi.com/entry/354858999"
"https://kadenkaigi.com/entry/354822870"

まとめ

やばい。楽しくなってきた。

cssを定義するように書けるので非常に非常に分かりやすいし簡単ですね。

スクレイピングを使うと色々な情報を取得することが出来るので、非常に便利ですね。

が、便利な反面迷惑かけてしまうことも当然ありますので、しっかりルールを守って使っていきたいですね。

と記事を書き終えた所で、なんとスクレイピング用のgemがあるらしい。これは、また別の機会で…くそう。

【Ruby on Rails】決まった時間に自動で処理してくれる`whenever`の使い方!

こんばんは。早くエンジニアになりたいopiyoです。

以前rssを取得する方法について、まとめて見たのですが今日はそれの発展させたいと思います。 opiyotan.hatenablog.com

時代は変わる。そして情報も常に変わる。

だから、rss情報も常に最新の情報を自動で取得したいですよね。

そんな時に便利なのが自動で決まった時間に処理をしてくれるwheneverというgemです。

  • 毎日2時間毎にrss情報を取得する!
  • 毎日朝3時にDBのバックアップを取得する!

みたいな事が出来ちゃう訳ですね。

wheneverの導入

先ずは、wheneverという定期実行するためのgemをインストールします。

# Gemfile
gem 'whenever', :require => false

そして、魔法のbundle install

$ bundle install

次にやるのが、wheneverの設定を記述するファイルを作成します。 これはコマンドが用意されています。

$ bundle exec wheneverize .
[add] writing `./config/schedule.rb'
[done] wheneverized!

すると、schedule.rbというファイルが出来上がります!

# config/schedule.rb
# Use this file to easily define all of your cron jobs.
# 
# It's helpful, but not entirely necessary to understand cron before proceeding.
# http://en.wikipedia.org/wiki/Cron
# 
# Example:
# 
# set :output, "/path/to/my/cron_log.log"
# 
# every 2.hours do
#   command "/usr/bin/some_great_command"
#   runner "MyModel.some_method"
#   rake "some:great:rake:task"
# end
# 
# every 4.days do
#   runner "AnotherModel.prune_old_records"
# end
# 
# Learn more: http://github.com/javan/whenever

ここに定期実行する為の処理を書いていきますよー

schedule.rbの書き方

今回は、動作確認までしたいので1分毎にHelloWorldを出力するrakeタスクを呼び出す処理を設定します。

# config/schedule.rb
# cronログを吐き出す場所
set :output, File.join(Whenever.path, "log", "cron.log")
# ジョブの実行環境の指定
set :environment, :development

# 1分毎に`HelloWorld`を出力する
every 1.minutes do
  begin
    rake "rss:hello"
  rescue => e
    raise e
  end
end
# lib/tasks/rss.rake
namespace :rss do
  task :hello => :environment do
    rss_hello = RssImport.new
    rss_hello.hello
  end
end
# lib/rss_import.rb
class RssImport
  def hello
    puts "HelloWorld"
  end
end

これで準備は完了です!

wheneverを実行する

先ずは、設定ファイルの記述にミスが無いかどうかチェック!

エラーになる

$ bundle exec whenever
bundler: failed to load command: whenever (/Users/taku/.rbenv/versions/2.4.1/bin/whenever)
NameError: undefined local variable or method `import' for #<Whenever::JobList:0x007fb7fba35330>

こんなエラーが出た時は、設定ファイルをもう一度見直してください。 私はrakeタスクを定義する場所を""で囲っていなかったので最初ずっとエラーになってました。

他の問題としては、rakeタスクを設定しているファイルが読めていない可能性があるのでschedule.rbの最初にrequire "/path/to/config/environment.rb"を定義してみてください。

成功する

成功すると、こんなメッセージが表示されます。

$ bundle exec whenever
* * * * * /bin/bash -l -c 'cd /Users/taku/rails/mapachannel && RAILS_ENV=development bundle exec rake rss:hello --silent >> /Users/taku/rails/mapachannel/log/cron.log 2>&1’

## [message] Above is your schedule file converted to cron syntax; your crontab file was not updated.
## [message] Run `whenever --help' for more options.

ここまで来たら実際に、これをcrontabというXXに登録してあげます!

$ bundle exec whenever --update-crontab
[write] crontab file updated

正しく設定されているかどうかは、crontab -lコマンドでチェック出来ます!

$ crontab -l

# Begin Whenever generated tasks for: /Users/taku/rails/mapachannel/config/schedule.rb at: 2018-01-18 14:21:42 +0900
* * * * * /bin/bash -l -c 'cd /Users/taku/rails/mapachannel && RAILS_ENV=development bundle exec rake rss:hello --silent >> /Users/taku/rails/mapachannel/log/cron.log 2>&1'

# End Whenever generated tasks for: /Users/taku/rails/mapachannel/config/schedule.rb at: 2018-01-18 14:21:42 +0900

なんかどのサイトを確認方法はcrontab -eって書かれてるのだけど、-eにするとviが開くから良くないと思うのだけど。 間違えて-eしてしまった場合は慌てずに、esc + :q!で閉じれます!

間違えて設定してしまった場合は、これで

$ bundle exec whenever --clear-crontab

定期実行されているかチェック

最後に1分間毎にHelloWorldが呼ばれているかチェックします。

logを見て見ましょう!

$ tail -f log/cron.log
HelloWorld
・
・
・

tail -fとするとリアルタイムにログを見る事が出来ます。 1分間毎にHelloWorldが増えて表示されれば成功してますね。

【Bootstrap】ナビゲーションメニューをセンタリングして均等化する方法!

こんばんは。opiyoです。

よくあるナビゲーションメニューですが、センタリングされてないとダサいですよね。

bootstrapnavのサンプルを、そのままコピペして試してみたのですが

  • センタリングされない
  • 文字数に応じた領域になってしまいかっちょ悪い

って状況だったので、色々試してみました。

サンプルそのまま

    <nav class="navbar navbar-default">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbarEexample1">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">タイトル</a>
            </div>

            <div class="collapse navbar-collapse" id="navbarEexample1">
                <ul class="nav navbar-nav">
                    <li><a href="#">メニューAAAAAAAAAAAaaaaa</a></li>
                    <li class="active"><a href="#">メニューB</a></li>
                    <li><a href="#">メニューCCc</a></li>
                </ul>
            </div>
        </div>
    </nav>

出来上がったサンプルがこちら↓↓

f:id:opiyotan:20180117171913p:plain

解決方法

センタリングして均等化させたかったので調べてみるとnav-justifiedを書けばいいってあったのでやってみたのだが上手くいかぬ。

色々と悩んでいたのだが、navにこだわる必要あるか?ってなったのでbtn-groupで囲ってるやる作戦に変更したらすんなり上手くいった。

    <div class="btn-group btn-group-justified btn-group-lg">
      <%= link_to root_path, class: "btn btn-default" do %>
        <%= fa_icon("commenting comment-info", text: "人気") %>
      <% end %>
      <%= link_to root_path, class: "btn btn-default" do %>
        <%= fa_icon("commenting comment-info", text: "新着") %>
      <% end %>
      <%= link_to root_path, class: "btn btn-default" do %>
        <%= fa_icon("commenting comment-info", text: "見つける") %>
      <% end %>
      <%= link_to root_path, class: "btn btn-default" do %>
        <%= fa_icon("commenting comment-info", text: "サイトについて") %>
      <% end %>
    </div>

↓html展開すると

<div class="btn-group btn-group-justified btn-group-lg">
      <a class="btn btn-default" href="/">
        <i class="fa fa-commenting fa-comment-info"></i> 人気
      </a>
      <a class="btn btn-default" href="/">
        <i class="fa fa-commenting fa-comment-info"></i> 新着
      </a>
      <a class="btn btn-default" href="/">
        <i class="fa fa-commenting fa-comment-info"></i> 見つける
      </a>
      <a class="btn btn-default" href="/">
        <i class="fa fa-commenting fa-comment-info"></i> サイトについて
      </a>    
</div>

出来上がったサンプルがこちら↓↓ f:id:opiyotan:20180117171900p:plain

こんな感じ。 画面の領域狭めてもきちんとレスポンシブになってるぞい。

navについては、こちらのサイトにいっぱいサンプルある。やっほいー

http://bootstrap3.cyberlab.info/components/navbar.html

※「bootstrap nav」とかで調べて最初に出てくるページはbootstrap4だから注意。全然違うのよ。

まとめ

僕の場合はデザインが、ある程度見栄え良くないと作る気がどんどん失せていくので、こういうのがサラッと出来るって大事だなーと思う。

【Ruby on Rails】Rakeタスクを使えば様々な処理が自動化出来る?(初心者向け)

今日は様々な場面で活躍するrakeタスクの作り方と実行方法をまとめてみます。

Rakeとは

そもそもRakeですが、Rubyで書かれたコードをタスクとして作成しておき必要に応じて呼び出し実行する事が出来る機能です。

rakeタスクを利用する場面としては、こんなのが有ります。

  • 何かしらのデータの連携
  • データベースのバックアップ
  • 定期的にデータを更新、削除する

Rakeタスクの作り方

今回は、Hello Worldとコンソール上に表示するrakeタスクを作成してみます!

rakeファイル

# lib/tasks/herro.rake
namespace :hello do
  task :world => :environment do
    hw = HelloWorld.new
    puts hw.hoge
  end
end

大事なのが、namespacetaskで定義した名称です。ここがrakeタスクを実行する時に使います。

:environmentっていうのは、とりあえずおまじないだと理解してます。

タスクを実行するクラスファイル

# lib/hello_world.rb
class HelloWorld
  def hoge
   "Hello World"
  end
end

こちらは単純なクラスファイルです。hogeメソッドが呼ばれるとHello Worldを返すだけのクラスです。

注意点としては、ファイル名とクラス名は合わせて下さい。

オートロード対象となるパスの追加

ここハマりポイントです。私は30分ほど悩んでも分からず教えてもらいました。

タスクを実行するファイルをlib/配下に置きましたが、設定を変更しないとrailsの世界から見えないだそうです。

# config/application.rb
config.autoload_paths += %W(#{config.root}/lib)

Rakeタスクの実行方法

$ rake hello:world
Hello World

Rakeタスクの確認方法

定義されているrakeタスクの一覧を表示するコマンドがあるみたいです。

$ rake --tasks
rake about                              # List versions of all Rails frameworks and the environment
rake app:template                       # Applies the template supplied by LOCATION=(/path/to/template) or URL
rake app:update                         # Update configs and some other initially generated files (or use just update:configs or update:bin)
rake assets:clean[keep]                 # Remove old compiled assets
rake assets:clobber                     # Remove compiled assets
rake assets:environment                 # Load asset compile environment
rake assets:precompile                  # Compile all the assets named in config.assets.precompile
rake cache_digests:dependencies         # Lookup first-level dependencies for TEMPLATE (like messages/show or comments/_comment.html)
rake cache_digests:nested_dependencies  # Lookup nested dependencies for TEMPLATE (like messages/show or comments/_comment.html)
rake db:create                          # Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to creating ...
rake db:drop                            # Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to dropping the de...
rake db:environment:set                 # Set the environment value for the database
rake db:fixtures:load                   # Loads fixtures into the current environment's database
rake db:migrate                         # Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)
rake db:migrate:status                  # Display status of migrations
rake db:rollback                        # Rolls the schema back to the previous version (specify steps w/ STEP=n)
rake db:schema:cache:clear              # Clears a db/schema_cache.dump file
rake db:schema:cache:dump               # Creates a db/schema_cache.dump file
rake db:schema:dump                     # Creates a db/schema.rb file that is portable against any DB supported by Active Record
rake db:schema:load                     # Loads a schema.rb file into the database
rake db:seed                            # Loads the seed data from db/seeds.rb
rake db:setup                           # Creates the database, loads the schema, and initializes with the seed data (use db:reset to also drop the database first)
rake db:structure:dump                  # Dumps the database structure to db/structure.sql
rake db:structure:load                  # Recreates the databases from the structure.sql file
rake db:version                         # Retrieves the current schema version number
rake dev:cache                          # Toggle development mode caching on/off
rake initializers                       # Print out all defined initializers in the order they are invoked by Rails
rake log:clear                          # Truncates all/specified *.log files in log/ to zero bytes (specify which logs with LOGS=test,development)
rake middleware                         # Prints out your Rack middleware stack
rake notes                              # Enumerate all annotations (use notes:optimize, :fixme, :todo for focus)
rake notes:custom                       # Enumerate a custom annotation, specify with ANNOTATION=CUSTOM
rake restart                            # Restart app by touching tmp/restart.txt
rake routes                             # Print out all defined routes in match order, with names
rake secret                             # Generate a cryptographically secure secret key (this is typically used to generate a secret for cookie sessions)
rake stats                              # Report code statistics (KLOCs, etc) from the application or engine
rake time:zones[country_or_offset]      # List all time zones, list by two-letter country code (`rails time:zones[US]`), or list by UTC offset (`rails time:zones[-8]`)
rake tmp:clear                          # Clear cache and socket files from tmp/ (narrow w/ tmp:cache:clear, tmp:sockets:clear)
rake tmp:create                         # Creates tmp directories for cache, sockets, and pids

まとめ

rakeタスクを使うことで様々な処理を作成しておけば色々な場面で何度も使う事が出来るので非常に便利ですし、業務でも良く利用します。

また、これと合わせて定期実行の仕組みを入れて上げると「毎日4時にDBバックアップを行う」などが出来るようになります!

今日はこんな感じです。

【Ruby】rssを取得して簡単にまとめサイトが作っちゃおう!

こんばんは。早くエンジニアになりたいopiyoです。

最近は会社で全くコードを書くことが出来ず、焦りまくっていう日々を歩んでいるのですが自分で少しでもコードを書く時間を作ろうと思ってRailsアプリを作っています。

その中でトレンド情報を取得して表示したいなーなんて思っていたのですが、Googleもyahooも今は提供してないみたい。 でも何かしら情報を取得できる術はないかなーと色々調べていたところ、rssの情報を取得することは何だか出来そうってことが分かったのでコードを書いてみました。

rss情報を取得できれば、簡単にまとめサイトとか作れちゃいそうでワクワクしちゃいますよね。

今回はGoogleキーワードを使ってrss情報を取得するってのをやろうと思います。

Googleキーワード

Googleキーワードってのは情報取得したいキーワードを設定しておき、メールかrssで最新情報を取得出来ちゃうっていう優れものですね。

f:id:opiyotan:20180115193947p:plain

使い方は簡単で、Googleキーワードのサイトに行って取得したいキーワードと各種設定をするだけ。

画像の例だと今大流行中の「仮想通貨」のキーワードで引っかかった最新情報が常に取得できます。 これを上手く使えば仮想通貨のまとめサイトみたいなものも簡単に作れるかもしれませんね。

作成するとrssのアイコンが表示されるので、それをクリックしてURLをメモしておいてください。

Rubyのコード

rssから情報を取得してターミナル上にタイトルを表示させてみます。

require 'feedjira'

sites = [
  "https://www.google.co.jp/alerts/feeds/17514568391276082754/11140714952475134210"
]

@list = []
sites.each do |site|
  rss = Feedjira::Feed.fetch_and_parse site
  rss.entries.each do |item|
    @list += [
      :id => item.id,
      :title => item.title
    ]
  end
end

puts @list

feedjiraというgemを使ってます。 Feedjira::Feed.fetch_and_parseこの辺りが肝で色々な情報を取得できそうなので、色々試してみたいと思います。

他の部分は取得したデータをグルグル回して情報を取得して@listに突っ込んで表示されているだけです。

めちゃくちゃ簡単。

この他の項目に取得したサイトURLが取得できるので、これを使って一覧化させればまとめサイトが出来ちゃうかも?

実行方法

実行方法はgemをインストールして、rubyを付けて実行するだけ。

$ gem install feedjira
$ ruby rss-saple.rb
W, [2018-01-15T19:43:47.599363 #10005]  WARN -- Feedjira: Failed to parse last modified ''
{:id=>"tag:google.com,2013:googlealerts/feed:954412367556280749", :title=>"<b>仮想通貨</b>イーサリアム、2018年は時価総額を3倍に拡大か"}
{:id=>"tag:google.com,2013:googlealerts/feed:2024205748243453586", :title=>"【市況】ブラジル、ファンドによる<b>仮想通貨</b>投資を規制【フィスコ・ビットコインニュース】"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"<b>仮想通貨</b>の詐欺で「テクノロジー批判」し炎上 「いや、人間の悪意のせい」"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"Oracle WebLogic Serverに脆弱性攻撃--<b>仮想通貨</b>の発掘を狙う"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"【市況】<b>仮想通貨</b>取引所クラーケン、稼働停止から復旧【フィスコ・ビットコインニュース】"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"インドネシアが中国、韓国に次いで<b>仮想通貨</b>取引禁止の最終段階に"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"最大級のQ&amp;Aサイト「OKWAVE」を運営するオウケイウェイヴ、<b>仮想通貨</b>交換業の登録申請を行うことを決定"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"韓国、<b>仮想通貨</b>の匿名取引に罰金科す方針【フィスコ・ビットコインニュース】"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"個人投資家株師孔明:メルカリが<b>仮想通貨</b>ビジネスに参入か?【FISCOソーシャルレポーター】"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"ウクライナ、政府や中央銀行からなる<b>仮想通貨</b>規制グループを結成"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"Oracle WebLogic Server の脆弱性(CVE-2017-10271)を悪用する攻撃事例について"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"<b>仮想通貨</b>『Centrality(セントラリティ) トークン名:CENNZ(センズ)』のICOが6分で完売!"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"【社会】政府「<b>仮想通貨</b>実名制を滞りなく推進…ブロックチェーン育成」"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"2018年のデジタルアセットのトレンド予測。キーワードは「相互運用性」"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"コラム:ビットコイン、「リアルマネー」に絶対ならない訳"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"収益不動産売買に<b>仮想通貨</b>NEW"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"韓国が<b>仮想通貨</b>取引を禁止へ、大手取引所捜査に市場が動揺"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"インドネシア中銀が<b>仮想通貨</b>売買を行わないよう国民に呼びかけ"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"2017年の<b>仮想通貨</b>のパフォーマンスランキングが発表される。1位はRipple"}
{:id=>"tag:google.com,2013:googlealerts/feed:111", :title=>"【期間限定】長期インターンサイトInfrAに登録すると抽選でビットコインをプレゼント"}

rssの情報

取得したrss情報はこんな感じ

<feed xmlns="http://www.w3.org/2005/Atom" xmlns:idx="urn:atom-extension:indexing">
<id>
tag:google.com,2005:reader/user/17514568391276082754/state/com.google/alerts/11140714952475134210
</id>
<title>Google アラート - 仮想通貨</title>
<link href="https://www.google.com/alerts/feeds/17514568391276082754/11140714952475134210" rel="self"/>
<updated>2018-01-15T09:45:00Z</updated>
<entry>
<id>
tag:google.com,2013:googlealerts/feed:954412367556280749
</id>
<title type="html"><b>仮想通貨</b>イーサリアム、2018年は時価総額を3倍に拡大か</title>
<link href="https://www.google.com/url?rct=j&sa=t&url=http://hedge.guide/news/ethereum-2018.html&ct=ga&cd=CAIyHGM1ZjhiY2MyYmY4NTIxMmU6Y28uanA6amE6SlA&usg=AFQjCNH4fLhHDJ0OwroDbbn7kJ6iMyjgEQ"/>
<published>2018-01-15T09:45:00Z</published>
<updated>2018-01-15T09:45:00Z</updated>
<content type="html">
<b>仮想通貨</b>イーサリアムの共同開発者Steven Nerayoff氏は、8日のCNBCのインタビューで、<b>仮想通貨</b>市場全体の市場拡大に伴って、今年はイーサリアムの時価総額を現在の3倍に増幅させると述べた。 イーサリアムは、ビットコインに次ぐ市場規模を持つ<b>仮想通貨</b>だ。<b>仮想通貨</b>取引の契約を自動的に実行し、取引内容を&nbsp;...
</content>
<author>
<name/>
</author>
</entry>
<entry>
<id>
tag:google.com,2013:googlealerts/feed:2024205748243453586
</id>
<title type="html">【市況】ブラジル、ファンドによる<b>仮想通貨</b>投資を規制【フィスコ・ビットコインニュース】</title>
<link href="https://www.google.com/url?rct=j&sa=t&url=https://kabutan.jp/news/marketnews/%3Fb%3Dn201801150658&ct=ga&cd=CAIyHGM1ZjhiY2MyYmY4NTIxMmU6Y28uanA6amE6SlA&usg=AFQjCNGyvJMQq3YiEWr93lA0gM354A-FPA"/>
<published>2018-01-15T09:45:00Z</published>
<updated>2018-01-15T09:45:00Z</updated>
<content type="html">
ブラジル証券取引委員会(CVM)は、<b>仮想通貨</b>を金融資産として認めないと定めたほか、海外のファンドへの出資を通した<b>仮想通貨</b>への投資についても、CVMの方針確定を待つことも併せて定め ... ブラジル証券取引委員会(CVM)とブラジル中央銀行は、12月に<b>仮想通貨</b>に関連するリスクを警告する共同声明を発表していた。
</content>
<author>
<name/>
</author>
</entry>

まとめ

分かっちゃえば、めちゃくちゃ簡単。

アイデア次第ですげーのが作れるかも。なんてね。

【PostgreSQL】Dockerで作ったDBにcsvファイルを参照したcopyコマンドを実行するには?(\copy)

コンテナチェック

$ docker ps

コンテナログイン

$ docker exec -it NAME /bin/bash

コンテナへファイルをコピー

$ docker cp ~/hoge.csv NAME:/tmp/

PostgreSQLにログイン

$ psql hoge -p5432

copyコマンドのファイルパスをコンテナ側に合わせ実行

COPY shop_sales (sales_date,shop_id,shop_name) from '/hoge.csv' with csv;

ってのをバカみたいにやっていたのですが、本番環境のRDSだと実行出来なくね?ってなり再調査。

\copyってコマンドを使うみたい。 こうするとローカルのパスでも参照してくれるみたい!

\COPY shop_sales (sales_date,shop_id,shop_name) from '/Users/taku/hoge.csv' with csv;

参考にさせていただきました。ありがとうございます。 https://qiita.com/egg_chicken/items/cec72bda3759f875285f