おれおれ電話帳

f:id:wwater:20160727145817p:plain

趣味でローカルなWebサービスを作ってみました。

仕事場などに掛かってくる電話は基本的に決まっているのですが、滅多にかけてこない相手もいます。
そして電話機能が持っている電話帳って数が少ないため、全部登録できません。

かといってネットの電話番号検索は、電話が掛かっている最中の検索としてちょっと遅い。
よってある程度の地域やローカルな番号はあらかじめcsvファイルとして保存しておく方法を取りました。

Python3+Pandas+Flask+JQueryAjaxという構成。 データはそれほど多くないのでDataFrameに読み込ませました。

検索する所に番号を入力していくと、段々と候補が絞られていく感じ。 リストになければ、リストをゼロにする感じです。

実は追加で、リストになければ他の迷惑電話検索サービスに検索にいくようにしようかと思っています。
が、それはそのサイトの利用規約によるのでどうしようかなー、という感じです。

また検索した電話がリストになければ登録フォームを表示するようにしようかと思っています。

なぜこれがローカルなのかというと、ユーザー登録管理は考えてないから。

おかげでFlaskはUIとして使っているだけです。

from flask import Flask, render_template, request, redirect, url_for, jsonify

@app.route("/")
def index():
  return render_template('index.html')

@app.route("/リロード用", methods=['POST'])
def リロード():
  # あれこれ
  return redirect(url_for('index'))

@app.route("/post", methods=['POST'])
def post():
  # なんたら
  return jsonify(result)

if __name__ == "__main__":
  # 迷惑電話データ処理
  app.run()

と、flask関係はこれだけ。 あとはpythonで電話関係のクラスを一つ作って中で処理して、表示はJQueryにお任せです。
気が向いたら改造しよう。

電話帳の処理はこんな感じでやった。
ちなみにエラー処理とかほとんど考えてない。何故ならオレオレだから!

import pandas as pd

class TellData:
  __tel_data = "./tel_data.csv"
  __ci = ["tel","name","desc","flag"]

  def __init__(self, fname = __tel_data):
    super(TellData, self).__init__()
    self.__fname = fname
    self.reload()

  def __check_type(self,indata):
    if isinstance(indata, int):
      indata = str(indata)
    elif isinstance(indata, str):
      indata = indata.replace("-","")
    return indata

  def reload(self):
    self.df = pd.read_csv(self.__fname, header = 0, dtype=str)
    self.df["tel"] = self.df["tel"].str.replace("-","")
    self.df = self.df.fillna("") # Jquery.parseで"Non"だとエラーとなる

  def save(self):
    self.df.to_csv(self.__fname, index=False, encoding="utf-8")

  def topfilter(self, in_telnum):
    in_telnum = self.__check_type(in_telnum)
    ans = self.df[self.df["tel"].str.contains(in_telnum)]
    ans.flag = ans.flag.astype(int)
    ans = ans.sort_values(by="flag", ascending=True)[self.__ci]
    ret = []
    for key, col in ans.iterrows():
      ret.append(dict(col))
    return ret

  def add(self, tel, name, desc, flag=0):
    if not tel:
      return

    tel = self.__check_type(tel)
    ans = self.df[self.df.tel == tel]
    if len(ans) == 1:
      return

    y = pd.Series([tel, name, desc, flag], index=self.__ci)
    self.df = self.df.append(y, ignore_index=True)

ちなみにJavascriptの中身がなかなか濃い。
なんせテーブル部分は全てJavascriptで書いているから。

enterやボタンを押して検索するのは、ローカルでは手間だから入力された時のkeyupのタイミングでテーブル描画してみた。 速度が大事なのでhtmlの追加部分はJQueryのappendではなく、innerHTMLを使ってみた。
デザインは苦手な為、Bootstrapを使う。

$(function() {
    $('#tel').each(function() {
      $(this).bind('keyup', cht(this));
      function cht(elm) {
# ~ 省略 ~

function addlist(dd) {
    var insert = "";
    for(var i = 0; i < dd.length; i++) {
        var flang = "";
        if (dd[i]["flag"] == "2") {
            insert += "<tr class='danger'>";
            flang = "迷惑電話";
        } else if (dd[i]["flag"] == "1") {
            insert += "<tr class='warning'>"
            flang = "怪しい";
        } else {
            insert += "<tr class='info'>";
            flang = "OK";
        }
        insert += "<td>" + dd[i]["tel"]  + "</td>";
        insert += "<td>" + dd[i]["name"] + "</td>";
        insert += "<td>" + dd[i]["desc"] + "</td>";
        insert += "<td>" + flang + "</td>";
        insert += "</tr>"
    }
    $('table tbody#ial')[0].innerHTML = insert;
}

人のサンプルを見ていると、本体のhtmlにデータを書いて、省略しているとか表示を絞っている感じの物が多い。
私は検索するたびに、thタグ以下をempty()して描画したhtmlを追加という形にした。ローカルじゃないと出来ない贅沢だね!

どちらが正しいのかは不明。たぶんデータ件数によってかわるんだろうなぁ。

広告を非表示にする