某大学生のらくがきのーと

大学三回生です。調べた事をまとめたり、日記も書くかもしれません。

scrapyでmysql入れたデータをlogstashを用いてElasticsearchと同期

まずは必要なものをインストール

使用したものはこんな感じです.

  • pyenv
  • python3.6.2
  • MySQL
    • mysqlclient
    • scrapy
  • Elasticsearch
  • Kibana
  • logstash

pyenvを使ってscrapyを使用するための環境を作成するのは過去の記事でやりました.

python導入&scrapy環境構築 - 某大学生のらくがきのーと


今回は実際にscrapyを使用してgunosyニュースを取得し,最終的にはElasticsearchにデータを突っ込んだ手順を追っていきたいと思います.

Scrapyを使用してクローリングし,MySQLにデータを入れるまで

まずはMySQLと,pythonMySQLを操作するために必要なmysqlclientをダウンロードします.

MySQL.

$ brew update
$ brew install mysql
$ brew info mysql 

mysqlclientをインストールするpyenvの環境のディレクトリで下記を実行.

$ pip install mysqlclient

とりあえずこれでMySQLにデータを入れるのに必要なものは揃いました.
pythonを使ってプログラムを書いていきます.
pyenvで開発環境を整えたディレクトリでプロジェクトを作成し,treeコマンドで確認します.

$ scrapy startproject gunosy
$ cd gunosy
$ scrapy genspider gunosy_spider gunosy.com
$ tree

.
├── gunosy
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   └── settings.cpython-36.pyc
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── settings.py
│   └── spiders
│       ├── __init__.py
│       ├── __pycache__
│       │   └── __init__.cpython-36.pyc
│       └── gunosy_spider.py
└── scrapy.cfg

まずはitems.pyとsettings.pyを編集します.
特にsettings.pyでダウンロード間隔を設定しないとサイトに迷惑がかかってしまうので必ずしましょう.

#items.py
import scrapy
class GunosyItem(scrapy.Item):
    url = scrapy.Field()
    タイトル = scrapy.Field()
    元記事サイト名 = scrapy.Field()
    更新日 = scrapy.Field()
    取得日時 = scrapy.Field()
#settigs.py
DOWNLOAD_DELAY = 3 #コメント化されてるのでコメントを外す.

ここまでできたら次は実際にspiderのコードを書いていきます.書き方は様々でしょうが,私は下記を参考にこのように書きました.
Python3でMySQLを使う – 基本操作からエラー処理までサンプルコード付 | Crane & to.

#gunosy_spider.py

#必要なものをインポート
import scrapy
from gunosy.items import GunosyItem
import datetime
import MySQLdb
import atexit #終了時に接続を切るのに使用

#データベース接続とカーソル作成.
connection = MySQLdb.connect(
    host='localhost', user='root', passwd='*****', db='sample_db', charset='utf8')
cursor = connection.cursor()
cursor.execute("DROP TABLE IF EXISTS `gunosy_data`")

class GunosySpiderSpider(scrapy.Spider):
    name = 'gunosy_spider'
    allowed_domains = ['gunosy.com']
    start_urls = ['https://gunosy.com/categories/14']

    def parse(self, response):
        #詳細ページをパルス
        for href in response.xpath('//div[@class="list_title"]/a/@href'):
            yield response.follow(href, self.parseItem)

        #次のページをパルス
        for href in response.xpath('//div[@class="pager-link-option"]/a/@href'):
            yield response.follow(href, self.parse)

    #詳細ページの処理
    def parseItem(self, response):
        item = GunosyItem()
        item['url'] = response.url
        item['タイトル'] = response.xpath('//h1[@class="article_header_title"]/text()').extract_first()
        item['元記事サイト名'] = response.xpath('//ul[@class="article_header_lead"]/li[@class="article_header_lead_by"]/text()').extract_first()
        item['更新日'] = response.xpath('//ul[@class="article_header_lead"]/li[@class="article_header_lead_date"]/@content').extract_first()
        item['取得日時'] = datetime.datetime.utcnow() + datetime.timedelta(hours=9)

        # エラー処理
        try:
            # CREATE
            cursor.execute("""CREATE TABLE IF NOT EXISTS `gunosy_data` (
            `id` int(11) NOT NULL auto_increment primary key,
            `url` text not null,
            `タイトル` text  NOT NULL,
            `元記事サイト名` text,
            `更新日` text,
            `取得日時` datetime
          ) """)

            # INSERT
            cursor.execute(
            "INSERT INTO gunosy_data (url, タイトル, 元記事サイト名, 更新日,取得日時)"
            "VALUES (%s, %s, %s, %s, %s)",
            (item['url'], item['タイトル'], item['元記事サイト名'], item['更新日'], item['取得日時']))

        except MySQLdb.Error as e:
            print('MySQLdb.Error: ', e)

        yield item

    #プログラム終了時に呼び出され,接続を閉じるメソッド.
    def endMethod():
        print ('\n\n\n\nFINISHED\n\n\n')
        # 保存を実行(忘れると保存されないので注意)
        connection.commit()
        # 接続を閉じる
        connection.close()

    atexit.register(endMethod)

これをmysqlで確認してみるとちゃんとデータが入っていました.

MySQLのデータをElasticsearchに突っ込む

次はMySQLに入れたデータをlogstashを用いてElasticsearchに入れていきます.
まずは必要なElastichsearch,Kibana,logstashをインストールします.
Download Elasticsearch Free • Get Started Now | Elastic
Download Kibana Free • Get Started Now | Elastic
Download Logstash Free • Get Started Now | Elastic

インストールしたら,logstashの設定ファイルを書きます.書いたのですが,正直詳しいことはまだ理解していません.; ;
とりあえずこのように書いて,ファイル名はgunosy.confにしてlogstashディレクトリに置きます.

input {
  jdbc {
    jdbc_driver_library => "mysql-connector-java-5.1.44/mysql-connector-java-5.1.44-bin.jar"
    jdbc_driver_class => "com.mysql.jdbc.Driver"
    jdbc_connection_string => "jdbc:mysql://localhost:3306/sample_db"
    jdbc_user => "root"
    jdbc_password => "dnt2626h8"
    statement => "SELECT * FROM gunosy_data"
    type => "gunosy"
    use_column_value => true
    tracking_column => "id"
    tracking_column_type => "numeric"
    clean_run => true
  }
}
filter {
}
output {
    elasticsearch {
      index => "gunosy_index"
      hosts => ["localhost:9200"]
      document_id => "%{id}"
      document_type => "gunosy_type"
  }
  stdout {codec => rubydebug {metadata => true }}
}

そしてそれぞれ起動します.
elasricsearchディレクトリで下記を実行

$ bin/elasticsearch

kibanaディレクトリで下記を実行

$ bin/kibana

logstashディレクトリで下記を実行

$ bin/logstash -f gunosy.conf 

データが入っているか確認.
kibanaでdev toolsで確認してみます.
ブラウザでhttp://localhost:5601/にアクセスしてDev Toolsで下記を実行

GET gunosy_index/_search
{
  "query": {"match_all": {} },
  "size": 30,
  "sort": [
    {
      "id": {
        "order": "asc"
      }
    }
  ]
}

これでElasticsearchにデータが入ったこともわかると思います.

elasticsearch-headを使って確認するのも便利かもしれません.

これからやること

logstashの設定がいまいちよくわかってないので,スケジューリングとか,そこらへんを色々やってみたいと思います.

python導入&scrapy環境構築

pythonの導入,scrapyを使用するための環境構築などをまとめます.

まず,このサイトを参考にpythonを入れました.
qiita.com

最初に,Pythonのバージョン管理や,仮想環境を構築できるpyenvを入れました.
仮想環境を使えると,この環境では◯◯のパッケージが使えて,こっちでは△△が使えて,みたいな住み分けができて便利みたいです.システムに直接ダウンロードしちゃうと干渉が起きたりした時に対処が大変なんですかね.

このサイトにも,scrapyを使う場合,仮想環境を使うことが推奨されていました.
インストールガイド — Scrapy 1.2.2 ドキュメント
後ほど詳述しますが,このサイトではvirtualenvを用いていますが,私はpyenv-virtualenvを使用しました.(名前がややこしいですがこの二つは別物みたいです)


それでは,実際にやった手順を追っていきたいと思います.
まず,pyenvをインストール.

$ brew install pyenv

私の環境ではzshを使っているので,
.zshrcに下記を追加.

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

追記したのちにリフレッシュ

$ source .zshrc

インストール可能なpythonの一覧をコマンドで確認.

$ pyenv install -l 

実行した時に最新のバージョン(3.6.2)をインストールしました.

$ pyenv install 3.6.2

インストールされたバージョンを確認

$ pyenv versions                                                                                              
* system (set by /Users/****/.pyenv/version)
  3.6.2

アクティブにするバージョンを選択.

$ pyenv global 3.6.2

確認してみると,

$ pyenv versions
  system
* 3.6.2 (set by /Users/****/.pyenv/version)

pythonを正しくインストールできたか確認.

$ which python
/Users/****/.pyenv/shims/python

ここまでで,とりあえずpythonのインストールをすることができました.次は仮想環境を構築するためのpyenv-virtualenvを入れていきたいと思います.
このサイトを参考にさせていただきました.
qiita.com

pyenv-virtualenvのインストール

$ brew install pyenv-virtualenv

インストール終了後,.zshrcを書き換え.(先ほど追記した部分を書き換えました.)

## Set path for pyenv
export PYENV_ROOT="${HOME}/.pyenv"
if [ -d "${PYENV_ROOT}" ]; then
    export PATH=${PYENV_ROOT}/bin:$PATH
    eval "$(pyenv init -)"
    eval "$(pyenv virtualenv-init -)"
fi

リフレッシュ.

$ source .zshrc

ここからscrapyをインストールするための仮想環境を作っていきます.
まず,適当にフォルダを作成し移動.

$ mkdir ~/Desktop/pyenv_sc
$ cd ~/Desktop/pyenv_sc

pythonのバージョンを確認.

$ pyenv versions
  system
* 3.6.2 (set by /Users/****/.pyenv/version)

先ほど,globalでアクティブにしたので,3.6.2が設定されています.

仮想環境を構築し,確認.

$ pyenv virtualenv 3.6.2 sc
.....
$ pyenv versions
  system
* 3.6.2 (set by /Users/****/.pyenv/version)
  3.6.2/envs/sc
  sc

仮想環境に切り替え,確認.

$ pyenv local sc
(sc)$ pyenv versions
  system
  3.6.2
  3.6.2/envs/sc
* sc (set by /Users/****/Desktop/pyenv_sc/.python-version)

これで,このディレクトリに映るたびに自動でsc環境が使用されます.この状態でパッケージをインストールすると,この仮想環境にインストールされ,他の環境に影響を与えません.

環境を削除する場合は

$ pyenv uninstall sc
pyenv-virtualenv: remove /Users/****/.pyenv/versions/3.6.2/envs/sc? (yを入力)

削除されたか確認.

$ pyenv versions
pyenv: version `sc' is not installed (set by /Users/****/Desktop/pyenv_sc/.python-version)
  system
  3.6.2

これで仮想環境構築の流れを追うことができました.


以上をまとめると,下記のようになります.

## pyenvのインストール
$ brew install pyenv
## pyenv-virtualenvのインストール
$ brew install pyenv-virtualenv

## .zshrcに追記
## Set path for pyenv
export PYENV_ROOT="${HOME}/.pyenv"
if [ -d "${PYENV_ROOT}" ]; then
    export PATH=${PYENV_ROOT}/bin:$PATH
    eval "$(pyenv init -)"
    eval "$(pyenv virtualenv-init -)"
fi

##リフレッシュ
$ source .zshrc

##pythonのバージョンを確認し,インストール,アクティブ化.
$ pyenv install -l
$ pyenv install 3.6.2
$ pyenv global 3.6.2
$ pyenv versions

##パッケージをインストールするための仮想環境を構築するためフォルダを作成し,移動.
$ mkdir ~/Desktop/pyenv_sc
$ cd ~/Desktop/pyenv_sc

##仮想環境を構築し,切り替え.
$ pyenv virtualenv 3.6.2 sc
$ pyenv local sc

以上です.

cakePHPの環境構築から開発開始までまとめ

sudo apt-get update
sudo apt-get install libmcrypt-dev
sudo apt-get install php-mcrypt
sudo apt-get install php-curl
curl -L -O https://github.com/phpbrew/phpbrew/raw/master/phpbrew
chmod +x phpbrew
sudo mv phpbrew /usr/local/bin/
phpbrew init
[[ -e ~/.phpbrew/bashrc ]] && source ~/.phpbrew/bashrc
phpbrew lookup-prefix ubuntu
phpbrew install 7.0.11 +default +mysql +pdo +fpm +opcache +intl
phpbrew switch php-7.0.11
phpbrew use php-7.0.11

下記を実行してphp-7.0.11が入っていることを確認.

php -v

そのあと

php -i|grep intl

を実行しintl拡張が入っていることを確認.
下記を実行しapacheがphp7.0を使うように設定(?)

sudo add-apt-repository ppa:ondrej/php -y
sudo apt-get update -y
sudo apt-get install php7.0-curl php7.0-cli php7.0-dev php7.0-gd php7.0-intl php7.0-mcrypt php7.0-json php7.0-mysql php7.0-opcache php7.0-bcmath php7.0-mbstring php7.0-soap php7.0-xml php7.0-zip -y
sudo mv /etc/apache2/envvars /etc/apache2/envvars.bak
sudo apt-get remove libapache2-mod-php5 -y
sudo apt-get install libapache2-mod-php7.0 -y
sudo cp /etc/apache2/envvars.bak /etc/apache2/envvars

phpmyadminをインストール

phpmyadmin-ctl install

「phpMyAdminのログインとセットアップ」
ログイン:
 Cloud9のIDと同じIDでログインする。パスワードは最初は設定されていないので空欄。
設定:
 「一般設定」の「サーバ接続の照合順序」: utf8_general_ci
外観の設定:
 「言語」を「日本語」
ユーザパスワードの設定:
 「ユーザ」タブを開いて該当ユーザIDの「特権を編集」リンクをクリック。
 下の方へスクロールすると、「パスワードを変更する」とあるのでそこでパスワードを入れ、
 右下に見える「実行」ボタンをクリックする。

composerのインストール

curl -s https://getcomposer.org/installer | php

cakePHPのインストール

php composer.phar create-project --prefer-dist cakephp/app 作成したいプロジェクトの名前

必要なライブラリ類をプロジェクトにインストール

cd 作成したプロジェクトの名前
composer install

ブラウザから確認

https://ワークスペース名−ユーザID.c9users.io/プロジェクト名

configフォルダのapp.phpを開き、データベース設定を記載する

プロジェクトフォルダ\configにあるapp.phpファイルを開き、「Datasources」という文字列を検索。
(私の場合217行目にありましたが、その時点のバージョンにより数行の変動があると思います。)
そこから12行程度下までスクロールさせると 'username' => という記載が見つかるのでそこから下を修正。

'username' => 自分のDBユーザ名
'password' => パスワード
'database' => データベース名
'timezone' => '+09:00',


bootstrup.phpも修正する
同じフォルダにあるbootstrup.phpを開き、「timezone」と記載された行を文字列検索する。

date_default_timezone_set('UTC');

と記載されいますので、UTCAsia/Tokyoに変更。

date_default_timezone_set('Asia/Tokyo');

cloud9上でのcakePHP3.4の環境構築

どうもダンテです。
今回はブログを始めようと思うきっかけになった
icloud 9上でのCakePHP3.4の環境構築」
について色々詰まってしまったのでまとめておきたいと思います。

まず、CakePHP3をしようとしたのは新しく始めたバイトで必要になったからです。
そこでドットインストールのCakePHP3入門の通りにしようとしたのですが、
こちらではローカル開発環境を使っていて、cloud9は使ってませんでした。
そこで他のサイトを検索して、下記のサイトを参考にさせていただきました。
(ブログの作法とかよくわかってないんですけど、URLはっつけちゃっていいんですかね。)

Cloud9でCakePHP3【その1】 | トライスターソリューションズ

Cloud9でCakePHP3【その2】 | トライスターソリューションズ


でも、今最新のCakePHPは多分3.4なんで、このサイトの通りではダメでした。

まず、
intl拡張が入ってなかったので、下記のサイトを参考にphp7.0.11とかそこらへん周辺を入れました。

Cloud9 で PHP 7 コピペ用 - Qiita

コードは下記の通りにしました。

sudo apt-get update
sudo apt-get install libmcrypt-dev
sudo apt-get install php-mcrypt
sudo apt-get install php-curl
curl -L -O https://github.com/phpbrew/phpbrew/raw/master/phpbrew
chmod +x phpbrew
sudo mv phpbrew /usr/local/bin/
phpbrew init
[[ -e ~/.phpbrew/bashrc ]] && source ~/.phpbrew/bashrc
phpbrew lookup-prefix ubuntu
phpbrew install 7.0.11 +default +mysql +pdo +fpm +opcache +intl
phpbrew switch php-7.0.11
phpbrew use php-7.0.11
php -v

そのあと

php -i|grep intl

をすれば、無事intlが入ってました。

そして【その2】のCakePHPのインストールをしてブラウザから確認をしようとしたのですが、、
これがうまくいきませんでした。

アクセスしようとすると、

Parse error: syntax error, unexpected '.', expecting '&' or variable(T_VARIABLE) in ~~functions.app

と出てきました。

理由はよくわからないんですけど(ちゃんと勉強しないとですね)
エラーの通り,$argsの前の ... を消してみたらエラーは消えました。
これでうまく行けばよかったのですが、
今度は違うエラーが出ました。


これやっちゃダメでした。
CakePHP7が認識されていなかったってわかった時に若干大丈夫なのかな
って思ってたんですけどやっぱダメでしたね。
MVCを作ってブラウザからアクセスしようとしたらエラー吐かれました。
消した...を元に戻しました。
(全部戻せたのかわからないんだけど大丈夫なのかな。。)

細かいエラーメッセージは忘れましたが、
bootstrap.php

version_compare(PHP_VERSION, '5.6.0') < 0

がエラーを吐いてました。
phpが5.5.9だよ
って内容ですね。

しかし、上でやったようにphp 7.0.11は入れたし、

php -v

を実行してもちゃんとphp 7.0.11になってたんですね。
ここで詰まって、ダウンロードの仕方とかコマンドの設定がおかしかったのかな、、、
と思い、色々調べたり試行錯誤しました。
様々なサイトをみても「これだ!」というのは見つけられませんでした。

そこで試しに適当なphpファイルを作って

<?php
echo PHP_VERSION;
?>

をしてみるとやっぱりphpは5.9.9。

これはちゃんとphp 7を認識してくれていないのかなと思い、たどり着いたのが下のサイト
How to upgrade a PHP workspace to version 7? - Cloud9 Support - Cloud9 Community

英語のサイトですね。大学入ってから何もしてないので読むのが辛いですね。
ここのanswer通りに

sudo add-apt-repository ppa:ondrej/php -y
sudo apt-get update -y

sudo apt-get install php7.0-curl php7.0-cli php7.0-dev php7.0-gd php7.0-intl php7.0-mcrypt php7.0-json php7.0-mysql php7.0-opcache php7.0-bcmath php7.0-mbstring php7.0-soap php7.0-xml php7.0-zip -y

sudo mv /etc/apache2/envvars /etc/apache2/envvars.bak
sudo apt-get remove libapache2-mod-php5 -y
sudo apt-get install libapache2-mod-php7.0 -y
sudo cp /etc/apache2/envvars.bak /etc/apache2/envvars

を実行して、もう一度ブラウザからアクセスしてみると、、

今度はうまくいきました。

どうやら、installするだけじゃなく、apacheに指定してあげないとダメみたいですね。

エラーに書いてる事を素直に受け止めて、php7がちゃんと指定されていないことに気づけば一瞬で解決できたことですね。。。
エラーはちゃんと対処しないとダメですね。
プログラミングは気づかなくて沼にハマると本当に抜け出せなくて辛いですね( ;∀;)
もっと頑張ろう。。

初めまして。

某大学の3回生です。

 

開発環境を構築したり、色々検索したりしたあと、メモっとかないと忘れちゃうんで自分用にブログを始めました。

はてなブログのこともよくわかんない。

 

日記書いたりするかな。