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になって,改良されたのかしらん?


Windows7にCDH5.1.3でHadoop・その1失敗編

Hadoopプログラミングをする上で,いちいちサーバにjarを持って行ってテストをするのは大変すぎるので,Windows上のEclipseでHadoopプログラムをデバッグしていたんだけど,新しいHadoopをCDH5.1.3で入れたので,新しいバージョン.
以前の情報はこちら

インストール

まず,
https://ccp.cloudera.com/display/SUPPORT/CDH+Downloads
で,CDH5.1.3のtarを取得.
CDH5.1.3なのはサーバとバージョンを併せるため.

とりあえず,
hadoop-2.3.0-cdh5.1.3.tar.gz
をダウンロード.
Cygwinの/usr/local/libに展開.

$ cd /usr/local/lib
$ tar zxvf hadoop-2.3.0-cdh5.1.3.tar.gz
$ ln -s hadoop-2.3.0-cdh5.1.3 hadoop
$ ln -s /cygdrive/c/Program\ Files\ /Java/jdk1.7.0_60/ jdk1.7
$ ln -s jdk1.7 java

Windowsの環境変数にHADOOP_HOMEを追加. Pathも追加.
HADOOP_HOME:C:\usr\cygwin\usr\local\lib\hadoop
PATH:...;%HADOOP_HOME%\bin

hadoop/bin-mapreduce1/hadoop-config.shに以下を追記
# the root of the Hadoop installation
if [ -z "$HADOOP_HOME" ]; then
  export HADOOP_HOME=`dirname "$this"`/..
else
  export HADOOP_HOME=$(cygpath -u "$HADOOP_HOME")
fi
hadoopにも以下を追記.
#cygwin=false
cygwin=true
# some Java parameters
export JAVA_HOME=/usr/local/lib/java

Windowsではローカルモードでしか起動しないので,以下のように設定する.
etc/hadoop/core-site.xml
<configuration>
    <property>
        <name>hadoop.tmp.dir</name>
        <value>C:\tmp\hadoop</value>
    </property>
</configuration>
etc/hadoop/mapred-site.xml
<configuration>
    <property>
        <name>mapred.job.tracker</name>
        <value>local</value>
    </property>
    <property>
         <name>dfs.replication</name>
         <value>1</value>
    </property>
</configuration>

Eclipseプラグイン

ここまで来て問題発生.
ここにあるとおり,プラグインの公式な物がHadoop2.x系では出ていないとのこと.
ということで,どうしようかと考えていたら.
Windows用HadoopHDInsightの記事を発見.
とりあえずこれを試してみることにする.
というところで,続きは次回.