2016年2月1日月曜日

2006年の節分まで恵方巻なんてなかった!?クックパッドデータを使って調べてみた.

節分が近づいてきました.
で,最近は恵方巻きとか太巻きとか節分に食べる訳ですが,子供の頃そんな風習無かったよな~としか思えない.

マスコミに踊らされているとか,コンビニ戦略だ,とか色々言われているけど,一体いつから恵方巻きとか太巻きとかが節分に食べられるようになったのか気になる.
というわけで,クックパッドとNIIによって提供されているクックパッドレシピデータを使って調べてみた.データは1998年から2014年まである.

とりあえず,レシピのタイトルに「恵方巻き」「太巻き」が入っているレシピを検索し,いつ投稿されたのかを調べる.ただし,全体の投稿数と比較しないと何とも言えないので,
「一日に投稿されたレシピの内,恵方巻き・太巻きが含まれている割合」
を各日ごとに検出してみた.



ちゃんとピークは2月ごとに訪れているらしい.
んでもって,最初のピークは2003年2月.

う~ん,2003年より前はクックパッドのデータにどれほど統計的意味があるか分からないレベルなので,何とも言えないかな.
ただ,別途調べた「雑煮」だと2000年からピークが出ているので,それに比べるとやはり節分に太巻きという風習は2000年代初頭はそれほどメジャーなイベントでは無かったのかも知れない.

なお,恵方巻のみだと2006年が初出.恵方巻きという言葉自体は2006年くらいから使われ始めたもののようだ.
それまでは一件もレシピがないみたいだけど、誰がこの名前つけたんだろう?




というわけで,思ったより太巻きを食べる風習というのは昔からあったみたいだけど,恵方巻きと言う言葉は最近メジャーになったものらしいということが分かりました.

クックパッドのデータ,近年の食文化の変化を見るには適しているのかも.
論文にはなりづらそうだけど.


2015年7月15日水曜日

学会タイマーオンライン再び

GoogleAppEngineの仕様変更に伴って
学会タイマーオンラインのメンテナンスができなくなったので,別の場所に再設置.

プレゼンタイマーオンライン

MacでもWindowsでもAndroidでも,アプリのインストール無しに使えます.

2015年3月7日土曜日

人狼知能エージェントの作成・その6 ver0.1.16

人狼知能サーバのバージョンが0.1.16に上がりました.

バージョン0.1.16での変更点として大きいものとして,
RoleAsignPlayerに追加する各役職とのPlayerが,Playerクラスを継承しなくなりました.

これまでは.村人であればAbstractVillagerPlayerというクラスを継承したクラスを使って,
行動を規定していました.
たとえば,
class MyVillagerPlayer extends AbstractVillagerPlayer{
}

しかしながら,AbstractVillagerPlayerはPlayerを実装していたのですが,
Playerを実装する意味がないということから,
AbstractRoleクラスを継承したAbstractVillagerをいうクラスを継承する事になりました.
たとえば,
class MyVillager extends AbstractVillager{
}

同様に,AbstractSeer,AbstractMediumなどのクラスを継承してMySeer,MyMediumなどを作るようにしてください.
基本的には,extendsするクラスとAbstractVillagerPlayerなどからAbstractVillagerに変更すればOkです.

今後も0系統は大きな変更がある可能性がありますが,ご了承ください.



2014年12月11日木曜日

Pythonを使ってTwitterでOAuthのログインをするためのクラスを作る

TwitterのOAuthでログインできるようにしておくと色々便利なのはAppEngineで経験済みなので,そのためのライブラリを作成してみる.

基本的にはこちらのページを参考にこしらえた.
pythonでoauth認証
事前準備は,
さくらインターネットでPython2.7を使ってTwitterAPIを叩くを参考のこと.
なお,Twitterとの接続に使うのは,python-twitter

まず,
http://syncer.jp/twitter-api-create-application
を参考に,Twitterのアプリを作成しておく.
ただし,アプリ作成の場所が,分かりづらくなったので,直接こちらにアクセスした方がよい.
https://apps.twitter.com/
Twitter社はアプリ作らせる気がないのか?と思うくらい分かりづらい.

このとき,CallBackURLにアプリのCGIのURLを指定しておくことを忘れずに.
後から変えられるけど.

次に,アプリ作成に入る.
まず,sqliteを使うので,oauth.dbというファイルを作っておいて,
$ sqlite3 oauth.db
sqlite> CREATE TABLE oauth (oauth_token text primary key,oauth_token_secret text);
sqlite> CREATE TABLE user (id integer primary key, consumer_key text, consumer_secret text, access_token text, access_token_secret text, screen_name text, image_url text, time datetime);
sqlite> .exit
として,データベースを作成しておく. 次に,TwitterLogin.pyを作成.
ここが今日のハイライト.


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import site
site.addsitedir('/home/username/lib/python')

import os
import cgi
import cgitb
import oauth2 as oauth
import sqlite3
import twitter
import datetime
from Cookie import SimpleCookie
from twitter import TwitterError

request_token_url = 'https://api.twitter.com/oauth/request_token'
access_token_url = 'https://api.twitter.com/oauth/access_token'
authenticate_url = 'https://api.twitter.com/oauth/authorize'

class TwitterLogin:
    def __init__(self, db_name, consumer_key, consumer_secret):
        self.db_name = db_name
        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret

    def getOAuth(self):
        consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
        client = oauth.Client(consumer)
        # reqest_token    
        resp, content = client.request(request_token_url, 'GET')
        request_token = dict(self.parse_qsl(content))
       
        #call_back="http://torix.sakura.ne.jp/twitter/signin.cgi"
   
        # request_token    
        con = sqlite3.connect(self.db_name)
        con.execute(u'insert into oauth values (?, ?)', (request_token['oauth_token'], request_token['oauth_token_secret']))
        con.commit()
        con.close()

        #
        url = '%s?oauth_token=%s' % (authenticate_url, request_token['oauth_token'])
        print 'Content-type: text/html; charset: utf-8\n\n'
        print
        print '' % url


    def getApi(self):
        access_token, access_token_secret, screen_name, image_url = self.loadAccessToken()
        self.screen_name = screen_name
        self.image_url = image_url
        if not access_token == None:
            # Cookieを使った認証
            api = twitter.Api(consumer_key=self.consumer_key,
                              consumer_secret=self.consumer_secret,
                              access_token_key=access_token,
                              access_token_secret=access_token_secret)
            return api
        elif 'QUERY_STRING' in os.environ:
            # CallBackを使った認証
            query = cgi.parse_qs(os.environ['QUERY_STRING'])
            if len(query) == 0:
                return None
            # oauth_token_secret を取得
            con = sqlite3.connect(self.db_name)
            oauth_token_secret = con.execute(
                u'select oauth_token_secret from oauth where oauth_token = ?'
                , [query['oauth_token'][0]]).fetchone()[0]
            con.close()

            if oauth_token_secret == None:
                return None

            # Access_token と access_token_secret を取得
            consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
            token = oauth.Token(query['oauth_token'][0], query['oauth_verifier'][0])
            client = oauth.Client(consumer, token)
            resp, content = client.request(
                access_token_url, "POST", body="oauth_verifier=%s" % query['oauth_verifier'][0])
            access_token = dict(self.parse_qsl(content))

            # access_tokenの保存
            api = twitter.Api(consumer_key=self.consumer_key,
                        consumer_secret=self.consumer_secret,
                        access_token_key=access_token['oauth_token'],
                        access_token_secret=access_token['oauth_token_secret'])
            try:
                user = api.VerifyCredentials()
                uid = user.GetId()
                self.screen_name = user.screen_name
                self.image_url = user.profile_image_url
                self.saveAccessToken(uid, access_token['oauth_token'], access_token['oauth_token_secret'], self.screen_name, self.image_url)
            except TwitterError:
                return None
            return api
        else:
            return None

    #save access token to db
    def saveAccessToken(self, uid, access_token, access_token_secret, screen_name, image_url):

        con = sqlite3.connect(self.db_name)
        c = con.cursor()
        #print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        c.execute(u"replace into user (id, consumer_key, consumer_secret, access_token, access_token_secret, screen_name, image_url, time) values (?, ?, ?, ?, ?, ?, ?, datetime(?))", [uid, self.consumer_key, self.consumer_secret, access_token, access_token_secret, screen_name, image_url, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")])
        con.commit()
        c.close()

        ck = SimpleCookie()
        ck.load(os.environ.get("HTTP_COOKIE",""))
        ck["id"] = uid
        ck["token"] = access_token
       
        now_date = datetime.datetime.now()
        expires = now_date
        expires = expires + datetime.timedelta(seconds=+(60*60*24))
        expires = expires.strftime('%a, %d-%b-%Y %H:%M:%S %Z')
           
        ck["id"]["expires"] = expires
        ck["token"]["expires"] = expires
        print ck.output(["id", "expires"])
        print ck.output(["token", "expires"])

    #load data from data base
    def loadAccessToken(self):
        ck = SimpleCookie()
        ck.load(os.environ.get("HTTP_COOKIE",""))
        if ck.has_key("id") and ck.has_key("token"):
            id = int(ck["id"].value)
            token = ck["token"].value
            access_token = None

            con = sqlite3.connect(self.db_name)
            c = con.cursor()
            c.execute(u'select access_token, access_token_secret, screen_name, image_url from user where id=%d'% id)
            for row in c:
                access_token = row[0]
                access_token_secret = row[1]
                self.screen_name = row[2]
                self.image_url = row[3]
            con.close()

            if not access_token == None and access_token == token:
                return access_token, access_token_secret, self.screen_name, self.image_url
            else:
                return None, None, None, None
        else:
            return None, None, None, None



    def parse_qsl(url):
        param = {}
        for i in url.split('&'):
            _p = i.split('=')
            param.update({_p[0]: _p[1]})
        return param

    def parse_qsl(self, url):
        param = {}
        for i in url.split('&'):
            _p = i.split('=')
            param.update({_p[0]: _p[1]})
        return param

getOAuthで,OAuth認証を行うページに飛ばして,callbackで戻ってきたときにgetApiで捕まえる.
それ以降は,UserIDとAccessTokenをCookieに保存することでSession管理をすることにする.
本当は独自のsessionIDを発行した方がいいのかもしれない.

次に,実際にログインするところを作ってみよう. 使い方は以下の通り.
なお,consumer_keyとconsumer_secretはTwitterで登録したアプリのものをつかう.
callback urlがhttp://xxx.xx.xx/twitter/login.cgi
そのURLでアクセスできるcgiを以下のように作成する.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import site
site.addsitedir('/home/username/lib/python')
from TwitterLogin import TwitterLogin

consumer_key = 'consumer_key'
consumer_secret = 'consumer_secret'

if __name__ == '__main__':
    twitter = TwitterLogin('oauth.db', consumer_key, consumer_secret)
    api = twitter.getApi()
    print 'Content-type: text/html; charset: utf-8\n\n'
    if api == None:
        print 'Fail to login'
    else:
        user = api.VerifyCredentials()
        print user.screen_name

これで,認証したアカウントのスクリーンネームが表示されるはず.

APIの使い方は,以下を参照.
https://python-twitter.googlecode.com/hg/doc/twitter.html

色々問題はあるかもしれないけど,とりあえず動いたので,満足.




2014年12月8日月曜日

さくらインターネットでPython2.7を使ってTwitterAPIを叩く

タイトル長いな.
世界の中心で愛を叫ぶみたいになってもうた.

さて,TwitterAPIを使ったツイート収集だけど,最近検索APIで1週間分なら無制限にとれるっぽいことが分かったので,これを使って遊んでみよう計画.

最近Pythonも気になるので,Pythonでさくらサーバ使って遊んでみる.


PythonでTwitterのAPIをたたいてみよう-セットアップ偏
を参考にしてみる.

なお,Twitterとの接続に使うのは,python-twitter

$ setenv PYTHONPATH /home/username/lib/python

$ wget --no-check-certificate github.com/simplegeo/python-oauth2/archive/master.zip
$ unzip master.zip
$ cd  python-oauth2-master/
$ ./setup.py install --home=~

$ cd ../
$ rm master.zip
$ wget --no-check-certificate https://github.com/bear/python-twitter/archive/master.zip
$ unzip master.zip
$ cd  python-twitter-master/
$ ./setup.py install --home=~

$ cd ../
$ rm master.zip
$ wget --no-check-certificate https://github.com/jcgregorio/httplib2/archive/master.zip
$ unzip master.zip
$ cd  httplib2-master/
$ ./setup.py install --home=~

$ cd ../
$ rm master.zip
$ wget --no-check-certificate https://pypi.python.org/packages/source/s/simplejson/simplejson-3.6.5.tar.gz
$ tar zxvf simplejson-3.6.5.tar.gz
$ cd simplejson-3.6.5/
$ ./setup.py install --home=~

これで必要なファイルはダウンロード完了.
ここで適当なアプリを作成しておく.

ConsumerKeyとConsumerSecret,AccessToken, AccessTokenSecretを獲得して,
以下のようなcgiを作成.

#!/usr/bin/env python
# -*- coding: utf-8 -*-


#!/usr/bin/env python
# -*- coding: utf-8 -*-


import site
site.addsitedir('/home/username/lib/python')

import sys
import twitter

print ('Content-type: text/html; charset=UTF-8\n\n')

CONSUMER_KEY = ''                             # Consumer Key
CONSUMER_SECRET = ''         # Consumer Secret
ACCESS_TOKEN = '' # Access Token
ACCESS_TOKEN_SECRET = ''         # Accesss Token Secert

api = twitter.Api(consumer_key=CONSUMER_KEY,
                      consumer_secret=CONSUMER_SECRET,
                      access_token_key=ACCESS_TOKEN,
                      access_token_secret=ACCESS_TOKEN_SECRET)


tlAry = api.GetSearch(term="keyword",count=100)
tweetlist=[]
for s in tlAry:
    if not s.text.startswith('RT @'):
        tweetlist.append(s.text)
        print s.text.encode('utf-8')


これで,keywordを含むツイートを取得可能.
ポイントの一つが,
import site
site.addsitedir('/home/username/lib/python')
の部分.
これを書いておかないとライブラリを読みに行ってくれないので注意.
さくらインターネットでは,ライブラリはローカルに置くしかないので,この作業をやらないと,twitterライブラリがimportできません.




2014年12月2日火曜日

Windows7にCDH5.1.3でHadoop・断念編

というわけで,前回のエントリーでHDInsightでHadoopをと思ったけど,
その後どうやってもEclipseでは起動しない.
どうもライブラリその他の関係でうまくいかないようだ.

色々試した結果,EclipsePluginがHadoop2.x系には対応していないと言う結論に.
結局利用可能なのは,Hadoop0.21系まで.

ひとまずHadoop2.x系のPluginがリリースされるまでは,Hadoop0.21系を利用することに.
こちらのエントリーに書いた方法で概ねインストール可能.
変更点は,
hadoop-env.shが
hadoop/bin/hadoop-env.sh
から
hadoop/conf/hadoop-env.sh
へ移動になったことくらい.

結局2年前のHadoopを使うことになるとは.とほほ.


2014年11月25日火曜日

Windows7にCDH5.1.3でHadoop・その2 HDInsightインストール編

というわけで,ここを参考にHDInsightでWindows7にHadoopを導入してみようとトライ.

まずは,HDInsight Previewsのページへ・・・行ってみるとすでに404.

嫌な予感をはらみつつ,Microsoft Web Platform Installerからの導入を目指す.
直接Microsoft Web Platform InstallerをDLすると,Microsoft Web Platform Installer5.0となっている.
説明のページが4.0だったので,バージョンが上がっている.

ここで,

  1. インストーラー(wpilauncher.exe)を実行
  2. Microsoft HDInsight for Windows Server Community Technology Previewを選択

というのが流れのはずなのだが,Microsoft HDInsight for Windows Server Community Technology Previewがない.
あるのは,Microsoft HDInsight Emulator for Windows Azureのみ.
for Windows Azureというあたりに駄目そうな予感を感じながら,とりあえずダウンロードしてみる.

やたら長いインストールが終わると,C:\直下に大量のディレクトリができる.
C直下は綺麗にしておきたい身としては,勝手にフォルダ作りまくっていらっとするけど,しょうがない.

C:\Azul
C:\hadoop
C:\HadoopInstallFiles
C:\hdp
C:\hdpdata

が作成されたようだ.
このうち,C:\hdpがHadoopの各種ライブラリがインストールされているフォルダとなる.
各種アプリがすでにインストールされているが,
C:\hdp\hadoop-2.4.0.2.1.3.0-1981以下にあるのがHadoop本体.
とりあえず,C:\hdp\hadoop-2.4.0.2.1.3.0-1981でコマンドプロンプトを開き,
C:\hdp\hadoop-2.4.0.2.1.3.0-1981>bin\hadoop version
Hadoop 2.4.0.2.1.3.0-1981
Subversion git@github.com:hortonworks/hadoop-monarch.git -r 3c481b5d3c117181c4be
3d3a25697e2e0574f972
Compiled by jenkins on 2014-07-15T14:23Z
Compiled with protoc 2.5.0
From source with checksum 8a8b83aa11aad760f2a019f4cea188c
This command was run using /C:/hdp/hadoop-2.4.0.2.1.3.0-1981/share/hadoop/common
/hadoop-common-2.4.0.2.1.3.0-1981.jar

というわけで,hadoopコマンドが動くことは確認.
さて,これをどうやってEclipseから呼び出すか,それが問題だ.

ちなみに,参考ページにはProgram Filesの問題からJAVA_HOMEをHDInsightでインストールした物にしないと駄目だ,と書いてあるが,特に問題なくインストール完了.
Microsoft Web Platform Installer5.0になって,改良されたのかしらん?