Python から Yahoo! 日本語形態素解析 Web サービスを使うための Wrapperを書いてみました。
ついでに前回紹介させてもらった「うはぁ検索」に組み込んで Wiki と はてな と Yahoo!日本語形態素解析Webサービス とAmazon を同時に検索する 「うひゃ検索」 に進化させてみました。
http://small-world.sakura.ne.jp/whya.cgi
Yahoo! では形態素解析用の辞書のメンテナンスをしているとのことで
頻繁に検索される言葉は辞書に登録されているようです。
この辞書に登録されていればかなりメジャーな言葉といえそうですね。
ちなみに一般的な辞書に載ってなくって登録されているのは
等
残念ながら? まだ登録されていないのは。
等でした。
Yahoo! 日本語形態素解析 Web サービスは辞書がメンテナンスされているのはスバラシいのですが、困るのは未知語を全て名詞と判断してしまうことです。
英数文字やカタカナだけで書かれた言葉は、めちゃくちゃな言葉でも全て名詞と判断されてしまいます。実際のところ未知語のほとんどは名詞なので、困らない場合も多いのでしょうが、使っている方は未知語なのか名詞なのかの区別がつかないので、ここは利用者側に品詞を選択できるようにしてほしかったです。
Yahoo! 日本語形態素解析 Web サービスの Wrapper のソースを貼り付けておきます。
#!/home/small-world/local/bin/python # coding=utf-8 import sys, urllib, logging from xml.etree import ElementTree class YahooApisParseWrapper: def __init__(self, appid, logger=False ): self.opener = urllib.FancyURLopener() self.appid = appid self.logger = logger self.YahooApisParseWrapperUrl = \ "http://jlp.yahooapis.jp/MAService/V1/parse?" if self.logger: self.logger.debug( 'YahooApisParseWrapperLocalSearchUrl: ' + self.YahooApisParseWrapperUrl ) # xmlnsが定義されているとtagの名前の前に # xmlnsで定義されているURIが付加されて # {http://webservices.amazon.com/AWSECommerceService/2005-10-05}Title # のようになる def getXmlns( self, xml ): xmlns = '' start = xml.find( 'xmlns="' ) + len( 'xmlns="' ) end = xml.find( '"', start + len( 'xmlns="' ) ) if start >= 0 and end >= 0: xmlns = '{' + xml[ start : end ] + '}' if self.logger: self.logger.debug( 'xmlns: ' + xmlns ) return xmlns # Yahoo!日本語形態素解析Webサービスの実行 def Parse( self, Keywords ): try: # Getの変数に値をセット Keywords = urllib.quote( Keywords ) get_val = 'appid=' + self.appid +\ '&sentence=' + Keywords # ログ出力 if self.logger: self.logger.debug( 'Parse: ' + self.YahooApisParseWrapperUrl + '&' + get_val ) # API実行 xml = self.opener.open(self.YahooApisParseWrapperUrl , get_val).read() if self.logger: self.logger.debug( xml ) # xmlnsの取得 xmlns = self.getXmlns( xml ) # ElementTreeの構築 eTree = ElementTree.fromstring( xml ) return eTree, xmlns except: msg = 'Parse失敗 %s: %s \n' \ %(sys.exc_info()[0], sys.exc_info()[1]) if self.logger: logger.error( msg ) # Parseの結果から要素を取り出す # 取り出す要素を指定できる。 def getWord( self, eTree, xmlns, extractAttributes ): try: # 検索にヒットしたwordのリスト作成 wordList = for elem in eTree.getiterator(): if elem.tag == xmlns + 'word': wordList.append( elem ) # 各wordからextractAttributesで指定された要素を取り出して # itemsに入れて返す # itemsはディクショナリのリスト items = for item in wordList: Attr = {} Attr['Tree'] = item for key, val in extractAttributes.items(): Attr[ key ] = item.find( val ).text.encode( 'utf-8' ) items.append( Attr ) return items except: msg = 'getWord失敗 %s: %s \n' \ %(sys.exc_info()[0], sys.exc_info()[1]) if self.logger: logger.error( msg ) if __name__ == '__main__': # ---------- Logger set up ---------- # DEBUG_LEBEL=logging.DEBUG #DEBUG_LEBEL=logging.INFO LOG_FILE="./YahooApisParseWrapper.log" LOGGER_NAME="YahooApisParseWrapper" logger = logging.getLogger(LOGGER_NAME) logger.setLevel(DEBUG_LEBEL) formatter =\ logging.Formatter("%(asctime)s, %(levelname)s, %(module)s, %(lineno)d, %(message)s") hdlr = logging.FileHandler(LOG_FILE) hdlr.setFormatter(formatter) logger.addHandler(hdlr) # ---------- End Logger set up ---------- # try: # 必須 # Yahoo! JAPAN Webサービス の アプリケーションID appid = 'Your Access Key ID' # インスタンス作成 awsapw = YahooApisParseWrapper( appid, logger ) # Parseの実行 # searchWord = '涼宮ハルヒ' #searchWord = 'モーニング娘。' searchWord = 'しょこたん' #searchWord = 'ごっつい' #searchWord = 'ほしのあき' # Parse をする eTree, xmlns = awsapw.Parse( searchWord ) # Parseの検索結果から値を取り出す extractAttributest = { 'surface':xmlns + 'surface' , 'pos':xmlns + 'pos' } wordList = awsapw.getWord( eTree, xmlns, extractAttributest ) # 一語か複数語かの判定 if len( wordList ) == 1: print searchWord, wordList[0]['pos'], "Yahoo!形態素解析辞書に登録済み" else : print searchWord, "は分解されちゃうよ", for item in wordList: print item['surface'], except: msg = 'main失敗 %s: %s \n' \ %(sys.exc_info()[0], sys.exc_info()[1]) logger.error( msg )
ではでは