import re
emoticon_string = r"""
(?P<EMOTICON>
[<>]?
[:;=8] # eyes
[-o*']? # optional nose
[][()dDpP/:{}@|\\ ] # mouth
|
[][()dDpP/:}{@|\\ ] # mouth
[-o*']? # optional nose
[:;=8] # eyes
[<>]?
)"""
regex_strings = (
# URL:
r"""(?P<URL>https?://(?:[-a-zA-Z0-9_$@.&+!*(),]|%[0-9a-fA-F][0-9a-fA-F])+)"""
,
# Twitter username:
r"""(?P<USER>@\w +)"""
,
# Hashtags:
r"""(?P<HASHTAG>\# +\w +[\w '-]*\w +)"""
,
# Cashtags:
r"""(?P<CASHTAG>\$ +\w +[\w '-]*\w +)"""
,
# Remaining word types:
r"""
(?P<NUMBER>[+-]?\d +(?:[,/.:-]\d +[+-]?)?) # Numbers, including fractions, decimals.
|
(?P<WORD>\w +) # Words without apostrophes or dashes.
|
(?P<ELLIPSIS>\. (?:\s *\. )+) # Ellipsis dots.
|
(?P<ELSE>\S ) # Everything else that isn't whitespace.
"""
)
word_re = re .compile ( r"""({}|{})""" .format ( emoticon_string, "|" .join ( regex_strings) ) , re .VERBOSE | re .I | re .UNICODE )
emoticon_re = re .compile ( regex_strings[ 1 ] , re .VERBOSE | re .I | re .UNICODE )
######################################################################
class Tokenizer:
def __init__ ( self , preserve_case= False ) :
self .preserve_case = preserve_case
def tokenize ( self , s) :
try :
s = str ( s)
except UnicodeDecodeError :
s = str ( s) .encode ( 'string_escape' )
s = unicode ( s)
# Tokenize:
words = [ ]
for x in word_re.finditer ( s) :
for key, val in x.groupdict ( ) .items ( ) :
if val:
if not self .preserve_case :
val = val.lower ( )
if key in [ 'WORD' , 'ELLIPSIS' , 'ELSE' ] :
words.append ( val)
elif key in [ 'HASHTAG' , 'CASHTAG' , 'USER' , 'URL' ] : # Add more here if needed
words.append ( "{{{}|{}}}" .format ( key, re .sub ( r'^[#@$]+' , '' , val) ) )
else :
words.append ( "{{{}|{}}}" .format ( key, val) )
return words
if __name__ == '__main__' :
tok = Tokenizer( preserve_case= False )
test = ' RT @trader $AAPL 2012 is oooopen to ‘Talk’ about patents with GOOG definitely not the treatment #samsung got:-) heh http://s...content-available-to-author-only...e.com'
tokenized = tok.tokenize ( test )
print ( "\n " .join ( tokenized) )
aW1wb3J0IHJlCgplbW90aWNvbl9zdHJpbmcgPSByIiIiCig/UDxFTU9USUNPTj4KICBbPD5dPwogIFs6Oz04XSAgICAgICAgICAgICAgICAgICAgICMgZXllcwogIFstbyonXT8gICAgICAgICAgICAgICAgICAgICMgb3B0aW9uYWwgbm9zZQogIFtdWygpZERwUC86e31AfFxcXSAgICAgICAgICMgbW91dGggICAgICAKICB8CiAgW11bKClkRHBQLzp9e0B8XFxdICAgICAgICAgIyBtb3V0aAogIFstbyonXT8gICAgICAgICAgICAgICAgICAgICMgb3B0aW9uYWwgbm9zZQogIFs6Oz04XSAgICAgICAgICAgICAgICAgICAgICMgZXllcwogIFs8Pl0/CikiIiIKCnJlZ2V4X3N0cmluZ3MgPSAoCiMgVVJMOgpyIiIiKD9QPFVSTD5odHRwcz86Ly8oPzpbLWEtekEtWjAtOV8kQC4mKyEqKCksXXwlWzAtOWEtZkEtRl1bMC05YS1mQS1GXSkrKSIiIgosCiMgVHdpdHRlciB1c2VybmFtZToKciIiIig/UDxVU0VSPkBcdyspIiIiCiwKIyBIYXNodGFnczoKciIiIig/UDxIQVNIVEFHPlwjK1x3K1tcdyctXSpcdyspIiIiCiwKIyBDYXNodGFnczoKciIiIig/UDxDQVNIVEFHPlwkK1x3K1tcdyctXSpcdyspIiIiCiwKIyBSZW1haW5pbmcgd29yZCB0eXBlczoKciIiIgooP1A8TlVNQkVSPlsrLV0/XGQrKD86WywvLjotXVxkK1srLV0/KT8pICAjIE51bWJlcnMsIGluY2x1ZGluZyBmcmFjdGlvbnMsIGRlY2ltYWxzLgp8Cig/UDxXT1JEPlx3KykgICAgICAgICAgICAgICAgICAgICAgICAjIFdvcmRzIHdpdGhvdXQgYXBvc3Ryb3BoZXMgb3IgZGFzaGVzLgp8Cig/UDxFTExJUFNJUz5cLig/OlxzKlwuKSspICAgICAgICAgICAjIEVsbGlwc2lzIGRvdHMuIAp8Cig/UDxFTFNFPlxTKSAgICAgICAgICAgICAgICAgICAgICAgICAjIEV2ZXJ5dGhpbmcgZWxzZSB0aGF0IGlzbid0IHdoaXRlc3BhY2UuCiIiIgopCgp3b3JkX3JlID0gcmUuY29tcGlsZShyIiIiKHt9fHt9KSIiIi5mb3JtYXQoZW1vdGljb25fc3RyaW5nLCAifCIuam9pbihyZWdleF9zdHJpbmdzKSksIHJlLlZFUkJPU0UgfCByZS5JIHwgcmUuVU5JQ09ERSkKZW1vdGljb25fcmUgPSByZS5jb21waWxlKHJlZ2V4X3N0cmluZ3NbMV0sIHJlLlZFUkJPU0UgfCByZS5JIHwgcmUuVU5JQ09ERSkKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKY2xhc3MgVG9rZW5pemVyOgogICBkZWYgX19pbml0X18oc2VsZiwgcHJlc2VydmVfY2FzZT1GYWxzZSk6CiAgICAgICBzZWxmLnByZXNlcnZlX2Nhc2UgPSBwcmVzZXJ2ZV9jYXNlCgogICBkZWYgdG9rZW5pemUoc2VsZiwgcyk6CiAgICAgICB0cnk6CiAgICAgICAgICAgcyA9IHN0cihzKQogICAgICAgZXhjZXB0IFVuaWNvZGVEZWNvZGVFcnJvcjoKICAgICAgICAgICBzID0gc3RyKHMpLmVuY29kZSgnc3RyaW5nX2VzY2FwZScpCiAgICAgICAgICAgcyA9IHVuaWNvZGUocykKICAgICAgICMgVG9rZW5pemU6CiAgICAgICB3b3JkcyA9IFtdCiAgICAgICBmb3IgeCBpbiB3b3JkX3JlLmZpbmRpdGVyKHMpOgogICAgICAgICAgIGZvciBrZXksIHZhbCBpbiB4Lmdyb3VwZGljdCgpLml0ZW1zKCk6CiAgICAgICAgICAgICAgIGlmIHZhbDoKICAgICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLnByZXNlcnZlX2Nhc2U6CiAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gdmFsLmxvd2VyKCkKICAgICAgICAgICAgICAgICAgIGlmIGtleSBpbiBbJ1dPUkQnLCdFTExJUFNJUycsJ0VMU0UnXToKICAgICAgICAgICAgICAgICAgICAgICB3b3Jkcy5hcHBlbmQodmFsKQogICAgICAgICAgICAgICAgICAgZWxpZiBrZXkgaW4gWydIQVNIVEFHJywnQ0FTSFRBRycsJ1VTRVInLCdVUkwnXTogIyBBZGQgbW9yZSBoZXJlIGlmIG5lZWRlZAogICAgICAgICAgICAgICAgICAgICAgIHdvcmRzLmFwcGVuZCgie3t7fXx7fX19Ii5mb3JtYXQoa2V5LCByZS5zdWIocideWyNAJF0rJywgJycsIHZhbCkpKQogICAgICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICAgICB3b3Jkcy5hcHBlbmQoInt7e318e319fSIuZm9ybWF0KGtleSwgdmFsKSkKICAgICAgIHJldHVybiB3b3JkcwoKaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzoKICAgIHRvayA9IFRva2VuaXplcihwcmVzZXJ2ZV9jYXNlPUZhbHNlKQogICAgdGVzdCA9ICcgUlQgQHRyYWRlciAkQUFQTCAyMDEyIGlzIG9vb29wZW4gdG8g4oCYVGFsa+KAmSBhYm91dCBwYXRlbnRzIHdpdGggR09PRyBkZWZpbml0ZWx5IG5vdCB0aGUgdHJlYXRtZW50ICNzYW1zdW5nIGdvdDotKSBoZWggaHR0cDovL3MuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmUuY29tJwogICAgdG9rZW5pemVkID0gdG9rLnRva2VuaXplKHRlc3QpCiAgICBwcmludCgiXG4iLmpvaW4odG9rZW5pemVkKSk=