へぬもへメモ

https://twitter.com/henumohe

Webstemmer使おうとして文字コードに悩まされたけど解決

昨日の記事で書いた、Webstemmerステップ4の文字コードエラーが治った。

昨日の状況

『ステップ4. 学習したパターンを使って本文を抽出する』を実行すると文字化け

C:\Python27\Lib\site-packages\webstemmer>extract.py -C euc-jp asahi.pat asahi.201107111623.zip
PATTERN: 201107111602/www.asahi.com/digital/av/TKY201106280357.html
MAIN-6: 召ツ宵エ。・将ツ。・。・娼。将苡ェイ召エ宵ョ将」召ェツ。ェ。。ェゥ。ェメ。ェ。\将「\宵ェ\召エ召ツ娼ャ。ェ。。
  • 元の文字列はUnicode文字列
  • EUC-JP,shift-jis,utf-8などひと通りエンコード試したけど全て文字化け
  • PyhtonはUnicode文字列を直接表示できない
    • 直接表示しようとすると"UnicodeEncodeError: 'cp932' codec can't encode character u'\xa1' in position 0:illegal multibyte sequence"
  • try-except文を使って1文字ずつ↑のエラー吐かせてみた

新たに分かったこと

  • 元の文字列はEUC-JPっぽい "\xa1\xca\xa3\xb6\xb7\xee\xa3\xb2" = "(6月2"
  • extract.pyは文字コード自動認識しない
  • オプション-cでデフォルトの文字コードを指定する
    • 公式の説明
      • "HTML ファイル内に charset の指定がない場合、 デフォルトで使用する文字コードの名前 ("euc-jp", "utf-8" など)を指定します。文字コードの自動認識機能はありません。"
    • オプション-Cは出力テキストの文字コード指定なので今回は関係なさそう

とりあえず、文字コード周りをEUC-JPに統一してみることにした。
↓元のコードのエンコードを外して

  def dump_text(self, name, tree,
                pat_threshold, diffscore_threshold, main_threshold,
                codec_out='utf-8', strict=True):
   #enc = lambda x: x.encode(codec_out, 'replace')
    enc = lambda x: x
    ........
          if pat1.title_sectno < sectno and main_threshold <= sect.mainscore:
            for b in sect.blocks:
              print 'MAIN-%d: %s' % (sect.id, enc(b.orig_text))
          else:
            for b in sect.blocks:
              print 'SUB-%d: %s' % (sect.id, enc(b.orig_text))
    print
    return

オプションに-c euc-jpを追加して

C:\Python27\Lib\site-packages\webstemmer>extract.py -c euc-jp asahi.pat asahi.201107111623.zip

実行すると

...
!MATCHED: 201107111623/www.asahi.com/digital/av/TKY201106280357.html
PATTERN: 201107111602/www.asahi.com/digital/av/TKY201106280357.html
MAIN-6: (6月29日発売のAERAムック『AERA×Apple アップルはお好き
ですか』から抜粋した記事です)
MAIN-6: 死者3025人、行方不明者2770人、全壊家屋2万8千戸……(6月10日現
在)。3月11日に起きた東日本大震災でもっとも被害の大きかった自治体のひとつ、宮城
県石巻市。海に近い市街地は石巻市立病院などいくつかの建物を除き、街は跡形もなく流
された。
...

治ったー!ようやく先に進めます。
色々分からない所もあるけど今は放置。余裕ができたら細かいところも追って行きたい。