Pythonで、メールで乗り換え検索

去年書いた、メールで「えきから時刻表」の乗り換え案内を拝借するスクリプトが出てきた。
レンタルサーバーに置いてCRONしてたけど、なんとまだ使える!
ただ、こんなスーパー決めうち地獄コードは、二度とメンテしたくない!

#!/usr/bin/env python
#coding: utf-8

"""
http://i.ekikara.jp/cgi-bin/route_mobile.cgiをメールで拝借するスクリプト。
cronで。

次の本文でメールすると、検索結果が返信される。

乗車駅名 降車駅名

複数の同名駅があるときは、それらの駅番号が返信されるので、
駅名を目当ての駅の番号で置き換えて、またメールする。
"""
import datetime
from email.parser import Parser
from email.mime.text import MIMEText
import imaplib
import smtplib
import urllib
import httplib
import sgmllib
import re

HOSTNAME = "ここには、メールのホスト名を書く"
USERNAME = "ここには、乗り換え検索を受けるメールアドレスを書く"
PASSWORD = "ここには、メールのパスワードを書く"
FROM = USERNAME

class TagStripper(sgmllib.SGMLParser):
  """
  http://www.codereading.com/codereading/python/strip-html-tags.htmlでひろった
  HTMLタグを取り除くパーザー。
  """
  def __init__(self):
    sgmllib.SGMLParser.__init__(self)

  def strip(self, some_html):
    self.theString = "" 
    self.feed(some_html)
    self.close()
    return self.theString

  def handle_data(self, data):
    self.theString += data


tag_stripper = TagStripper()
m = imaplib.IMAP4_SSL(HOSTNAME)
m.login(USERNAME, PASSWORD)
m.select()
unused, mailnums = m.search(None, "UNSEEN")

for num in mailnums[0].split():
  unused, data = m.fetch(num, "RFC822")
  headers = Parser().parsestr(data[0][1])
  charset = headers.get_charsets()[0]
  recv_body = headers.get_payload().strip()

  if len(recv_body.split(" ")) != 2:
    body = ["You searched it: %s\n" % recv_body,
            "Transfer search system could not find it.",
            "Your request has some problem.",
            "Please confirm the station name or number and remember how to use it."]
    sent_body = "\n".join(body).decode("shift-jis").encode(charset)
    s = smtplib.SMTP(HOSTNAME)
    msg = MIMEText(sent_body)
    msg.set_charset(charset)
    msg.set_type("text/plain")
    msg["Subject"] = ""
    msg["From"] = FROM
    TO = headers["From"]
    msg["To"] = TO
    s.sendmail(FROM, TO, msg.as_string())
    s.quit()
    continue

  intext, outtext = recv_body.split(" ")
  incode, outcode = "", ""
  if intext.isalnum():
    incode = intext
  if outtext.isalnum():
    outcode = outtext
  intext_param = urllib.urlencode({
    "intext": intext.decode(charset).encode("shift-jis")}) # 出発駅
  outtext_param = urllib.urlencode({
    "outtext": outtext.decode(charset).encode("shift-jis")}) # 到着駅
  incode_param = urllib.urlencode({
    "incode": incode.decode(charset).encode("shift-jis")}) # 出発駅コード
  outcode_param = urllib.urlencode({
    "outcode": outcode.decode(charset).encode("shift-jis")}) # 到着駅コード
  now = datetime.datetime.now()
  year_month = "".join(["%04d"%now.year, "%02d"%now.month])
  day = str(now.day)
  hour = str(now.hour)
  minute = str(now.minute)
  url = "".join(["/cgi-bin/route_mobile.cgi?", intext_param,
  "&", outtext_param, "&", incode_param, "&", outcode_param,
  "&now_time=%3C%3C+%8C%BB%8D%DD%8E%9E%8D%8F%82%C5%8C%9F%8D%F5+%3E%3E&month=",
  year_month, "&day=", day, "&way=&hour=", hour, "&min=", minute, "&arrive=&airplane=on&sprexprs=on&utrexprs=on&max=3&sort=time&half=on&cut=on&direct=on&.cgifields=utrexprs&.cgifields=way&.cgifields=sprexprs&.cgifields=airplane"])
  
  conn = httplib.HTTPConnection("i.ekikara.jp:80")
  conn.request("GET", url)
  res = conn.getresponse()
  html = res.read()
  conn.close()
  
  l = []
  l.append(" ".join(["You searched it:", intext, outtext]).decode(charset).encode("shift-jis"))
  keywords = ["clock", "money", "foot", "depart", "arrive"]
  alias = {"clock": "total time", "money": "fee", "foot": "transfer",
           "depart": "depart", "arrive": "arrive"}
  station_duplicated = False
  no_such_station = False
  result_counter = 1

  for line in html.splitlines():
    if "form" in line: 
      # 複数の同名駅があるときだけ"form"含むレスポンスが返ってくる
      if "select" in html and "option" in html:
        station_duplicated = True
      else:
        no_such_station = True
      break
    for kw in keywords:
      if kw in line:
        if "*." in line:
          continue
        if kw == "clock":
          l.append("\n*** search result %d ***" % result_counter)
          result_counter += 1
        l.append("".join([alias.get(kw), ": ", tag_stripper.strip(line)]))
        continue

  if station_duplicated == True:
    l.append("\nTransfer search system found a several stations with same name.")
    l.append("Please send again with station number below instead of station name.")
    for line in html.splitlines():
      if "select" in line:
        l.append("")
      if "option" in line:
        code = re.match(r"""^.*"(?P<code>.*)".*$""", line).groupdict()["code"]
        if not code:
          continue
        l.append("".join([code, ": ", tag_stripper.strip(line)]))

  if no_such_station == True:
    l.append("\nTransfer search system could not find it.")
    l.append("Your request has some problem.")
    l.append("Please confirm the station name or number and remember how to use it.")

  sent_body = "\n".join(l).decode("shift-jis").encode(charset)
  s = smtplib.SMTP(HOSTNAME)
  msg = MIMEText(sent_body)
  msg.set_charset(charset)
  msg.set_type("text/plain")
  msg["Subject"] = ""
  msg["From"] = FROM
  TO = headers["From"]
  msg["To"] = TO
  s.sendmail(FROM, TO, msg.as_string())
  s.quit()

  #検索済みの既読メールを残さないなら、コメントを外す
  #m.store(num, "+flags", "\\deleted")
  #m.expunge()

m.logout()