わーい、ふぁぼ監視スクリプトできたよー!

chirp streamを使ってふぁぼられを自動で通知するスクリプトを書いた。
要: python simplejson
oauth使ってますが python-oauth等のライブラリは必要ありません
自分でコンシューマキーとアクセストークンを取得しておく必要があります

gist: 410946 - GitHub:b


新感覚Twitter体験
結構おぞましいデータが吐かれてきます こわい

ChirpUserStreamをOAuthでPythonから

みなさんChirpUserStreamしてますか!便利ですよね!

最新のTwitter API「ChirpUserStreams」をPythonから使う - ctrlshiftの日記を使ってみたのですが、basic認証の有効期限が残り僅かなのが気になります。たしか六月中に廃止されるはず。
ということで、認証部分をoauthと入れ替えてやればいい。

最初はoauth対応Twitterライブラリのtweepyをハックしようとしてたんですが、すごく独特な記述が行われていたので断念。もっと勉強しないと。
で、Twitter API を OAuth で認証するスクリプトを 0 から書いてみた - trial and errorを参考に認証部分をOAuthに。
ちゃんと動きました。よかった。


動かすには事前にoauthの登録が必要です。
Twitter / アプリケーション
なんか適当に登録してconsumer_keyとcousumer_secret を取得

初回起動時にアクセス用のトークンを取得するためのurlがもらえるので、そこから7桁の番号を取得して打ち込みます。
自分はtweepyを使って取得しました。
tweepyでOAuthを試してみた

import tweepy
consumer_token = "xxxxxxxxxxxxxx"
consumer_secret = "xxxxxxxxxxxxxxxx"
auth = tweepy.OAuthHandler(consumer_token, consumer_secret)
redirect_url = auth.get_authorization_url()
redirect_url

# redirect_urlのURLにブラウザでアクセスして許可すると7桁の数字が表示されるのでそれを入力

verifier = '1234567'
auth.get_access_token(verifier)
key = auth.access_token.key
secret = auth.access_token.secret
auth = tweepy.OAuthHandler(consumer_token, consumer_secret)
auth.set_access_token(key, secret)
oauthapi = tweepy.API(auth)
oauthapi.update_status('hello from tweepy(OAuth)')
#/usr/bin/python
#-*- encoding:utf-8 -*-

import time, random
import urllib, urllib2
import hmac, hashlib
import cgi
import simplejson
import time

ckey = ""
csecret = ""
atoken =""
atoken_secret = "" 

def make_signature(params, url, method, csecret, secret = ""):
    # Generate Signature Base String
    plist = []
    for i in sorted(params):
        plist.append("%s=%s" % (i, params[i]))

    pstr = "&".join(plist)
    msg = "%s&%s&%s" % (method, urllib.quote(url, ""),
                        urllib.quote(pstr, ""))

    # Calculate Signature
    h = hmac.new("%s&%s" % (csecret, secret), msg, hashlib.sha1)
    sig = h.digest().encode("base64").strip()
    
    return sig

def init_params():
    p = {
        "oauth_consumer_key": ckey,
        "oauth_signature_method": "HMAC-SHA1",
        "oauth_timestamp": str(int(time.time())),
        "oauth_nonce": str(random.getrandbits(64)),
        "oauth_version": "1.0"
        }

    return p

def oauth_header(params):
    plist = []
    for p in params:
        plist.append('%s="%s"' % (p, urllib.quote(params[p])))
        
    return "OAuth %s" % (", ".join(plist))

# Request Token URL
reqt_url = 'http://twitter.com/oauth/request_token'
# Authorize URL
auth_url = 'http://twitter.com/oauth/authorize'
# Access Token URL
acct_url = 'http://twitter.com/oauth/access_token'
# status update
post_url = 'http://twitter.com/statuses/update.xml'
# show friends timeline
frtl_url = 'http://twitter.com/statuses/friends_timeline.xml'
'chirpstream'
chirp_url ='http://chirpstream.twitter.com/2b/user.json' 

if not atoken and not atoken_secret:
    # Request Parameters
    params = init_params()

    print "Get request token:",
    
    # Generate Signature
    sig = make_signature(params, reqt_url, "GET", csecret)
    params["oauth_signature"] = sig

    # Get Token
    req = urllib2.Request("%s?%s" % (reqt_url, urllib.urlencode(params)))
    resp = urllib2.urlopen(req)
    
    print "\t[OK]"
    
    # Parse Token Parameters
    ret = cgi.parse_qs(resp.read())
    token = ret["oauth_token"][0]
    token_secret = ret["oauth_token_secret"][0]

    # Get PIN
    print "* Please access to this URL, and allow."
    print "> %s?%s=%s" % (auth_url, "oauth_token", token)
    print "\n* After that, will display 7 digit PIN, input here."
    print "PIN ->",
    pin = raw_input()
    pin = int(pin)
    
    print "Get access token:",
    
    # Generate Access Token Request
    params = init_params()
    params["oauth_verifier"] = pin
    params["oauth_token"] = token
    
    sig = make_signature(params, acct_url, "GET", csecret, token_secret)
    params["oauth_signature"] = sig
    
    # Get Access Token
    req = urllib2.Request("%s?%s" % (acct_url, urllib.urlencode(params)))
    resp = urllib2.urlopen(req)
    
    print "\t[OK]"
    
    # Parse Access Token
    fin = cgi.parse_qs(resp.read())
    atoken = fin["oauth_token"][0]
    atoken_secret = fin["oauth_token_secret"][0]
    
    print "Access Token: %s" % atoken
    print "Access Token Secret: %s" % atoken_secret
    
    print "Your screen_name is '%s'." % fin["screen_name"][0]
    
def update():
    # Update Status by OAuth Authorization
    print "What are you doing?:",
    post = 'oauth test'
    
    params = init_params()
    params["oauth_token"] = atoken
    params["status"] = urllib.quote(post, "")
    
    sig = make_signature(params, post_url, "POST", csecret, atoken_secret)
    params["oauth_signature"] = sig
    
    del params["status"]
    
    req = urllib2.Request(post_url)
    req.add_data("status=%s" % urllib.quote(post, ""))
    req.add_header("Authorization", oauth_header(params))
    
    try:
        resp = urllib2.urlopen(req)
    except urllib2.HTTPError, e:
        print "Error: %s" % e
        print e.read()
        
def getTimeline():
    # Get Friends Timeline by OAuth Authorization
    params = init_params()
    params["oauth_token"] = atoken
    
    sig = make_signature(params, frtl_url, "GET", csecret, atoken_secret)
    params["oauth_signature"] = sig
    
    req = urllib2.Request(frtl_url)
    req.add_header("Authorization", oauth_header(params))
    resp = urllib2.urlopen(req)

    # Show Timeline
    print resp.read()
    print "Done!!"

# Get Stream
params = init_params()
params["oauth_token"] = atoken

sig = make_signature(params, chirp_url, "GET", csecret, atoken_secret)
params["oauth_signature"] = sig

req = urllib2.Request(chirp_url)
req.add_header("Authorization", oauth_header(params))
res = urllib2.urlopen(req)

res.readline()
res.readline()

while True:
  try:
    j = simplejson.loads(res.readline())
    print "[%s] %s".encode('utf-8') % (j['user']['screen_name'], j['text'])
  except:
    time.sleep(0.5)

専門用語抽出するための TF-IDF をPython で書いた

DBCLSでやってる自然言語処理の話。
TF * IDFは ある単語が、その単語を含む文書において、全体の文書と比較しながら「どれぐらい非凡か」ということを示す。

スコア = (ドキュメントに含まれる特定の単語の数/ドキュメントに含まれる全単語数) / log(全ドキュメント数 / 特定の単語を含むドキュメント数)


専門文書に含まれる専門用語を、青空文庫のログで比較して専門用語のスコアを高くとれるか、ということに使う。
まだ単語の抽出が済んでないので、スコアはあとで。


要: MeCabMeCabPythonバインディング

#/usr/bin/python
#-*- encoding:utf-8 -*-
import os
import MeCab
from sys import argv
from math import log
from glob import glob

mecab = MeCab.Tagger("-Ochasen")

class TFIDF(object):
    def __init__(self, documents_path):
        self.documents_path = documents_path

    def count_docs(self):
        cnt = 0 
        for i in self.documents_path:
            cnt += len(glob(""+i+"*"))
        return cnt
    
    def count_pop_docs(self,word):
        cnt = 0
        for path in self.documents_path:
            for i in glob(path +"*"):
                text = open(i).read()
                if self.count_nown(text,word,verbose=False)[0] > 0:
                    cnt += 1
        return cnt
    
    def count_nown(self,text,word,verbose=True):
        nown_cnt = 0
        word_cnt = 0
        node= mecab.parseToNode(text) 
        while node.next:
            node = node.next 
            if node.feature.split(",")[0] == "名詞":
                nown_cnt +=1
                if node.surface == word:
                    word_cnt += 1
        if verbose:print ""+""+"名詞:"+str(nown_cnt),word+":"+str(word_cnt)
        return word_cnt ,nown_cnt
    
    def get_tf(self,doc,word):
        text = open(doc).read()
        word_cnt , nown_cnt = self.count_nown(text,word)
        return 1.0 * word_cnt / nown_cnt

    def get_idf(self,word):
        word_pop_count = self.count_pop_docs(word)
        number = self.count_docs()
        print "全"+str(number)+"ドキュメントの中、「"+word+"」は"+str(word_pop_count)+"個数存在"
        return log(1.0 * number / word_pop_count)
    
    def count(self,doc , word):
        tf = self.get_tf(doc , word)
        idf = self.get_idf(word)
        return 1.0*tf * idf 
        
documents_path = [ # 青空文庫を置いたディレクトリ
    "/Users/mizchi/aozora/"
    ]
doc =  "/Users/mizchi/dbcls/pne/2006/2375_51_2006.txt" # 解析対象のドキュメント
word = "DNA" #テストしたい単語

score = tfidf.count(doc,word)
print ""+ doc +"の"+word+"のTF-IDFスコアは"+score+"です"

視線追従データをRで解析する準備とかいろいろ

大学の課題。たぶんゼミの人しか何をいってるかわからない。
四択問題を解いている最中の視点移動データを与えられた。


emr1.csv

;No.     ,Time,Timecode,X,Y,P,Error,Cue,Status
;00000000,00:00:00.000,00:13:10:07,312,556,4.16,,,0x00000000
;00000001,00:00:00.017,00:13:10:08,311,559,4.16,,,0x00000000
;00000002,00:00:00.033,00:13:10:07,312,556,4.16,,,0x00000000
;00000003,00:00:00.050,00:13:10:08,311,559,4.16,,,0x00000000
;...


解析したい範囲のcsvを作っておく from to の単位は秒
target.csv

;No.,from,to
;01,97,105
;02,131,134
;03,159,162
;04,187,190
...

library("ReadImages")

filterDf = function(df,from,to){
  fps = 60
  df = df[(fps*from):(fps*to),]
  df = df[df$X < 1000,]
  df[df$Y > - 1000,]
}

setBackGround = function(){
  # 画像サイズがあわない
  img = read.jpeg("/Users/mizchi/Documents/mtlab/EMR課題/10-13.jpg")
  plot(img)
  par(new=T)
}

plotData = function(mod,col=1){
  plot(
       mod$X,
       mod$Y * -1 ,
       type="l",
       col= col
     )
  par(new=T)
}

main = function(){
  raw_data = read.csv("~/Documents/mtlab/EMR課題/emr1.csv")
  time_table1 = read.csv("~/Documents/mtlab/EMR課題/target.csv")

  for(i in 1:length(time_table1$from)){
    mod = filterDf(
             raw_data ,
             from = time_table1$from[i],
             to = time_table1$to[i]
      )
    plotData(mod ,col= i %% 8 )
  }
  
}
main()

今日はここまで。

Rの文法再確認した

Rを復習した。
主に細かい挙動の確認です

代入
あ = 3 -> a
## あ = 3 , a = 3

日本語も変数として使用可
= と <- は同じ。 -> で逆方向に

イテレータ

for と while

for(i in リストのオブジェクト ){
    処理1
    処理2
}

for(i in リストのオブジェクト )
    処理

while(TRUE){}
    if(FALSE | TRUE) break
条件分岐
if (i in リストのオブジェクト ){
    処理1
    処理2
}

for(i in リストのオブジェクト )
    処理

nc = ifelse(na > nb, na, nb)

組み込み関数

any : 条件がTRUEかFALSEか

any(3>4) #FALSE


exists: その変数がNULLでないか

a = 3
exists("a") # TRUE
exists("b") # FALSE
exists("NULL") #FALSE

c : 配列

list = c(1,2,3)
list2 = c(1:15)

length() :配列長

length(0:15) # 16


cbind,rbind : 同じ長さの配列から行列を作成

> cbind(c(1,2,4),2:0)
     [,1] [,2]
[1,]    1    2
[2,]    2    1
[3,]    4    0
> rbind(c(1,2,4),2:0)
     [,1] [,2] [,3]
[1,]    1    2    4
[2,]    2    1    0

matrix : 行列

matrix(0,2,5)
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    0    0
[2,]    0    0    0    0    0

m[1,] <- c(1,3,4,5,6)
m[2,] <- c(5,3,6,1,4)
m[1,4] #-> 5

colnames(m) = c("A","B","C","D","E")
rownames(m) = c("alpha","beta")

      A B C D E
alpha 1 3 4 5 6
beta  5 3 6 1 4

データフレーム

df = data.frame(m)
as.data.frame(m)
      A B C D E
alpha 1 3 4 5 6
beta  5 3 6 1 4

データフレームと行列は相互に変換可能

array : 分割表

> array(1:30,c(3,4,2))
, , 1

     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12

, , 2

     [,1] [,2] [,3] [,4]
[1,]   13   16   19   22
[2,]   14   17   20   23
[3,]   15   18   21   24

class: 型チェック

> class(1)
[1] "numeric"
> class("1")
[1] "character"
> class(c(3,3))
[1] "numeric"
> class(m)
[1] "matrix"
> class(as.data.frame(m))
[1] "data.frame"
論理式

&
&&

xor(a,b)


もっと細かいのはしょう先生のブログを読みましょう
Rの言語仕様とか色々参考にできそうな関数とかのメモ - Seeking for my unique color.
オブジェクト指向についてはまだ謎が多いのであとで調べる。eval黒魔術でどうにかしようとしたけど、ちょっと無理だった。

emacsのmulti-termでzshを使う設定

Emacsのshell-modeは補完がきかないしやっぱりtermだよな!で、termならmulti-termだよな!
ということで、今までやろうやろうと思っていながら放置していた、multi-termでzshを動かす環境を作った

環境はCocoa Emacs 23.1
termのなかでvim動くしipython動くし、つまりはほぼフル機能のターミナルが動いている。
おかげで標準のターミナルいらないぐらい便利です。


まずはzshの設定

Mac標準zshは日本語回りに問題があるらしいのでmacportszshをいれる(とはいっても、zsh使う人ならやってるだろうが)

sudo port install zsh-devel +mp_completion +pcre

~/.zshrcに追記

[[ $TERM = "eterm-color" ]] && TERM=xterm-color

これがないと、[delete]キーがSpaceの挿入になってしまっていた。zsh以外はちゃんと動いていた。

Emacs

Emacsでauto-installをいれてる場合、

M-x auto-install-from-emacswiki
multi-term

なければここから


次にucs-normalizeをいれる (Emacs23.2から不要とのこと)
ここから落として~/.emacs.d/elispにいれておく


~/.emacs.elの設定

;;term
(require 'multi-term)
(setq multi-term-program shell-file-name)
(add-hook 'term-mode-hook '(lambda ()
			     (define-key term-raw-map "\C-y" 'term-paste)
			     (define-key term-raw-map "\C-q" 'move-beginning-of-line)
			     (define-key term-raw-map "\C-f" 'forward-char)
			     (define-key term-raw-map "\C-b" 'backward-char)			     
			     (define-key term-raw-map "\C-t" 'set-mark-command)			     
			     (define-key term-raw-map (kbd "ESC") 'term-send-raw)
			     (define-key term-raw-map [delete] 'term-send-raw)
                             (define-key term-raw-map "\C-z"
                               (lookup-key (current-global-map) "\C-z"))))
(global-set-key (kbd "C-c n") 'multi-term-next)
(global-set-key (kbd "C-c p") 'multi-term-prev)
(set-language-environment  'utf-8)
(prefer-coding-system 'utf-8)

(require 'ucs-normalize) 
(setq file-name-coding-system 'utf-8-hfs)
(setq locale-coding-system 'utf-8-hfs)
(setq system-uses-terminfo nil)


すごーーーーく環境依存な気がするのですが、とりあえずこれで一通り動くようになると思います