読者です 読者をやめる 読者になる 読者になる

モバイルサイト用のヘッダ出力を Python で書いてみた

モバイルサイトを3キャリアでほぼ共通化して作りたい - http://d.hatena.ne.jp/tilfin/20080530/1212376626
上記のエントリで DoCoMo, au, SoftBank 用のモバイルサイトを XHTML で作成する場合のそれぞれの書き方を調べた。
その書き方に従って HTTP ヘッダと XHTML 宣言部分を出力する CGI サンプルを Python で書いてみた。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import codecs

class UserAgent:
  def __init__(self, ua):
    if ua.startswith("DoCoMo"):
      self.kind =  1
    elif ua.startswith("KDDI"):
      self.kind =  2
    elif ua.startswith("SoftBank") or ua.startswith("Vodafone") or ua.startswith("MOT"):
      self.kind =  3
    else:
      self.kind =  0

  def is_mobile(self):
    return self.kind > 0

  def is_docomo(self):
    return self.kind == 1

  def is_au(self):
    return self.kind == 2

  def is_softbank(self):
    return self.kind == 3

  def get_content_type(self):
    if self.kind > 0:
      return "Content-Type:application/xhtml+xml; charset=Shift_JIS"
    else:
      return "Content-Type:text/html; charset=UTF-8"

  def get_declare(self):
    if self.kind == 1:
      return """<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html PUBLIC "-//i-mode group (ja)//DTD XHTML
 i-XHTML(Locale/Ver.=ja/1.0) 1.0//EN" "i-xhtml_4ja_10.dtd">"""
    elif self.kind == 2:
      return """<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html PUBLIC "-//OPENWAVE//DTD XHTML 1.0//EN"
 "http://www.openwave.com/DTD/xhtml-basic.dtd">"""
    elif self.kind == 3:
      return """<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html PUBLIC "-//J-PHONE//DTD XHTML Basic 1.0 Plus//EN"
 "xhtml-basic10-plus.dtd">"""
    else:
      return """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">"""


agent = UserAgent(os.environ.get("HTTP_USER_AGENT", "N/A"))
print agent.get_content_type() + "\r\n\r\n" + agent.get_declare()
print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">'
print "<body>"

file = "content.html"
if agent.is_mobile():
  f = codecs.open(file, "r", "utf-8")
  s = f.read()
  print s.encode('cp932')
  f.close()
else: 
  f = open(file, "r")
  print f.read()
  f.close()

print "</body></html>"

クラス UserAgent のコンストラクタには、クライアントのユーザーエージェント値を渡す。文字エンコーディングは、モバイルでは Shift_JIS 、通常は UTF-8 とした。
サンプルの最後のところで body 内のコンテンツを別ファイルから読み込んで書き出している。Shift_JIS へのエンコーディングを shift_jis と指定したところエラーになり、cp932 としたら成功した(この件については後で調べてみることにする)。
get_content_type() で Content-Type 部分が取れる。ケータイ以外のときが、Content-Type:text/html; となっているのは IE では MIME Type 判別がうまくいかないためか、ファイルのダウンロードしよう(保存するかどうかのダイアログが阿上がった)とするのでこうした。get_declare() ではそれぞれのキャリアに対応した XHTML 宣言部を返す。

ちなみにウノウラボの chihiro さんが のとおり、高機能なキャリアや端末情報を取得できる Python 用ライブラリを公開されている。画面領域など詳細まで判別したいときにはこのようなモジュールの使用すると良いだろう。