Created
September 8, 2016 11:44
-
-
Save GNQG/0f10bb68aabed84057726c4c33c1553d to your computer and use it in GitHub Desktop.
This file contains 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
from urllib import urlencode | |
from urllib2 import urlopen,HTTPError,URLError | |
import socket | |
import re | |
import json | |
try: | |
from unescape_charref import unescape_charref | |
except ImportError: | |
unescape_charref=None | |
class DEE2JSONDecoder(json.JSONDecoder): | |
def __init__(self,encoding=None,**kwgs): | |
# some control sequences are not escaped in string | |
# ex. eventid=105(headline) line 319 u'\t\t\t"Info" : "...\t(^^)"' | |
# toavoid this set strict=False | |
json.JSONDecoder.__init__(self,encoding,strict=False,**kwgs) | |
class DEE2EventData(object): | |
DEE2_URL='http://manbow.nothing.sh/event/event.cgi' | |
GETJSON_PARAM=(('action','JSONList'),) | |
def __init__(self,eventid,name=None): | |
self._eventid=int(eventid) | |
self._name=name if isinstance(name,basestring) else None | |
self._songlist=[] | |
self._headline=[] | |
def getsonglist(self,utf8=False): | |
tmpjson=self._getjson(utf8) | |
if self._name is None: | |
self._name=tmpjson.get('EventName') | |
self._songlist=tmpjson['Data'] | |
def getheadline(self,utf8=False): | |
tmpjson=self._getjson(utf8,(('output','headline'),)) | |
if self._name is None: | |
self._name=tmpjson.get('EventName') | |
self._headline=tmpjson['Data'] | |
def get(self,utf8=False): | |
self.getsonglist(utf8) | |
self.getheadline(utf8) | |
def _getjson(self,utf8,iterable=None): | |
param=self.GETJSON_PARAM | |
if utf8==True: | |
param+=(('utf-8','on'),) | |
if iterable: | |
param+=iterable | |
query=urlencode(param+(('event',self._eventid),)) | |
try: | |
ret=urlopen(self.DEE2_URL+'?'+query).read() | |
except URLError,e: | |
if isinstance(e.reason, socket.timeout): | |
raise Exception("timeout: %s" % e) | |
else: | |
raise | |
except socket.timeout,e: | |
raise Exception("timeout: %s" % e) | |
# fix structure error: [{...},{...},...,{...},] -> [{...},{...},...,{...}] | |
# this may be happen when last registered entry is deleted | |
# ex. eventid=104 BOFU2015 | |
ret=re.sub( | |
r'}\s*,\s*\]\s*}\s*\Z', | |
r'}]}', | |
ret | |
) | |
if not utf8: | |
# remove extra escapes for Damemoji: [cp932 1st byte]\\ -> [cp932 1st byte]\ | |
ret=re.sub( | |
'([\x81-\x9f\xe0-\xfc]'+r'\\)\\', | |
r'\1', | |
ret | |
) | |
# for output=headline | |
# truncated multibyte character involves '"' when decoded | |
# to avoid this, first, inserting ' ' before '"' | |
ret=re.sub( | |
r'^(\s*\".*?\"\s*:\s*\".*)\"(\s*[,\]}]?\s*)$', | |
r'\1 "\2', | |
ret,flags=re.MULTILINE | |
) | |
# second, decode this with errors='replace' | |
# truncated character('[\x81-\x9f\xe0-\xfc] ') generates '\ufffd' | |
# valid string does not change ' ' | |
ret=ret.decode('cp932',errors='replace') | |
# and last, remove ' ' or '\ufffd' from end of each string | |
ret=re.sub( | |
ur'^(\s*\".*?\"\s*:\s*\".*)[ \ufffd]\"(\s*[,\]}]?\s*)$', | |
ur'\1"\2', | |
ret,flags=re.MULTILINE | |
) | |
else: | |
# if utf8 mode, only to do is decoding string | |
ret=ret.decode('cp932',errors='replace') | |
if unescape_charref: | |
# unescape character reference | |
ret=unescape_charref(ret) | |
# in some cases strings contain unescaped '"' | |
# ex. eventid=26 line 2 '\t"EventName" : "B-1 "Unrestricted"" ,' | |
# add escapes to those | |
ret=re.sub( | |
ur'(^\s*\".*?\"\s*:\s*\")(.*\".*)(?=\"\s*[,\]}]?\s*$)', | |
lambda s:s.group(1)+re.sub( | |
ur'((^|[^\\])(?:\\\\)*)(?=\")', | |
ur'\1'+ur'\\', | |
s.group(2) | |
), | |
ret,flags=re.MULTILINE | |
) | |
return json.loads(ret,cls=DEE2JSONDecoder) | |
def clear(self): | |
self._eventid=None | |
self._name=None | |
self._songlist=[] | |
self._headline=[] | |
@property | |
def eventid(self): | |
return self._eventid | |
@eventid.setter | |
def eventid(self,evid): | |
if not getattr(evid,'__int__') or int(evid)<=0: | |
raise ValueError('eventid must be positive integer') | |
elif int(evid)==self.eventid: | |
self._eventid=int(evid) | |
else: | |
self.clear() | |
self._eventid=int(evid) | |
@eventid.deleter | |
def eventid(self): | |
self.clear() | |
@property | |
def eventname(self): | |
return self._name | |
@eventname.setter | |
def eventname(self,name): | |
self._name=name | |
@eventname.deleter | |
def eventname(self): | |
self._name=None | |
@property | |
def songlist(self): | |
return self._songlist | |
@songlist.setter | |
def songlist(self,sl): | |
if getattr(sl, '__iter__'): | |
self._songlist=list(sl) | |
else: | |
self._songlist=[] | |
@songlist.deleter | |
def songlist(self): | |
self._songlist=[] | |
@property | |
def headline(self): | |
return self._headline | |
@headline.setter | |
def headline(self,hl): | |
if getattr(hl, '__iter__'): | |
self._headline=list(hl) | |
else: | |
self._headline=[] | |
@headline.deleter | |
def headline(self): | |
self._headline=[] | |
if __name__=='__main__': | |
import sys | |
import time | |
args=sys.argv | |
if len(args)>=2: | |
for evid in args[1:]: | |
try: | |
ev=DEE2EventData(evid) | |
except: | |
continue | |
ev.get() | |
print u'EventID={} EventName={} songs={}'.format( | |
ev.eventid,ev.eventname,len(ev.songlist) | |
) | |
ev.clear() | |
if len(args)>2:time.sleep(1) | |
else: | |
print u'Usage: dee2.py ID1 ID2 ...' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment