2013年2月24日日曜日

Pythonで時間関連の関数の勉強(datetime)

地味ですが、Pythonの時間関連の勉強をしたいと思います。
当然いつもやっているのですが、しっかりと頭に叩き込みたいと思います。

下記をやることで頭に叩き込まれると思います。

  • 今日を得る
  • 明日を得る
  • 昨日を得る
  • 1時間前を得る
  • 29時間後を得る
  • 5分前を得る
  • 2011年3月11日からの経過日を得る
  • あと何年で50歳になるかを得る
  • あと年日で50歳になるかを得る
  • あと何時間で50歳になるかを得る
  • 8日後を得る
  • 1ヶ月後を得る
  • 3年2ヶ月3日及び11時間後を得る

さて、まずここを見ながら勉強します。

timedeltaオブジェクト


class datetime.timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[,weeks]]]]]]])
timedeltaオブジェクトは経過時間、すなわち二つの日付や時刻間の差を表します。


ということなので、時間の計算をしたいときは、このオブジェクトを使うことになるわけでしょう。
試しに、使ってみましょう。

d = datetime.timedelta(days = -1)
こうやると、dは、-1 day, 0:00:00となっています。
d1 = datetime.timedelta(days = 1)
d2 = datetime.timedelta(days = 5)
dd = d2 - d1
こうやると、ddは、4 days, 0:00:00となっています。確かに、計算できていますね。dd.total_seconds()を出してみると、345600.0となります。60秒×60分×24時間×4日ですと、まさしく345600ですね。合っていました。

dateオブジェクト


class datetime.date(year, month, day)
dateオブジェクトは日付 (年、月、および日) を表します。


次はdateオブジェクトで、年月日を表すオブジェクトですね。差分を表すのがtimedeltaですが、こちらはまさに日付を表すものになります。シンプルですね。では、実際使ってみます。

badDay = datetime.date(2011, 3, 11)
とやると、badDayは、2011-03-11となりました。
today = datetime.date.today()
とやると、今日の日付が得られます。2013-02-24となりました。
d = datetime.date.fromordinal(1000000)
こんなのもやってみました。1年1月1日を1とするという変な関数ですね。2といれると、1年1月2日ですし、365と入れると、1年12月31日となります。ちなみに、よく百万年とかいいますが、百万日ということで1000000と入れると、2738-11-28が返ってきます。100万年というのは果てしないことであるのだなと思った次第です。
y = today.year
とやりますと、先程作成したtodayの年のみyに入ります。month、dayも同じ仕組みですね。

ほぼほぼ、整いました。

それでは、宿題を順に解いていきましょう。

■ 今日を得る
これは先程やってしまいました。

■明日を得る
tomorrow = today + datetime.timedelta(days = 1)
とやると、2013-02-25 12:50:48.396328出ました。OKです。

■昨日を得る
yesterday = today - datetime.timedelta(days = 1)
とやると、2013-02-23 12:52:21.310513出ました。OKです。

■1時間前を得る
d = today - datetime.timedelta(hours = 1)
とやると、 2013-02-24 11:55:24.600223でました。タイムゾーンが違うんですけどまあいいでしょう。

■ 29時間後を得る
e = today + datetime.timedelta(hours = 29)
とやると、 2013-02-25 17:57:20.966985出ました。oKそうですね。

■5分前を得る
飽きてきました。
f = today - datetime.timedelta(minutes = 5)
2013-02-24 12:54:06.213152出ました。OKです。

■2011年3月11日からの経過日を得る
今日から引けばいいですね。
g = datetime.datetime(2011,3,11) - today
-717 days, 10:57:36.650128そういえば、today = datetime.datetime.today()としてましたので、全部時間がでてるですね。
ちなみに、date型と、datetime型で計算しようとすると怒られました。

■あと何年で50歳になるかを得る
これは今32歳ですので、今日から18年後を取得するってことでいいですかね。
いやーひととおり、色々やってたんですけど、よく考えたら18年ですね。

■1ヶ月前を得る
もう飽きたので眠いのでこれをやって終わりたいと思います。
i = today - datetime.timedelta(days=30)
2013-01-25 13:15:23.474761

終了です。

体得しました。修行のようでした。

Amazon 本 価格帯別販売点数調査 第二弾


アマゾン価格帯毎販売点数調査第二弾

100円単位バージョン

100円単位で調べたところ、0-99円は圧倒的の80万冊でしたが、これは電子書籍、青空文庫の関係であると思われます。2,000円以上50,000円で見てみると、2,700円〜2,799円台が最も多く、約6万点であることが分かりました。

以下は、2000円以上で、販売点数の多さ上位50位の表です。

MinPriceMaxPriceNumber of Books
2700279961750
2900299959648
3000309956439
2500259948213
2800289945611
2000209944932
3200329940019
2600269936034
3900399932371
3100319931282
2400249926640
3300339924939
5000509924926
3500359924917
3400349922853
2100219922500
2300239919947
4900499919715
2200229919468
3600369919302
3700379918584
4500459918497
4000409918364
3800389918350
4400449916632
4700479916099
4800489915133
4200429913945
5900599913541
9900999913250
8000809912270
100001009912237
5500559911857
4100419910880
6000609910494
4300439910374
4600469910168
790079999675
520052999311
540054999026
980098998554
700070997997
570057997562
950095997522
580058997128
17800178996930
21000210996881
690069996649
850085996245
10500105996221

total: 1,021,882

Amazon 本 価格帯別販売点数調査

2013年2月24日現在、アマゾンで和書を検索してみると、全部で5,595,348冊あると表示される。沢山ありますね。
ところで、アマゾンで売られている本はどの価格帯が一番多いのだろうか?まあ感覚的には1000円台かな?と思うんだけど、それを具体的に調べてみたいと思ってやってみた。あとは、数万円以上の高額本って結構あるのかな?とかも合わせて確認したい。

まずは、1000円〜10万円までを1000円単位で区切ってそれぞれの売ってる本の数を取得してテーブルで表示してみたいと思う。

はい、では結果を表示しましょう。

Pythonのオブジェクト指向の勉強(1)

Pythonのオブジェクト指向を学びたいと思います。

まずは、お気楽 Python プログラミング入門 第 5 回 オブジェクト指向の基礎知識をみながら勉強していきたいと思います。

まず読みながら勉強になったことを一覧化していきます。

  • クラス名の横に括弧をつけないと、継承されないだけで構文的には問題ない 
  • クラスを関数と同じ形式で呼び出すと、そのクラスのインスタンスを生成して返す 
  • Python のインスタンス変数は、代入操作が行われるときに生成される 
  • Python のインスタンス変数は、どこからでもアクセスすることができる(すべてがpublic) 
  • メソッドの第 1 引数にはインスタンスが渡される。Python では、この引数名を self と記述する習慣がある 
  • __init__() はインスタンスを生成するときに自動的に呼び出される特殊メソッド 
  • __init__() は return で値を返すとエラーになる

まだ途中だけど、満足した。今度続き読もう。

GAE jinja2 をちょっと効率的にする(くだらないこと)

GAEのjinja2というテンプレートエンジン?を使ってますが、一々出力するときの3行くらい書くのめんどくさいから、こうやって効率的にしたというくだらないことだけど。
def write(self,param,html):
    template = jinja_environment.get_template(html)
    self.response.out.write(template.render(param))
とやっておいて、使う時はこうやる。
write(self,{'aiueo':'aiueo'},'index.html')

google app engine - datastoreのけんきゅう

簡単なけんきゅうです。

class Price(db.Model):
    price = db.IntegerProperty()
このクラスを使います。

now = Price.all()
とやると、 <google.appengine.ext.db.Query object at 0x106845fd0>が返ってきます。これはデータが入っていようが、空だろうがこのような結果が返ってきます。

now = Price.all()
now = now.fetch(1)
とやると、 []が返ってきます。 当然これは、Priceにデータが入ってなかったからです。もしあれば、[<main.Price object at 0x1043a6210>]といったリストが返ってきます。

now = Price.all().fetch(1)
if not now:
    now = Price(price=100)
とやると、<main.Price object at 0x105e88810>が返ってきます。当然これはPriceにデータがなかったので、Priceオブジェクトを作成してnowに代入したからこの結果になってます。もしPriceにデータがあれば、[<main.Price object at 0x103f4aad0>]といったように、リストが返ってきます。

now = Price.all().fetch(1)
if not now: now = Price(price=100)
else: now = now[0]
とやると、Priceにデータがあってもなくても、<main.Price object at 0x106dcff90>といったようなものが返ってきます。

つまり

  • Price.all().fetch(1)とやると、オブジェクトのリストを返します。
  • Price.all().fetch(1)[0]とやれば、オブジェクト自体を取り出せます。(ただし、オブジェクトが無かった場合エラーになります)
  • よってfetch()後のリストが空でないことを確認した上で、オブジェクトを取り出します。

2013年2月23日土曜日

コールセンターの必要席数試算(アーランCと稼働率の関係)

コールセンターの必要席数を試算するときに、アーランを使う場合と使わない場合があると思います。

アーランを使う場合と使わない場合とで必要席数が大きく異なる場合、アーランを使わない場合に利用されている稼働率という指標を適当に設定しているケースがよくあります。そもそも、目標応答率が高いということは、取りこぼしがないように、入電が同時に沢山発生したときを考慮して席数を多めに配置するわけですから、当然ながら稼働率は下がります。なので、目標応答率70%のときも、95%のときも稼働率が80%なんてことは試算上はあってはならないのであります。

ということで、試しに、アーランCの結果を正とした場合に、各目標応答率に対する適正な稼働率を算出してみたいと思います。

各目標応答率に対する適正な稼働率を算出する


ちなみに、アーランを使わない場合の席数試算方法は下記になります。

必要席数 = 1時間当たり入電数 ÷ ( 60 ÷ ( 平均通話時間 + 平均後処理時間 ) × 稼働率 )
※平均通話時間と平均後処理時間の単位が”分”の場合の式です。単位が”秒”なら、60は、3600になります。

アーランを使う場合は、依然このブログで投稿した『JavaScriptでアーランCによりコールセンターの必要席数を計算する』で記載している計算方法を使いましょう。

ソースコードは下記です。下にあるボタンを押すとこれを起動させるようにしました。

1時間当たり入電数(件):
平均通話時間(分):
平均後処理時間(分):


<table>
<tr><td>1時間当たり入電数(件):</td><td><input id="call" type="text" size="50" /></td></tr>
<tr><td>平均通話時間(分):</td><td><input id="acd" type="text" size="50" /></td></tr>
<tr><td>平均後処理時間(分):</td><td><input id="acw" type="text" size="50" /></td></tr>
</table>
<input type="button" id="startBtn" value="稼働率を計算" /><br />
<div id="kadoritsuResult"></div>

<script type="text/javascript">
$(function(){
    $('#startBtn').click(function(){start();});
});

function start(){
 $('#kadoritsuResult').empty();
 var call = $('#call').val();
 var acd = 60*$('#acd').val();
 var acw = 60*$('#acw').val();
 var aht = acd+acw;
 var kadoritsu = 0;
 var sheet = 0;
 var text = '<br /><table class="kadoritsuTable">';
 
 text += '<tr><td>応答率</td><td>稼働率</td><td>必要席数</td></tr>';

 for(var sl=0.5;sl<1;sl+=0.01){
  sheet = erlangc(call,aht,sl);
  kadoritsu = Math.round((getKadoritsu(call,aht,sheet))*100)/100;
  text += '<tr><td>' + parseInt(sl*100) + '%</td><td>' + kadoritsu +'</td><td>' +
  sheet + '席</td></tr>';
 }

 text += '</table>';
 
 $('#kadoritsuResult').append(text);
}

function getKadoritsu(call,aht,sheet){
 return call/(3600/aht)/sheet
}

function erlangc(call,aht,sl){
    sl = 1 - sl;
    if(sl<=0)sl=0.0009;
    var erlang = aht*call/3600;
    var sheet = parseInt(erlang);
    var p = 1.0;
    var up = 1.0;
    var down = 0.0;
    var temp;

    while(p>=sl){
        sheet++;
        //分子
        for(var x=0; x<sheet; x++){
            up *= erlang/(sheet-x);
        }
        up = up*sheet/(sheet-erlang);
        //分母
        for(var x=0; x<sheet;x++){
            temp = 1.0;
            if(x!=0){
                for(var y=0; y<x;y++){
                    temp *= erlang/(x-y);
                }
            }
            down += temp;
        }
        down += up;
        p = up/down;
        up = 1.0; down = 0.0;
    }
    return sheet;
}
</script>

2013年2月21日木曜日

Product Advertising APIで効率よくItemSearchする(GAE×Python2.7)

こんばんは。タイトルのとおり効率よくItemSearchしたいと思ってます。
効率よくも何もないとお思いになられるかもしれませんが、本、DVD、おもちゃ、ホビー、TVゲームが全て検索できるItemSearch関数を作ろうということです。

私は本しかやったことなかったので、他のものも検索するにあたって、全て別の関数つくってたんじゃたまりません、ということで、全てを効率よく問題なく検索できる関数の姿を明らかにしようと思ってます。

今ここに本を検索する為の関数があります。

def bookSearch(browseNode,page,minPrice):
    pyzon = Pyzon(access_key_id, secret_access_key, associate_tag)
    xml = pyzon.ItemSearch(
                           search_index='Books', BrowseNode=str(browseNode),
                           ItemPage=str(page),Condition='All',MerchantId='All',
                           ResponseGroup='Small,SalesRank,Images,OfferSummary',
                           Sort='salesrank',MinimumPrice=str(minPrice)
                           )
    xml = urllib.unquote(xml)
    soup = BeautifulStoneSoup(xml)
    return soup

ご覧いただくと分かるかもしれませんが、pyzonとbeautifulsoupを使ってます。 ブラウズノードIDと、ページ、最低価格を引数にとり、検索をかけて、その結果をBeaftifulSoupのクラスにして返却しています。 さて、同じ引数でDVD、おもちゃ、ホビー、TVゲームも検索できるようにするには、今設定しているオプションが本以外でも問題なく使用できることを確認する必要があります。また、search_indexは、必ず設定しないといけないみたいですので、search_indexの値も引数にしないといけないのではないかと思ってます。

ItemSearch では、サーチインデックスの他に、1つまたは複数のパラメータ値を指定する必要があります。

さて、本以外でつかえる検索オプションを確認する為には、『SearchIndex-ItemSearch パラメータの組合せ (JP)』をみれば一目瞭然であります。 おおおお、DVDではなんと、最低金額設定ができないようです!

本(Books)DVD(DVD)TVゲーム(VideoGames)おもちゃ(Toys)ホビー(Hobbies)
Author, BrowseNode, Condition, ItemPage, Keywords, MaximumPrice, MerchantId, MinimumPrice, Power, Publisher, Sort, TitleActor, AudienceRating, Availability, BrowseNode, Count, Director, Format, ItemPage, Keywords, Magazines, Performer ,PostalCode, Publisher, Sort, State, TitleBrand, BrowseNode, Condition, ItemPage, Keywords, Manufacturer, MaximumPrice, MerchantId, MinimumPrice, Sort, TitleBrowseNode, Condition, ItemPage, Keywords, Manufacturer, MaximumPrice, MerchantId, MinimumPrice, Sort, TitleBrowseNode, Condition, ItemPage, Keywords, Manufacturer, MaximumPrice, MerchantId, MinimumPrice, Sort, Title

でも、このドキュメント古いから、一応試してみよう。DVDだけできないというのはおかしい。 やってみたら出来た。なんだかな。要するに、上記の本用の関数を引数にsearch_indexを加えるだけで問題ないらしい。まあ後は、レスポンスの取り方としては、大体全部同じなんだけど、itemattributesが、authorじゃなくてactorだったり、actorは複数あったりするのでこの辺りのレスポンスの取り方を注意すれば全然問題ないようだな。

ということで下記のようになりました。

def itemSearch(searchIndex,browseNode,page,minPrice):
    pyzon = Pyzon(access_key_id, secret_access_key, associate_tag)
    xml = pyzon.ItemSearch(
                           search_index=searchIndex, BrowseNode=str(browseNode),
                           ItemPage=str(page),Condition='All',MerchantId='All',
                           ResponseGroup='Small,SalesRank,Images,OfferSummary',
                           Sort='salesrank',MinimumPrice=str(minPrice)
                           )
    xml = urllib.unquote(xml)
    soup = BeautifulStoneSoup(xml)
    return soup
なんかどうってことないことでしたね。

2013年2月19日火曜日

Product Advertising APIのBrowseNodeLookupで本(和書)のBrowseNodeを全部取得する(2)


はい、前回やっていたことはかなり非効率であることが分かりました。再帰するのか否かはおいておきまして、そもそもBrowseNodeLookupの結果のルールに先程気づきまして、非常に複雑でめんどうなことをしていたと気づいた次第です。

さて、何がルールかというと、RootのLookupをした場合は、ancestorが一つだけあります。中間のLookupをした場合は、ancestorが複数あります。最下層のLookupをした場合は、ancestorがございません。このancestorの数を確認するだけで、最下層か否かを確認することが可能であります。どうでしょうか?衝撃的事実であったのではないかと思います。ぜひ、Browsenodeの取得に苦慮されている方がいましたら、この事実を教えてあげるといいと思います。

それでは失礼します。

コードは大体下記のようになるのではないでしょうか?

browsenodes = result.browsenodelookupresponse.browsenodes
ancestorsList = browsenodes.findAll('ancestors')
ancestorIdList = []

for ancestors in ancestorsList:
    if ancestors.browsenode:
        ancestorIdList.append(int(ancestors.browsenode.browsenodeid.contents[0]))
        ancestors.extract()
        
browseNodeList = browsenodes.findAll('browsenode')

#最下層じゃない
if len(ancestorIdList) > 0:
    #最下層じゃない場合の処理

#最下層
else:
    #最下層の場合の処理

2013年2月18日月曜日

Product Advertising APIのBrowseNodeLookupで本(和書)のBrowseNodeを全部取得する

Product Advertising APIのBrowseNodeLookupで本(和書)のBrowseNodeを全部取得したいと思います。

ここに、BrowseNodeLookupの説明が書いてあるんですがちょっと古くて、2013年2月現在では別の結果を返している気がするんですが。最新版ないんですかね?そもそもgoogle先生に聞くと、2011年頃に大幅な改訂がなされたとかで皆さん大騒ぎをしているんですがそれらの結果を反映した最新版が見つからないんですよね??英語だとあるんですかね。まあ自分で試して結果をみるのが一番確かだということで、試してみてます。

本(和書)のブラウズノードは、465610ですので、ここからどんどん下に掘っていきたいと思います。調べた感じですと、browsenodeを探して、その中にchildrenかancestorsが入ってたら飛ばす、両方とも入ってなかったら、そのbrowsenodeidを基に更に掘るという感じでどうだろうかと思っております。掘っても該当するbrowsenodeがなければそこが最下層であると認識します。僕は階層を明確化したいのではなく、最下層のbrowsenodeidの一覧を取得したいので、最下層であると判断されたら、browsenodelookupresponse > browsenodes > request > browsenodelookuprequest > browsenodeidを取得してリストに追加するというイメージでやってみたいと思います。いやいや今調べてたんだけど、そういうわけでもないんですね。なんなんだこのめちゃくちゃなresultは。まあ利用目的が違うとでもいいたいんだろうか。ドリルダウンで全ての属性を知りたいと思うことはあるだろうし、最下層の属性だけ抽出したいと思うこともあるだろうに。なぜこうもめんどくさい仕様になっているんだろうか。ということで、ancestorsが入ってなくてもancestorsであることもあることが分かりましたので、ancestorsを持っているタグ以降に出てくるものは全部ancestorsであるという条件も前提にいれましょう。

さて、BrowseNodeLookupで45610をみて、該当するidをforでBrowseNodeLookupすることを繰り返してみましょー。

class GetBrowseNode(webapp2.RequestHandler):
    def get(self):         
            browseNodeWasyo = 465610
            resultList = browseNodeCheck(browseNodeLookup(browseNodeWasyo))
            templateValues = {'result':resultList} 
            template = jinja_environment.get_template('index.html')
            self.response.out.write(template.render(templateValues))

def browseNodeLookup(browseNodeId):
    pyzon = Pyzon(access_key_id, secret_access_key, associate_tag)
    xml = pyzon.BrowseNodeLookup(browsenode_id=str(browseNodeId))
    xml = urllib.unquote(xml)
    soup = BeautifulStoneSoup(xml)
    return soup

def browseNodeCheck(result):
    resultList = []
    
    if not result.errors:
        browsenodes = result.browsenodelookupresponse.browsenodes
        ancestorsList = browsenodes.findAll('ancestors')
        for ancestors in ancestorsList:
            if ancestors.browsenode: ancestors.extract()
        browseNodeList = browsenodes.findAll('browsenode')
        childrenCnt = 0
        AncestorsCnt = 0
        
        for node in browseNodeList:
            if not node.children and not node.ancestors:
                if AncestorsCnt > 0:
                    AncestorsCnt += 1
                else:
                    time.sleep(1)
                    resultList += browseNodeCheck(browseNodeLookup(node.browsenodeid.contents[0]))
            else:
                if node.ancestors:
                    AncestorsCnt += 1
                elif node.children:
                    childrenCnt += 1
                    
        if  (childrenCnt + AncestorsCnt) == len(browseNodeList):
            browsenodeid = browsenodes.request.browsenodelookuprequest.browsenodeid.contents[0]
            resultList.append(int(browsenodeid))
            logging.debug(u'browsenodeid追加: ' + str(browsenodeid))
        
    else:
        code = result.errors.error.code.string
        message = result.errors.error.message.string
        logging.error(u'AmazonError! code: ' + code + u' message: ' + message)
    
    return resultList

これは、GAE、Pythonでつくっていまして、ライブラリは、PyzonとBeautifulSoupを使ってます。ブラウズノードを確認して、まだ下が有る場合はどんどん突き進み、もう下がない場合はリストにbrowsenodeidを追加するようになっております。再帰してます。ただ、これだと超時間がかかりまして、GAEのローカル環境ですと途中でエラーになりました。いずれにしてもこれを毎日のように実行すると考えるとかなり非現実的です。再帰が使える状況って限られますね。よって、都度都度検索型に変えようと思います。失礼いたしました。

再帰? (Python)

これ再帰?

def testdef(x):
    testList = []
    testList.append(x*2)
    if x >0: testList += testdef(x-1)
    return testList

testdefに10を入れると、[20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0]が出てきます。 これ再帰でしょう??初めて再帰をやった!?お恥ずかしいです。

2013年2月12日火曜日

cakePHP2.2 Bakeを研究してみる

私の環境は、mac、Eclipse、XAMPP、PHP5.3、cakePHP2.2.5、MySQLです。

Bakeとはデータベースのテーブルさえ作っておけば、瞬時にcakePHPのモデルとビューとコントローラーを自動で作ってくれる機能のことであります。 便利なんじゃないでしょうか。ベースとなる部分って基本的に固定された内容を毎回作成するわけですから、そのベースを多少修正するのは当たり前としても前段となる作業の大部分を自動化できるっていうのは大変有り難いことです。加えて、cakePHPのcookbookというリファレンスは、Bakeを使う前提で解説されている箇所も結構多そうなので、とりあえずBakeはマスターしておこうと思いました。

さて、Bakeの解説はここに載っていますので、こちらを見ながら試していきたいと思います。

下準備(プロジェクト作成〜データベース設定)

すんなりいくのか不安ですが、まずはEcliplse上でcakePHPのプロジェクトを作成すると共に、MySQLのデータベースを作成し、テーブルも作成します。 そして、cakePHPとデータベースを連携させる為の設定を実施します。ここまでのやり方詳細は、こちらに記載しましたので分からない場合はご確認ください。

さて、今回はbaketestという名前でプロジェクトを作成しました。フォルダは /Applications/XAMPP/xamppfiles/htdocs/baketest にあります。 データベースは、baketestという名前でこれまた作成しました。テーブルは下記2点を作成しました。

cakePHP2.2.5 ー ダウンロードから開発開始までの準備作業詳細を徹底解説!(Mac × Eclipse × XAMPP)


cakePHPを使うの結構久しぶりで、cakePHPの開発環境を削除してしまっていたことから、一からcakePHPをダウンロードするところから始めます。 ちなみに、私の開発環境は、Mac、Eclipse、PHP5.3です。ローカルのウェブサーバーはXAMPPを使っています。

cakePHPのダウンロード

ダウンロードはここからできます。今はver2.2.5が安定板の最新になっていますね。

cakePHPのインストール

インストールはこのページをみたら出来ますね。とりあえずウェブサーバにダウンロードしてきたcakePHPのフォルダをぶち込むだけで、インストール完了という超お手軽なようです。そういえばそうでした。でも、他にも2パターンインストールの方法があるようです。”運用”と”応用”は後でやってみます。
  • 開発(Development): 簡単にはじめることができますが、アプリケーションのURLには、CakePHPをインストールしたディレクトリ名が入ります。 他の設定と比べるとセキュリティ面はやや弱くなります。
  • 運用(Production): Webサーバのドキュメントルートを設定できる必要がありますが、URLをクリーンにでき、セキュリティを固くできます。
  • 応用(Advanced): 幾つかの設定により、CakePHPの重要な各ディレクトリをファイルシステムの異なる場所に配置することができるので、 多くのCakePHPアプリケーションがひとつのCakePHPコアライブラリのフォルダを共有することなどが可能です。

2013年2月9日土曜日

ありえないマーケティング

ありえないマーケティングを読んだ。カフェで2時間位で読んだ。読み返してないけど、やっぱり当たり前のことを当たり前にしっかり全部やることが重要なんだなあと思った。情報過多の時代なので情報提供により顧客をつかむ方法は価値が低下してきているので、あえて情報提供しませんというスタンスをうたいつつ、とはいえやはり情報提供を定期的に実施していくことで顧客リストをつくっていくのだよと書いてあった気がする。

インターネットビジネスは検索エンジン対応が重要で、検索エンジンは課題をもった人々がキーワードを入れて検索するわけですから、そのキーワードから想定される課題の本質に対してしっかりと応えないといけないと書いてあった気がする。キーワードは、ビッグワードはビッグな会社がうごめいているから、スモールニッチワードでビジネス展開をすることで、小資本の貧乏起業家も勝てる可能性が出てくるんだよと書いてあった。

2013年2月7日木曜日

ソーシャルもうええねん

『ソーシャルもうええねん』をこの前読みました。ここ最近の本で一番面白かった。
僕もソーシャルはもうええねんと思いました。
それにしても、この人はやっぱりネットで少し知ってたんだけど超すごくて、三浦大地以降、久しぶりに尊敬しました。

ブルーオーシャン戦略ってめずらしく、ものすごく分かり易いカタカナだと思っていまして、なぜ分厚い本がこのキーワードがお題で出来上がるのか分からないのですが、やっぱりブルーオーシャン戦略一本で人生生きていかないと死んでしまうのだと思いました。
そして全ては現在のご時世に合わせた世渡りと、ホンモノの武器を持たなくてはいけないんだろうなと思いました。

まあホンモノっていっても大体みんなたかが知れていたりもするでしょうし、そういう相対的な競合の中でのホンモノではあると思いますが、そんなせこいことを言ってると、ホンモノの武器は持てないんだろうとも思いました。

2013年2月4日月曜日

GAEでメールを送信する (Python)

GAEでメール送信するのは強烈に簡単です。
久しぶりで忘れてたのでメモっておきます。メモる必要すらないくらい簡単です。

ここを見ればすぐ分かります。

使い方イメージはこんな感じです。

from google.appengine.api import mail

class Mail(webapp2.RequestHandler):
    def post(self):
        company = cgi.escape(self.request.get('company'), True)
        name = cgi.escape(self.request.get('name'), True)
        mailAd = cgi.escape(self.request.get('mail'), True)
        
        if company and name and mailAd:
            sender_address = "Hoge Hogeo <hogehogeo@hogehoge.com>"
            subject = u"ほげほげ"
            body = u'ほげほげほげ\n\n'
            body += u'会社名: ' + company + u'\n'
            body += u'氏名: ' + name

            mail.send_mail(sender_address, mailAd, subject, body)
            
            self.redirect('/mail_success') 

2013年2月3日日曜日

『100円のコーラを1000円で売る方法』を読んでみた

『100円のコーラを1000円で売る方法』を読んでみました。

 

感想

マーケティング理論素人の俺的には結構おもしろかった。
自分の会社の商品はレッドオーシャンでぐっちゃぐちゃの市場が多いけど、面白い商品もある。売り方がキャズムを意識してないから、セールスが分散されて非効率なんだと思った。

ストーリー形式で、破天荒な女子が主人公になってます。まあ世の社会人にとっては常識はずれということで好きになれない人もいるかもしれませんが、俺的には好きですね。究極的にマーケティング理論を知らない破天荒女子ですので、まさに初心者用のマーケティング本ですね。学べる理論はストーリー仕立てなので多くはない(広く浅い)とも言えると思いますが、初心者には分かり易いし面白いしお勧めです。そもそも分厚いマーケティング理論の本も場合によっては冗長的だったりするでしょうし。

こういう本で手っ取り早く気づきを得るというのも中々いい方法だと思いました。

メモ

  • ほとんどの企業は時間とコストをかけて他社と同じことを一生懸命自社でもやろうとしています
  • バリュープロポジションとは顧客が望んでいて、他社では提供できなくて、自社では提供できる価値
  • 業界が成熟していることは差別化できない理由にはなりません。そう思うのなら頭を使っていない証拠です。
  • あなたのようにお客さんのいいなりになることを、最近マーケティングの世界では”カスタマー・マイオピア”と呼んでいます。
  • 世の中のほとんどの企業は本来価格勝負をしてはいけないのです
  • ちゃんと売れるためには、コミュニケーションが、戦略的に一貫性があることが大切です。