Created
July 18, 2011 04:19
-
-
Save yingtai/1088536 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#coding: utf-8 | |
import tweepy, random, re, os, time, urllib, urllib2, cookielib, csv, MeCab | |
from xml.etree.ElementTree import * | |
from PIL import Image | |
from cv import * | |
from BeautifulSoup import BeautifulSoup | |
secrets=[i for i in csv.reader(open('Database\\password.csv'))] | |
consumer_key=secrets[2][1]; consumer_secret=secrets[3][1] | |
access_key=secrets[4][1]; access_secret=secrets[5][1] | |
auth = tweepy.OAuthHandler(consumer_key, consumer_secret) | |
auth.set_access_token(access_key, access_secret) | |
api = tweepy.API(auth_handler=auth) | |
class Maze(): | |
def __init__(self): | |
self.ROAD=0; self.WALL=1; self.ROUTE=2 | |
self.STRROAD=u'□'; self.STRWALL=u'■'; self.STRROUTE=u'△' | |
self.width=11; self.height=9 | |
self.sx=1; self.sy=0 | |
self.gx=self.width-2; self.gy=self.height-1 | |
def makeMazeData(self): | |
bigdata=[[[] for x in range(self.width+2)] for y in range(self.height+2)] | |
for x in range(self.width+2): | |
for y in range(self.height+2): | |
if x in set(i+1 for i in range(self.width)) and y in set(j+1 for j in range(self.height)): | |
bigdata[y][x]=self.WALL | |
else: bigdata[y][x]=self.ROAD | |
self.dig(self.sx+1, self.sy+2, bigdata) | |
bigdata[self.sy+1][self.sx+1]=bigdata[self.gy+1][self.gx+1]=self.ROAD | |
data=[L[1:self.width+1] for L in bigdata[1:self.height+1]] | |
return data | |
def dig(self,px,py,bigdata): | |
for i in range(100): | |
vector=[[0,1,0,-1],[1,0,-1,0]]; r=random.randint(0,3) | |
dx=vector[0][r]; dy=vector[1][r] | |
if bigdata[py+dy*2][px+dx*2]!=self.ROAD: | |
bigdata [py+dy][px+dx]=bigdata[py+dy*2][px+dx*2]=self.ROAD | |
self.dig(px+dx*2, py+dy*2, bigdata) | |
def data2String(self,data): | |
stringData='' | |
for y in range(self.height): | |
for x in range(self.width): | |
if data[y][x]==self.ROAD: stringData+=self.STRROAD | |
elif data[y][x]==self.WALL: stringData+=self.STRWALL | |
elif data[y][x]==self.ROUTE: stringData+=self.STRROUTE | |
else: print 'translate error' | |
stringData+='\n' | |
return stringData | |
def string2Data(self,stringData): | |
data=[[[] for x in range(self.width)] for y in range(self.height)] | |
for x in range(width): | |
for y in range(height): | |
count=x+y*(self.width+1) | |
if stringData[cnt]==self.STRWALL: data[y][x]=self.WALL | |
elif stringData[cnt]==self.STRROAD: data[y][x]==self.ROAD | |
elif stringData[cnt]==self.STRROUTE: data[y][x]==self.ROUTE | |
else: print 'transtate error' | |
return data | |
def solve(self,data): | |
INF=1000; vector=[[1,0,-1,0],[0,1,0,-1]]; d=[[INF for x in range(self.width)] for y in range(self.height)] | |
d[self.sy][self.sx]=now=0 | |
que=[(self.sy,self.sx)]; goal=(self.gy,self.gx) | |
while True: | |
for count in que[:]: | |
p=que.pop(0) | |
for i in range(4): | |
newque=(p[0]+vector[0][i],p[1]+vector[1][i]); | |
if 0<=newque[0]<self.height and 0<=newque[1]<self.width and d[newque[0]][newque[1]]==INF and data[newque[0]][newque[1]]==self.ROAD: | |
d[newque[0]][newque[1]]=now+1; que.append(newque) | |
if d[self.gy][self.gx]!=INF: | |
data[self.gy][self.gx]=self.ROUTE; break | |
now+=1 | |
while True: | |
for i in range(4): | |
x=map(lambda g,v:g+v,goal,(vector[0][i],vector[1][i])) | |
if 0<=x[0]<self.height and 0<x[1]<self.width and d[x[0]][x[1]]==now: | |
goal=x; now-=1 ;data[x[0]][x[1]]=self.ROUTE; break | |
if now==0: break | |
data[self.sy][self.sx]=self.ROUTE | |
return data | |
def makeMain(self): | |
return self.data2String(self.makeMazeData()) | |
def solveMain(self,text): | |
text=re.split(u'(\W+)',text[3].lstrip(u'\n')+'\n') | |
return self.data2String(self.solve(self.string2Data(tweet))) | |
class Weather(): | |
def main(self,text): | |
text=unicode(text) | |
regionlist=[{'jp':unicode(i[0]),'en':i[1]} for i in csv.reader(open('Database\\region.csv'))] | |
conditionlist=[{'en':i[0],'jp':unicode(i[1])} for i in csv.reader(open('Database\\condition.csv'))] | |
datelist=[{'reg':u'現在','date':u'現在','n':0},{'reg':u'(きょう|今日)','date':u'今日','n':1},{'reg':u'(あした|あす|明日)','date':u'明日','n':2}, | |
{'reg':u'(!し|!明)(あさって|明後日)',u'date':'明後日','n':3},{'reg':u'[し明](あさって|明後日)','date':u'明後日','n':4}] | |
week=['Sun','Mon','Tue','Wed','Thu','Fri','Sat'] | |
region={'jp':'神戸','en':'Kobe'} | |
for i in regionlist: | |
if re.search(i['jp'],text)!=None: region=i; break | |
for i in datelist: | |
if re.search(i['reg'],text)!=None: date=i;break | |
elem=ElementTree(file=urllib2.urlopen('http://www.google.com/ig/api?weather=%s'%region['en'])) | |
current = elem.find('.//current_conditions') | |
forecasts=elem.findall('.//forecast_conditions') | |
if date['date']==u'現在': | |
condition={'en':current.find('condition').get('data')} | |
temp_c=current.find('temp_c').get('data') | |
humidity={'en':current.find('humidity').get('data')} | |
condition['jp']=condition['en'] | |
for i in conditionlist: | |
if condition['en']==i['en']: condition['jp']=i['jp'];break | |
humidity['jp']=humidity['en'].split(' ')[1] | |
return u'現在の%sの天気は%sです、気温は%s℃、湿度は&sです'%(region['jp'],condition['jp'],temp_c,humidity['jp']) | |
else: | |
for forecast in forecasts: | |
low=forecast.find('low').get('data') | |
high=forecast.find('high').get('data') | |
low=str((int(low)-32)*5/9); high=str((int(high)-32)*5/9) | |
condition={'en':forecast.find('condition').get('data')} | |
day_of_week=forecast.find('day_of_week').get('data') | |
condition['jp']=condition['en'] | |
for i in conditionlist: | |
if condition['en']==i['en']: condition['jp']=i['jp'];break | |
if week[(int(time.strftime('%w'))+date['n']-1)%7]==day_of_week: | |
return u'%sの%sの天気は%s、最高気温は%s℃、最低気温は%s℃でしょう'%(date['date'],region['jp'],condition['jp'],high,low) | |
class Sisoku(): | |
def __init__(self): | |
self.comb=[[(i,j) for i in range(j) for j in range(j+1) if i<j] for j in range(6) if 0<j] | |
def solve(self,opes,ans,n=6): | |
print opes,ans | |
length=len(opes) | |
opes=map(float,opes); opes_copy=opes[:]; ans=float(ans) | |
if not n in [1,2,3,4,5,6] or not length in [1,2,3,4,5,6]:return False | |
funclist=[lambda x,y:x+y, lambda x,y:x*y, lambda x,y:x-y, lambda x,y:y-x, lambda x,y:x/y, lambda x,y:y/x] | |
funcs=map(lambda i:i[:length],map(lambda list:map(lambda h:funclist[h],list),[(i,j,k,l,m) for i in range(n) for j in range(n) for k in range(n) for l in range(n) for m in range(n)])) | |
turns=map(lambda i:i[:length-1],[(i,j,k,l,m) for i in range((length-1)*(length)/2) for j in range((length-2)*(length-1)/2 if 2<length else 1) for k in range((length-3)*(length-2)/2 if 3<length else 1) for l in range((length-4)*(length-3)/2 if 4<length else 1) for m in range((length-5)*(length-4)/2 if 5<length else 1)]) | |
for func in funcs: | |
for turn in turns: | |
opes=opes_copy[:] | |
try: | |
for i in range(length-1): | |
opes[self.comb[length-(i+2)][turn[i]][0]] = func[i](opes[self.comb[length-(i+2)][turn[i]][0]],opes[self.comb[length-(i+2)][turn[i]][1]]) | |
opes.pop(self.comb[length-(i+2)][turn[i]][1]) | |
if -0.00001<opes[0]-ans<0.00001: return {'opes':opes_copy,'turn':turn,'func':func} | |
except (ZeroDivisionError,OverflowError,ValueError):continue | |
def data2String(self,data): | |
if data: | |
funcchr=['+','*','-','-','/','/']; func=[] | |
opes=data['opes']; turn=data['turn']; length=len(opes) | |
tests = map(lambda f:f(2.0,3.0),data['func']) | |
for test in tests: | |
if test==5: func.append(0) | |
elif test==6: func.append(1) | |
elif test==-1: func.append(2) | |
elif test==1: func.append(3) | |
elif test==2.0/3.0: func.append(4) | |
else: func.append(5) | |
opes=map(lambda i:str(int(i)),opes) | |
for i in range(length-1): | |
if func[i] in [3,5]: | |
opes[self.comb[length-(i+2)][turn[i]][0]]='('+opes[self.comb[length-(i+2)][turn[i]][1]]+funcchr[func[i]]+opes[self.comb[length-(i+2)][turn[i]][0]]+')' | |
opes.pop(self.comb[length-(i+2)][turn[i]][1]) | |
else: | |
opes[self.comb[length-(i+2)][turn[i]][0]]='('+opes[self.comb[length-(i+2)][turn[i]][0]]+funcchr[func[i]]+opes[self.comb[length-(i+2)][turn[i]][1]]+')' | |
opes.pop(self.comb[length-(i+2)][turn[i]][1]) | |
opes[0]=opes[0][1:len(opes[0])-1] | |
return opes[0] | |
else: | |
return u'解がありません' | |
def tweet2Data(self,text): | |
textlist=re.split('[^0-9\.]',text) | |
while True: | |
if '' in textlist: textlist.remove('') | |
else:break | |
list=[float(i) for i in textlist] | |
opes=list[:len(list)-1] | |
ans=list[len(list)-1] | |
return [opes,ans] | |
class Icon(): | |
def __init__(self): | |
pixiv_id=secrets[0][1];pixiv_pw=secrets[1][1] | |
self.connect =urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar())) | |
req = urllib2.Request("http://www.pixiv.net/index.php") | |
req.add_data( urllib.urlencode( {"mode":"login", "pixiv_id":pixiv_id, "pass":pixiv_pw} )) | |
res = self.connect.open(req).read() | |
def searchPageParser(self,html): | |
info=[] | |
illustList=BeautifulSoup(html).findAll('section',{'id':'search-result'})[0].findAll('li') | |
for illust in illustList: | |
a=illust.findAll('a') | |
if len(a)==1:continue | |
else: | |
image_author_name=a[1].string; image_author_id=a[1]['href'] | |
illust_id=a[0]['href'].split('illust_id=')[1] | |
if len(a)==2: bkm=0 | |
else: bkm=int(a[2]['data-tooltip'].split(u'件')[0].replace(',','')) | |
info.append({'bkm':bkm, 'illust_id':illust_id, 'image_author_name':image_author_name, 'image_author_id':image_author_id}) | |
return info | |
def illustPageParser(self,illust_id): | |
illusturl='http://www.pixiv.net/member_illust.php?mode=big&illust_id=%s'%illust_id | |
req=urllib2.Request(illusturl) | |
req.add_header('Referer',illusturl.replace("big","medium")) | |
html=self.connect.open(req).read().decode("utf8") | |
imgurl=BeautifulSoup(html).findAll('img')[0]['src'] | |
return imgurl | |
def download(self,illust_id): | |
try: | |
imgurl=self.illustPageParser(illust_id) | |
req=urllib2.Request(imgurl) | |
req.add_header('Referer','http://www.pixiv.net/member_illust.php?mode=big&illust_id=%s'%illust_id) | |
image=self.connect.open(req).read() | |
savedir=os.getcwd()+'\\Images' | |
file=open(savedir+'\\'+os.path.basename(imgurl),'wb') | |
for i in image: | |
file.write(i) | |
file.close() | |
except Exception,e:print e | |
def downloadMostFaved(self,query): | |
imgdatas=[];maxbkm=0;illust_id=-1 | |
for i in range(200): | |
url=u'http://www.pixiv.net/search.php?s_mode=s_tag&word=%s&order=date_d&p=%s'%(urllib.quote_plus(query.encode('utf-8')),str(i)) | |
html=self.connect.open(urllib2.Request(url)).read() | |
if re.search(u'<div class="no-item">見つかりませんでした</div>',html)!=None:break | |
imgdatas.extend(self.searchPageParser(html)) | |
imgdatas=sorted(imgdatas,key=lambda x:x['bkm'],reverse=True)[:(20 if len(imgdatas)>20 else len(imgdatas))] | |
print imgdatas | |
for i in imgdatas: | |
self.download(i['illust_id']) | |
def detectFace(self): | |
colors=[(0,0,255), (0,128,255), (0,255,255), (0,255,0), (255,128,0), (255,255,0), (255,0,0), (255,0,255)] | |
cascade=Load('Database\\cascade.xml') | |
for i in os.listdir(os.getcwd()+'\\Images'): | |
path=os.getcwd()+'\\Images\\'+i | |
img=LoadImage(path, CV_LOAD_IMAGE_COLOR) | |
faces = HaarDetectObjects(img, cascade, CreateMemStorage(0),1.11, 4, 0,(40, 40)) | |
if faces: | |
pilimg=Image.open(path) | |
x=faces[0][0][0];y=faces[0][0][1];width=faces[0][0][2];height=faces[0][0][3] | |
x-=width*0.2; y-=width*0.2; width*=1.4; height*=1.4 | |
croped=pilimg.crop((int(x),int(y),int(x+width),int(y+height))) | |
croped.save(os.getcwd()+'\\Images\\icon.gif') | |
try: | |
api.update_profile_image(os.getcwd()+'\\Images\\icon.gif') | |
for j in os.listdir(os.getcwd()+'\\Images'): | |
os.remove(os.getcwd()+'\\Images\\'+j) | |
return 0 | |
except:continue | |
def main(self,query): | |
query=query.split(u'を')[1].split('に')[0] | |
if re.search(u'(ちん|たん|きゅん)?の?(画像|絵)',query)!=None: | |
query=re.split(u'(ちん|たん|きゅん)?の?(画像|絵)?',query)[0] | |
self.downloadMostFaved(query) | |
self.detectFace() | |
return u'アイコンを%sの画像に変更しました'%query | |
class Twitter(): | |
def returnNewStatuslist(self,method): | |
statuses=method() | |
try: | |
statuses_data_path='Database\\mention_statuses.csv' if all([0<=i.text.find('@yingtai_bot') for i in statuses]) else 'Database\\timeline_statuses.csv' | |
old_statuses=[i for i in csv.reader(open(statuses_data_path))] | |
last_status_id=int(old_statuses[0][0].replace('\xef\xbb\xbf','')) | |
newstatuslist=[] | |
for status in statuses: | |
if status.id >last_status_id: newstatuslist.append(status) | |
new_status_writer=csv.writer(file(statuses_data_path,'w')) | |
for newstatus in newstatuslist: | |
new_status_writer.writerow([newstatus.id,newstatus.text,newstatus.author.id,newstatus.author.screen_name]) | |
new_status_writer.writerows(old_statuses) | |
return newstatuslist | |
except tweepy.error.TweepError,e: | |
print e | |
if not str(e).find('Rate limit exceeded.')>-1: | |
self.returnNewStatuslist(method) | |
def tweetResponser(self,statuses): | |
followers_ids=api.followers_ids() | |
#if statuses: | |
if False: | |
for status in statuses: | |
if status.author.id in followers_ids: | |
def reply(text): | |
try: api.update_status(u'@%s %s'%(status.author.screen_name,text),status.id) | |
except: | |
try:api.update_status(u'@%s %s '%(status.author.screen_name,text),status.id) | |
except:pass | |
if status.text.find('@yingtai_bot')>-1: | |
if status.text.find(u'天気')>-1: | |
api.update_status | |
elif re.search(u'迷路.*(昨|書|出)',status.text)!=None: | |
reply(u'\n%s'%m.makeMain()) | |
elif re.search(u'解[いきくけこ]',status.text)!=None: | |
try: | |
reply(u'\n%s'%m.solveMain(api.get_status(status.in_reply_to_status_id).text)) | |
except: | |
if status.id!=None: reply(u'迷路以外のツイートにリプライ飛ばしてませんか') | |
else: api.update_status(u'@%s えっ'%status.author.screen_name,status.id) | |
elif re.search(u'@yingtai_bot.*@[\w]+に[0-9]個の?(fav|ふぁぼ)',status.text): | |
self.favbomb(status) | |
elif re.search(u'(アイコン|icon|プロフィール画像|profile_image)を.+に')!=None: | |
reply(icon.main(status.text)) | |
else: reply('はい') | |
else: | |
if status.text.find('@')<0: | |
if re.search(u'((!ちゃん)|[ね寝](る|ます))|[nNnN][eeEE](1|[rrRRllLL])(!vv)|おやす',status.text)!=None: | |
reply([u'おやすみ',u'おやすみー',u'おやすみなさい'][random.randint(0,2)]) | |
elif re.search(u'(お[はそ][およ]|ohayo|[gGgG](ood|ood|OOD|OOD).*[mmMM](orning,orning,ORNING,ORNING)|ごおdもrにんg|むくり|mkr|[起お]きた|すらま|スラマ|早上好)',status.text)!=None: | |
reply([u'おはよう',u'おはよー',u'おはようございます'][random.randint(0,2)]) | |
elif re.search(u'離脱|りだ[つる]|([ppPP][ccCC]|パソ).*([閉と]じる|[け消]す|[き切]る|[お落]とす)|[で出][か掛]ける|を[で出]る|[い行]って[くき来](る|ます)|出発',status.text)!=None: | |
reply('いってらっしゃい') | |
elif re.search(u'(!聞|!吐|!嘆)きたく|帰宅|ただいま|kitaku|KITAKU',status.text): | |
reply([u'おかえり',u'おかえりなさい'][random.randint(0,1)]) | |
if re.search(u'([0-9.]+,)+[0-9\.] *(→|から|⇒|[-=]>) *[0-9\.]+',status.text)!=None: | |
data=sisoku.tweet2Data(status.text) | |
reply(sisoku.data2String(sisoku.solve(data[0],data[1]))) | |
def favbomb(self,status): | |
splited=re.split(u'(\W+)',status.text) | |
userid=splited[4];number=int(splited[6]) | |
print userid,"に",number,"個" | |
for p in tweepy.Cursor(api.user_timeline,id=userid).items(number): | |
try: api.create_favorite(p.id) | |
except: continue | |
api.update_status(u'@%sの代行として%s個のfavを贈りました'%(userid,number),status.id) | |
def follow_remove(self): | |
global hour | |
try: | |
fol=set(api.followers_ids()) | |
fri=set(api.friends_ids()) | |
#fol+=set('rh_ruson','alsuce10','ConstantineJP','e__ki','isennite','akatikukitiku') | |
for i in list(fol-fri): | |
api.create_friendship(i) | |
#for i in list(fri-fol): | |
# api.destroy_friendship(i) | |
except: hour-=1 | |
def main(self): | |
global hour | |
if time.localtime()[3]!=hour: | |
self.follow_remove() | |
api.update_status(analyzer.markov(analyzer.getwordlist())) | |
self.tweetResponser(self.returnNewStatuslist(api.mentions)) | |
self.tweetResponser(self.returnNewStatuslist(api.friends_timeline)) | |
hour=time.localtime()[3] | |
class Analyzer(): | |
def __init__(self): | |
self.wkt=lambda text:MeCab.Tagger("-Owakati").parse(text) | |
self.cha=lambda text:MeCab.Tagger('-Ochasen').parse(text) | |
def markov(self,texts): | |
wordlist=[] | |
for text in texts: | |
wordlist.extend(self.split(text)) | |
markov={}; word1=word2='' | |
for word in wordlist: | |
if word1 and word2: | |
if (word1,word2) not in markov: markov[(word1,word2)]=[] | |
markov[(word1,word2)].append(word) | |
word1,word2=word2,word | |
sentence='' | |
word1,word2=random.choice(markov.keys()) | |
while True: | |
while True: | |
if any([self.cha(sentence).split('\n')[0].find(pos)>-1 for pos in [u'フィラー',u'動詞',u'助詞',u'助動詞',u'記号']]): | |
sentence='' | |
try: tmp=random.choice(markov[(word1,word2)]);break | |
except: | |
word1,word2=random.choice(markov.keys()) | |
sentence+=tmp | |
word1,word2=word2,tmp | |
sentence=re.sub('(@(\w+)|#(\w+)|\w*_\w*|h?ttp://[\w\./]+)','',sentence) | |
if re.search('終助詞|助動詞|。',self.cha(sentence))!=None: | |
if 50<len(sentence)<140: | |
f=lambda list:list[len(list)-3] | |
#for i in self.cha(sentence).split('\n'): | |
# print '"%s"'%i | |
if not any(f(self.cha(sentence).split('\n')).find(pos)>-1 for pos in [u'連用',u'連体',u'未然',u'接頭',u'接続']): | |
if not sentence.endswith('。'):sentence+='。' | |
break | |
else:sentence='' | |
print self.cha(sentence) | |
#print '>',f(self.cha(sentence).split('\n')) | |
#print any(f(self.cha(sentence).split('\n')).find(pos)>-1 for pos in [u'連用',u'連体','未然','接頭']) | |
return sentence | |
def split(self,text): | |
m = self.wkt(text) | |
result = m.rstrip("\n").split(" ") | |
return result | |
def getwordlist(self): | |
return [i[1] for i in csv.reader(open('Database\\timeline_statuses.csv'))] | |
maze=Maze() | |
weather=Weather() | |
sisoku=Sisoku() | |
icon=Icon() | |
twitter=Twitter() | |
analyzer=Analyzer() | |
#print icon.detectFace() | |
if __name__ == '__main__': | |
hour=time.localtime()[3] | |
while True: | |
time.sleep(0.1) | |
#print analyzer.markov(analyzer.getwordlist()) | |
#""" | |
print u'残りAPI数: %s リセット: %s'%(api.rate_limit_status()['remaining_hits'],api.rate_limit_status()['reset_time']) | |
time.sleep(50) | |
print 'start' | |
twitter.main() | |
print 'end' | |
#""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment