php redis

%e7%84%a1%e9%a1%8c

redisがインストールされた状態

git clone git://github.com/nicolasff/phpredis.git
cd phpredis
phpize
./configure
make
make install

php iniにextension=redis.soを追加。

[vagrant@localhost rss11]$ sudo vi /etc/php.ini
[vagrant@localhost rss11]$ php -m | grep redis
redis

phpでredis操作

<?php
$redis = new Redis();
$redis->connect("127.0.0.1",6379);

// PINGで確認する
echo $redis->ping();

set

<?php
$redis = new Redis();
$redis->connect("127.0.0.1",6379);

// PINGで確認する
echo $redis->set('hoge', 'huga');

$value = $redis->get('hoge');

echo $value;

python redis module

Python client for Redis key-value store

$ sudo pip install redis

index.python

# _*_ coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals

def jaccard(e1, e2):
    """
    :param e1: list of int
    :param e2: list of int
    :rtype: float
    """
    set_e1 = set(e1)
    set_e2 = set(e2)
    return float(len(set_e1 & set_e2)) / float(len(set_e1 | set_e2))

def get_key(k):
    return 'JACCARD:PRODUCT:{}'.format(k)

# 商品xを購入した人が1,3,5
product_x = [1, 3, 5]
product_a = [2, 4, 5]
product_b = [1, 2, 3]
product_c = [2, 3, 4, 7]
product_d = [3]
product_e = [4, 6, 7]

# 商品データ
products = {
'X': product_x,
'A': product_a,
'B': product_b,
'C': product_c,
'D': product_d,
'E': product_e,
}

#redis
import redis
r = redis.Redis(host='localhost', port=6379, db=0)

for key in products:
    base_customers = products[key]
    for key2 in products:
        if key == key2:
            continue
        target_customers = products[key2]
        # ジャッカード指数
        j = jaccard(base_customers, target_customers)
        # redis Sortedに記録
        r.zadd(get_key(key), key2, j)

    # 例1 商品xを買った人はこんな商品も買っています
    print(r.zrevrange(get_key('X'), 0, 2))

    # 例2 商品Eを買った人はこんな商品も買っています。
    print(r.zrevrange(get_key('E'), 0, 2))
[vagrant@localhost rss10]$ python index.py
[b'B', b'D', b'A']
[b'C', b'A', b'X']

レコメンドアルゴリズムには、協調フィルタリングと内容ベース(コンテンツベース)フィルタリングがある

redis

サーバー起動
redis-server

クライアントの起動と終了
redis-cli

データベースの選択
0~15までデフォルトで設定されている
> select 1
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]>

データの保存
> bgsave
データはredis serverを立ち上げたディレクトリにdump.rdbで保存される

string
-set key value
mset key value key value

-get key
mget key key key

数字の操作
incr,decrby

key
> keys *
> keys *m*
> exits scroe
> rename age neneri
> del nenrei
> randomkey

list
push, pop
>rpush mycolor pink
>rpush mycolor green
追加した要素を見る
>lrange mycolor 0 3
>lrange mycolor 0 -1
削除
> rpop mycolor (rightから)
> lpop mycolor (leftから)
> lindex myclor 2
> llen mycolor
> ltrim mycolor 0 2

Set
追加: sadd
削除: srem

一覧: smembers
和集合: sunion
積集合: sinter (共通部分)
差集合: sdiff 

>suionstore myunion myset1 myset2

sorted set
追加: zadd
削除: zrem
一覧: zrange

Jaccard index

The Jaccard index, also known as the Jaccard similarity coefficient (originally coined coefficient de communauté by Paul Jaccard), is a statistic used for comparing the similarity and diversity of sample sets.

Jaccard(A,B)=|A∩B| / |A∪B|

mysqlのdataをsearch

%e7%84%a1%e9%a1%8c

<!doctype html>
<html>
<head>
  <title>検索画面</title>
  <meta charset="utf-8">
</head>
<body>
  <h1>検索画面</h1>

<form action="pdo_search.php" method="post">
  検索用語を入力:<input type="text" name="yourname">
<input type="submit" value="検索する">
</form>

</body>
</html>

%e7%84%a1%e9%a1%8c
mysqlのテーブルからfetch

<?php
header("Content-type: text/html; charset=utf-8");

if(empty($_POST)){
  header("Location: pdo_search_form.html");
  exit();
} else {
  //名前入力判定
  if(!isset($_POST&#91;'yourname'&#93;) || $_POST&#91;'yourname'&#93; === ""){
    $errors&#91;'name'&#93; = "名前が入力されていません。";
  }
}

if(count($errors) === 0){
  $dsn = 'mysql:host=localhost;dbname=test;charset=utf8';
  $user = 'dbuser';
  $password = 'xxxx';

  try {
    $dbh = new PDO($dsn, $user, $password);
    $statement = $dbh->prepare("select * from rss where title LIKE (:title)");

    if($statement){
      $yourname = $_POST['yourname'];
      $like_yourname = "%".$yourname."%";
      //プレースホルダへ実際の値を設定
      $statement->bindValue(':title',$like_yourname, PDO::PARAM_STR);

      if($statement->execute()){
        //レコード件数取得
        $row_count = $statement->rowCount();

        while($row = $statement->fetch()){
          $rows[] = $row;
        }
    } else {
      $errors['error'] = "検索失敗しました。";
    }
    $dbh = null;
  }
}catch (PDOException $e){
  print('Error:'.$e->getMessage());
  $errors['error'] = "データベース接続失敗しました。";
}

}
?>

<!doctype html>
<html>
<head>
  <title>検索結果</title>
  <meta charset="utf-8">
</head>
<body>

<?php if (count($errors) === 0): ?>

<p><?=htmlspecialchars($yourname, ENT_QUOTES, 'utf-8')."さんで検索しました。"?></p>
<p><?=$row_count?>件です。</p>

<table border='1'>
  <tr><td>id</td><td>title</td></tr>

<?php
foreach($rows as $row){
?>
<tr>
  <td><?=$row&#91;'id'&#93;?></td>
  <td><?=htmlspecialchars($row&#91;'title'&#93;,ENT_QUOTES,'utf-8')?></td>
</tr>
<?php
}
?>

<?php elseif(count($errors) > 0): ?>
<?php
  foreach($errors as $value){
    echo "<p>".$value."</p>";
  }
?>
<?php endif; ?>

</body>
</html>

crontab

crontab:設定した時間になったら定期的にコマンドを実行

crontab -e //クロン編集

MAILTO=”” //結果をメールで送信
0 9 * * * /home/dir/taisho.sh //時間指定と起動するシェルの指定

時間の設定例
分 時 日 月 曜日 説明
0 * * * * 毎時0分にソース実行
0,45 * * * * 毎時0分と45分にソースが実行
0 3 15 * * 毎月15日の3時にソースが実行

linux
ファイル名.sh
#! /bin/sh
command1
command2
command3

1. cronが起動しているかの確認

[vagrant@localhost rss6]$ /etc/rc.d/init.d/crond status
crond (pid  2624) を実行中...

2.cronに既にバッチ処理が設定されているか確認

[vagrant@localhost rss6]$ crontab -l
no crontab for vagrant

3. cronの設定ファイルを確認

[vagrant@localhost rss6]$ less /etc/crontab

4.バッチの設定

crontab -e
 0 0 * * * /bin/bash /home/xxx/cron_all.sh > /dev/null 2>&1

rssで取得したデータをmysqlに保存

a

$dbh = new PDO で接続、stmt->executeでsql文を実行
$stmt = $dbh->prepare(“insert into rss (title,link,site_title,site_link,date) values(?,?,?,?,?)”);
$stmt->execute(array($title,$link,$site_title,$site_link,$date));

reference
FETCH_ASSOC:Fetch a result row as an associative array

create table rss(
	id int not null auto_increment primary key,
	title varchar(255),
	link varchar(255),
	site_title varchar(64),
	site_link varchar(64),
	date datetime
);
<?php

try {
  $dbh = new PDO('mysql:host=localhost;dbname=test','dbuser','xxxx');
} catch(PDOException $e){
  var_dump($e->getMessage());
  exit;
}
$num = 5;//RSS取得件数

$rssUrl=array(
  'http://x6xo.hatenablog.com/rss',//サイトURL
);

//magpierss
require_once('./magpierss-master/rss_fetch.inc');
define('MAGPIE_OUTPUT_ENCODING', 'UTF-8');//encode
define('MAGPIE_CACHE_AGE','30');//cache

foreach($rssUrl as $no => $rss_url){
  if($rss_url != ''){
    //urlからRSSを取得
    $rss = @fetch_rss($rss_url);
      if($rss != NULL){
        for ($i=0; $i<count($rss->items); $i++){
          $rss->items[$i]["site_title"] = $rss->channel["title"];
          $rss->items[$i]["site_link"] = $rss->channel["link"];
        }
        // itemsを格納
        $rssItemsArray[] = $rss->items;
      }
  }
}

$concatArray = array();
if (is_array($rssItemsArray)) {
    for($i=0;$i<count($rssItemsArray);$i++){
    $concatArray = array_merge($concatArray,$rssItemsArray&#91;$i&#93;);//配列を統合する
  }

    foreach ($concatArray as $no => $values) {

        //RSSの種類によって日付を取得
        if($values['published']){$date = $values['published'];}
        elseif($values['created']){$date = $values['created'];}
        elseif($values['pubdate']){$date = $values['pubdate'];}
        elseif($values['dc']['date']){$date = $values['dc']['date'];}
        $date=date("Y-m-d H:i:s",strtotime($date));

        //Filter
        $nowtime = date("Y-m-d H:i:s",strtotime( "now" ));//現在時刻の取得
        if($date > $nowtime){//未来記事の排除
        }elseif(preg_match("/AD/", $values["title"])){//広告記事の排除
        }elseif(preg_match("/PR/", $values["title"])){
        }else{

            //値の定義
            $title=$values["title"];
            $link=$values["link"];
            $site_title=$values["site_title"];
            $site_link=$values["site_link"];

            //記事ごとに必要な項目を抽出
            $rssArray[]=array($date, $title, $link, $site_title, $site_link);
        }//
    }//

    //ソート
    function cmp($a, $b) {
        if ($a[0] == $b[0]) return 0;
        return ($a[0] > $b[0]) ? -1 : 1;
    }
    if($rssArray) { usort($rssArray, 'cmp'); }
    if(count($rssArray) > $num){$count=$num;}
    else{$count=count($rssArray);}

    for ($i=0; $i<$count; $i++) {
        $date=date("Y-m-d H:i:s",strtotime($rssArray&#91;$i&#93;&#91;0&#93;));
        $title=$rssArray&#91;$i&#93;&#91;1&#93;;
        $link=$rssArray&#91;$i&#93;&#91;2&#93;;
        $site_title=$rssArray&#91;$i&#93;&#91;3&#93;;
        $site_link=$rssArray&#91;$i&#93;&#91;4&#93;;
        $datelink = "<div>$date";
      $titlelink = "<a href='$link'>$title</a>";
      $site_titlelink = "<a href='$site_link'>[$site_title]</a></div>";
      echo "$datelink$titlelink$site_titlelink</div>";//(確認用)

      $stmt = $dbh->prepare("insert into rss (title,link,site_title,site_link,date) values(?,?,?,?,?)");
      $stmt->execute(array($title,$link,$site_title,$site_link,$date));
    }
}
?>

$stmt->fetchAll(PDO::FETCH_ASSOC) as $dataで、mysqlのデータを表示

<?php
// 接続
try {
  $dbh = new PDO('mysql:host=localhost;dbname=test','dbuser','xxxx');
} catch(PDOException $e){
  var_dump($e->getMessage());
  exit;
}
?>
<html>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>rss</title>
<body>
<?php

  date_default_timezone_set('Asia/Tokyo');

  $sql = "select * from rss order by date desc limit 10";
  echo '<table>';
  $stmt = $dbh->query($sql);
  foreach($stmt->fetchAll(PDO::FETCH_ASSOC) as $data){
    $date = date("m/d H:i",strtotime($data['date']));
    $title = ($data['title']);
    $link = ($data['link']);
    $site_link = ($data['site_link']);
    $site_title = ($data['site_title']);
    echo "<tr><td>$date</td><td><a href='$link'>$title</a></td><td><a href='$site_link'>[$site_title]</a></td></tr>";
  }

echo "</table>";

// 切断
$dbh = null;
?>

php rss

<?php
$num = 5;//RSS取得件数

$rssUrl=array(
  'http://x6xo.hatenablog.com/rss',//サイトURL
);

//magpierss
require_once('./magpierss-master/rss_fetch.inc');
define('MAGPIE_OUTPUT_ENCODING', 'UTF-8');//encode
define('MAGPIE_CACHE_AGE','30');//cache

foreach($rssUrl as $no => $rss_url){
  if($rss_url != ''){
    //urlからRSSを取得
    $rss = @fetch_rss($rss_url);
      if($rss != NULL){
        for ($i=0; $i<count($rss->items); $i++){
          $rss->items[$i]["site_title"] = $rss->channel["title"];
          $rss->items[$i]["site_link"] = $rss->channel["link"];
        }
        // itemsを格納
        $rssItemsArray[] = $rss->items;
      }
  }
}

$concatArray = array();
if (is_array($rssItemsArray)) {
    for($i=0;$i<count($rssItemsArray);$i++){
    $concatArray = array_merge($concatArray,$rssItemsArray&#91;$i&#93;);//配列を統合する
  }

    foreach ($concatArray as $no => $values) {

        //RSSの種類によって日付を取得
        if($values['published']){$date = $values['published'];}
        elseif($values['created']){$date = $values['created'];}
        elseif($values['pubdate']){$date = $values['pubdate'];}
        elseif($values['dc']['date']){$date = $values['dc']['date'];}
        $date=date("Y-m-d H:i:s",strtotime($date));

        //Filter
        $nowtime = date("Y-m-d H:i:s",strtotime( "now" ));//現在時刻の取得
        if($date > $nowtime){//未来記事の排除
        }elseif(preg_match("/AD/", $values["title"])){//広告記事の排除
        }elseif(preg_match("/PR/", $values["title"])){
        }else{

            //値の定義
            $title=$values["title"];
            $link=$values["link"];
            $site_title=$values["site_title"];
            $site_link=$values["site_link"];

            //記事ごとに必要な項目を抽出
            $rssArray[]=array($date, $title, $link, $site_title, $site_link);
        }//
    }//

    //ソート
    function cmp($a, $b) {
        if ($a[0] == $b[0]) return 0;
        return ($a[0] > $b[0]) ? -1 : 1;
    }
    if($rssArray) { usort($rssArray, 'cmp'); }
    if(count($rssArray) > $num){$count=$num;}
    else{$count=count($rssArray);}

    for ($i=0; $i<$count; $i++) {
        $date=date("Y-m-d H:i:s",strtotime($rssArray&#91;$i&#93;&#91;0&#93;));
        $title=$rssArray&#91;$i&#93;&#91;1&#93;;
        $link=$rssArray&#91;$i&#93;&#91;2&#93;;
        $site_title=$rssArray&#91;$i&#93;&#91;3&#93;;
        $site_link=$rssArray&#91;$i&#93;&#91;4&#93;;
        $datelink = "<div>$date";
      $titlelink = "<a href='$link'>$title</a>";
      $site_titlelink = "<a href='$site_link'>[$site_title]</a></div>";
      echo "$datelink$titlelink$site_titlelink</div>";//(確認用)
    }
}
?>

mysql

create table rss(
	id int not null auto_increment primary key,
	title varchar(255),
	link varchar(255),
	site_title varchar(64),
	site_link varchar(64),
	date datetime
);

MagpieRSS

<?php
//RSS
$rssUrl = array(
  'http://blog.livedoor.jp/news4vip2/index.rdf',//ニュー速クオリティ
  'http://himasoku.com/index.rdf',
  'http://kanasoku.info/index.rdf',
  'http://workingnews.blog117.fc.com/?xml',
  'http://blog.livedoor.jp/dgnplus/index.rdf',
  'http://majikichi.com/index.rdf',
);

//MagpieRSS
require_once('./magpierss-master/rss_fetch.inc');
define('MAGPIE_OUTPUT_ENCODING', 'UTF-8');
define('MAGPIE_CACHE_ON', false);

//配列編集
foreach ($rssUrl as $no => $rss_url){
  $rss = @fetch_rss($rss_url);
  if ($rss != NULL){
    for ($i=0; $i<count($rss->items); $i++){
      $rss->items[$i]["site_title"] = $rss->channel["title"];
      $rss->items[$i]["site_link"] = $rss->channel["link"];
    }
    $rssItemsArray[] = $rss->items;
  }
}
$contactArray = array();
for($i=0;$i<count($rssItemsArray);$i++){
$contactArray = array_merge($contactArray,$rssItemsArray&#91;$i&#93;);}
foreach ($contactArray as $no => $values){

//RSSの種類によって日付を取得
if($values['published']){$date = $values['published'];}
elseif($values['dc']['date']){$date = $values['dc']['date'];}
elseif($values['pubdate']){$date = $values['pubdate'];}
$date=date("Y-m-d H:i:s",strtotime($date));

//Filter
$nowtime = date("Y-m-d h:i:s", strtotime("now"));
if ($date > $nowtime){
} elseif(preg_match("/AD/", $values["title"])){
} elseif(preg_match("/PR/", $values["title"])){
} else {

// 値の定義
$title=$values["title"];
$link=$values["link"];
$site_title=$value["site_title"];
$site_link=$values["site_link"];

// 画像取得
$content=$values["content"]["encoded"];
preg_match('/<img.*>/i', $content, $img_all);
if(empty($img_all[0])){
  $content = $values['description'];
  preg_match('/<img.*>/i', $content, $img_all);
}
preg_match('/http.*?(\.gif|\.png|\.jpg|\.jpeg$|\.bmp)/i', $img_all[0], $gazo);
if(empty($gazo[0])){$gazo = "http://azaz.clouver.jp/antenna/noimage.png";}
else{$gazo = $gazo[0];}

//配列
$rssArray[]=array($date,$title, $link, $site_title, $site_link, $gazo);
}
}

$num = 50;
if(count($rssArray)>$num){$count=$num;}else{$count=count($rssArray);}
rsort($rssArray);

//HTML整形
for($i=0; $i<$count; $i++){
  $date=date("m/d H:i", strtotime($rssArray&#91;$i&#93;&#91;0&#93;));
  $title=$rssArray&#91;$i&#93;&#91;1&#93;;
  $link=$rssArray&#91;$i&#93;&#91;2&#93;;
  $site_title=$rssArray&#91;$i&#93;&#91;3&#93;;
  $site_link=$rssArray&#91;$i&#93;&#91;4&#93;;
  $gazo=$rssArray&#91;$i&#93;&#91;5&#93;;
    $datelink = "<div class='date'>$date</div>";
    $gazolink = "<a target='_blank' href='$link'><div class='trim'><img src='$gazo' /></div></a>";
    $titlelink = "<div class='title'><a href='$link'>$title</a></div>";
    $site_titlelink = "<div class='site_title'><a href='$site_link'>$date - [$site_title]</a></div>";
    echo "<article>$gazolink$titlelink$site_titlelink</article>";
}

?>