Pythonでtwitterクライアント作ってみる - その2

前回の続きでpythontwitter

ってかぜんぜん進んでない・・・

前に指摘されたとこも取り入れて

一覧を10秒おきに取得してコメントがあれば表示するようにしてみました

で、修正してみたけど問題発生

Ctl-Cで終了させたときにプロセスが残っちゃう

あとターミナルの制御が奪えてない(標準出力に吐き出してるだけ)からダサい・・・


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

"""
/** twitter cuiクライアントもどき
*
* @version 0.0.1
* @auther mochi
*
*/
"""

import sys, time, os, re
#import tty, termios
#import commands
import StringIO
import pycurl
import threading
from xml.parsers import pyexpat
#import difflib
#import sqlite3

class Product(object): # Interface
def setAttribute(name, value): pass
def getAttribute(name): pass
def execute(): raise NotImplementedError

class Parser: # Interface
def __init__(): pass
def parse(): pass

class XMLParser(Parser, threading.Thread):
p = None
str = ""
def __init__(self):
threading.Thread.__init__(self)
self.p = pyexpat.ParserCreate()

def createParser(self):
self.p = pyexpat.ParserCreate()

def startElement(obj, name, nodes):
global dispflg
if name == 'text':
dispflg = True
elif name == 'screen_name':
dispflg = True
else:
dispflg = False

def endElement(obj, name):
if name == 'text':
sys.stdout.write(" -> [ ")
sys.stdout.flush()
elif name == 'screen_name':
sys.stdout.write(" ]\n")
sys.stdout.flush()
time.sleep(0.1)

def charData(text, value):
if dispflg is True:
str = value.encode('UTF-8', 'replace').replace("\n", "")
str = str.replace(" ", "")
sys.stdout.write(str)
sys.stdout.flush()
#
def parse(self, str=""):
if not self.p: self.createParser()
if str is not "": self.str = str
self.p.StartElementHandler = self.startElement
self.p.EndElementHandler = self.endElement
self.p.CharacterDataHandler = self.charData
self.p.Parse(self.str)

del(self.p)
#
def run():
pass

class ApiContext(object): # Context
userID = 4671321
userName = "hagaeru3sei"
password = "******"
responseType = "xml" # [xml, json, atom, rss] which one choise
url = "http://twitter.com"
response = ""
parser = XMLParser()

#
def setResponseType(self, type):
self.responseType = type
#
def getResponseType(self):
return self.type
#
def getUserURL(self):
return self.url + "/users/show."+ self.responseType +"?screen_name=" + self.userName
#
def getTimeLineURL(self):
return self.url + "/statuses/friends_timeline." + self.responseType

#
def getUpdateURL(self):
return self.url + "/statuses/update." + self.responseType

# factory method
def Curl(*args):
return pycurl.Curl()

# set httpResponse
def setResponse(self, res):
self.response = res

#
def parse(self):
self.parser.parse(self.response)

class Twitter(Product, threading.Thread): # Twitter
context = None
type, value = "", ""
prevStr = ""

#
def __init__(self):
threading.Thread.__init__(self)
self.context = ApiContext()

def setOpt(self, type, value):
self.type = type
self.value = value
#
def execute(self, *args, **kwargs):
self.buffer = StringIO.StringIO()
curl = self.context.Curl()
curl.setopt(pycurl.URL, self.getURL())
curl.setopt(pycurl.USERPWD, self.context.userName + ':' + self.context.password)

if self.type == 'update':
curl.setopt(pycurl.POST, 1)
curl.setopt(pycurl.POSTFIELDS, "status=" + self.value)
elif self.type == "follow":
pass
elif self.type == "search":
pass
else:
curl.setopt(pycurl.WRITEFUNCTION, self.buffer.write)
curl.setopt(pycurl.FOLLOWLOCATION, 1)
curl.setopt(pycurl.MAXREDIRS, 5)
curl.setopt(pycurl.CONNECTTIMEOUT, 30)
curl.setopt(pycurl.TIMEOUT, 300)
curl.setopt(pycurl.NOSIGNAL, 1)

curl.perform()

#sys.stdout.write("\n")
#sys.stdout.flush()

#patt = re.compile("^.*(<\/.*>).*$")
o = self.buffer.getvalue().rstrip()

# 変更が無い場合表示しない
if o == self.prevStr: return

#print(difflib.context_diff(self.prevStr,o))
self.prevStr = o

self.context.setResponse(o)
self.context.parse()

self.buffer.close()

#
def load(self):
threads = []
sys.stdout.write("Loading...")
sys.stdout.flush()

self.start()
threads.append(self)
cnt = 0
list = ['|', '/', '-', '\\']
while self.isAlive() is True:
sys.stdout.write(list[cnt])
sys.stdout.flush()
sys.stdout.write("\b")
sys.stdout.flush()
time.sleep(0.1)
cnt += 1
if cnt > 3:
cnt = 0

for thread in threads:
thread.join()
#
def run(self):
if self.type == 'update':
self.execute()
else:
while True:
self.execute()
time.sleep(10)

#
def reload(self):
print('reload')

#
def follow(userId):
pass

#
def sendDirectMessage(userId):
pass

#
def setMessage(message):
self.message = message
return 0

#
def getURL(self):
if self.type == "update":
return self.context.getUpdateURL()
elif self.type == "follow":
return ""
elif self.type == "search":
return ""
else:
return self.context.getTimeLineURL()


# main
def main(*args, **kwargs):
type, value = "", ""
if not args[0].count(1): args[0].append(None)
if not args[0].count(2): args[0].append(None)
if args[0][1]:
type = args[0][1]
if args[0][2]:
value = args[0][2]
t = Twitter()
t.setOpt(type, value)
t.load()
return 0

if __name__ == "__main__":
try:
main(sys.argv);
except Exception,e:
print(e)

exit(0)

あ、あとXMLParserのparseでパースごとにインスタンス作ってやらないと例外投げられちゃったので修正したのと

起動時のオプションで投稿できるようにしました

shell> ./twitter.py update てすと

みたいな感じで