Python Bottle&Cork サンプルPG

Pythonのbottle.pyというフレームワークがありますが、なかなかわかりやすく使いかってが良いのでご紹介します。
下記はWEBで自分のサイトのランクを調べるプログラム。ログインして条件入力するページへ飛び検索開始すると1分ぐらいで順位を表示します。

あらかじめbottle,bottle-cork,google,BeautifulSoup,Beakerをpipもしくはeasy_installで入れておくこと。
bottle-corkはbottleのセッション管理モジュール。あまり詳しい情報が本サイトを見てもないのでソースコードを見るのが一番わかりやすい。

尚、プログラムはadapter.wsgiを使ってApache WEBサーバと連携するようにしてください。

必要とするPGファイル

  • adapter.wsgi
  • index.py
  • admin.py
  • rank.py
  • login.py
  • make_conf.py

テンプレート(views)

  • index.tpl
  • login_form.tpl

staticファイル(static)

  • css/style.css
  • js/protoypr.js
  • js/rankget.js

confファイル(conf)

  • register.json
  • user.json
  • roles.json
adapter.cgi
# -*- coding:utf-8 -*-
import sys, os ,bottle
dirpath = os.path.dirname(os.path.abspath(__file__))
sys.path.append(dirpath)
os.chdir(dirpath)
from index import app
application = app
rank_get.js
function ajaxReq(url){
         var p1 = document.js.url.value;
         var p2 = document.js.keywords.value;
         var p3 = document.js.number.value;
         var para = new String();
         para += '&url=';
         para += p1;
         para += '&keywords=';
         para += p2;
         para += '&number=';
         para += p3;
         new Ajax.Request(url, {
                          method: "get",
                          parameters: para,
                          onSuccess:function(httpObj){
                          $("result1").innerHTML = httpObj.responseText;
                          $("result2").innerHTML = httpObj.responseXML;
                          },
                          onFailure:function(httpObj){
                          $("result1").innerHTML = "エラー及び取得順位ゼロが要因で読み込めませんでした";
                          }
                                });
     }

     Ajax.Responders.register({
         onCreate: function() {
         Element.show($('loading'));
     },

     onComplete: function() {
         Element.hide('loading');
         alert('complete');
     }
    });

   Event.observe(window, 'load', function() {
      Element.hide('loading');
    }, false);
make_conf.py
#!/usr/bin/env python
#
#
# Regenerate files in example_conf

from datetime import datetime
from cork import Cork

def populate_conf_directory():
    cork = Cork('conf', initialize=True)

    cork._store.roles['admin'] = 100
    cork._store.roles['editor'] = 60
    cork._store.roles['user'] = 50
    cork._store.save_roles()

    tstamp = str(datetime.utcnow())
    username = password = 'admin'
    cork._store.users[username] = {
        'role': 'admin',
        'hash': cork._hash(username, password),
        'email_addr': username + '@localhost.local',
        'desc': username + ' test user',
        'creation_date': tstamp
    }
    username = password = 'guest'
    cork._store.users[username] = {
        'role': 'user',
        'hash': cork._hash(username, password),
        'email_addr': username + '@localhost.local',
        'desc': username + ' test user',
        'creation_date': tstamp
    }
    cork._store.save_users()

if __name__ == '__main__':
    populate_conf_directory()
rank.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from google import search
from BeautifulSoup import BeautifulSoup
import urllib

class webRank(object):
      def __init__(self):
          self.lang = 'ja'

      def search(self,domain,mysite,words,st0,st1):
          cnt = 1
          for url in search( words ,tld=domain, lang=self.lang,start=st0, stop=st1):
                soup = BeautifulSoup(urllib.urlopen(url))
                if url.find(mysite) != -1:
                       try:
                           title =  soup.find('title').string
                       except:
                           title = ""
                       #return str(cnt) + u"位" + url + "  " + title
                       return [str(cnt),url,title]
                cnt += 1
admin.py
import bottle
from beaker.middleware import SessionMiddleware
from cork import Cork
from login import *

@bottle.route('/admin')
def admin():
    """Only administrators can see this"""
    aaa.require(role='admin', fail_redirect='/sorry_page')
    return 'Welcome administrators'

@bottle.route('/register', method='POST')
def register():
    """Users can create new accounts, but only with 'user' role"""
    username = request.POST.get('user', '')
    password = request.POST.get('pwd', '')
    email_addr = request.POST.get('email_addr', '')
    aaa.register(username, password, email_addr)
    return 'Please check your inbox.'
~
login.py
import bottle
from beaker.middleware import SessionMiddleware
from cork import Cork

# Setup Beaker middleware to handle sessions and cookies
app = bottle.default_app()
session_opts = {
        'session.type': 'cookie',
        'session.validate_key': True,
}
app = SessionMiddleware(app, session_opts)

# Use users.json and roles.json in the local example_conf directory
aaa = Cork('conf')

@bottle.route('/login', method='POST')
def login():
    username = bottle.request.POST.get('user', '')
    password = bottle.request.POST.get('pwd', '')
#    return username,password
    aaa.login(username, password, success_redirect='/', fail_redirect='/login')

@bottle.route('/login')
@bottle.view('login_form')
def login_form():
    """Serve login form"""
    return {}

@bottle.route('/logout')
def logout():
    aaa.logout(success_redirect='/login')

@bottle.route('/sorry_page')
def sorry_page():
    """Serve sorry page"""
    return '<p>Sorry, you are not authorized to perform this action</p>'
index.py
# -*- coding: utf-8 -*-
import bottle
from bottle import route, request, response, template,static_file
from beaker.middleware import SessionMiddleware
from cork import Cork
from rank import webRank
# Setup Beaker middleware to handle sessions and cookies
app = bottle.default_app()
session_opts = {
        'session.type': 'cookie',
        'session.validate_key': True,
}app = SessionMiddleware(app, session_opts)
# Use users.json and roles.json in the local example_conf directory
aaa = Cork('conf')

from login import *
from admin import *

@route('/static/<filepath:path>')
def static(filepath):
    return static_file(filepath, root="./static")

@bottle.route('/')
@bottle.view('index')
def index():
    """Only authenticated users can see this"""
    aaa.require(fail_redirect='/sorry_page')
    return {}

@bottle.route('/rank', method="GET")
@bottle.view('web_rank')
def rank():
    """Only authenticated users can see this"""
    aaa.require(fail_redirect='/sorry_page')
    web = webRank()
    words = bottle.request.GET.get('keywords', '')
    url = bottle.request.GET.get('url', '')
    stop = bottle.request.GET.get('number', '')
    result = web.search("co.jp",url,words,1,int(stop))
    return {'url':result[1],'title':result[2],'rank':result[0]}

# Web application main

def main():

    bottle.debug(True)
    # Start the Bottle webapp
    bottle.run(app=app,host="0.0.0.0", quiet=false, reloader=True)

if __name__ == "__main__":
    main()
login_form.tpl
<!doctype html>
<html lang="ja">
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
</head>
<body>

  <div class="login_box">
      <h2>管理ページログイン</h2>
      <p>ログイン項目を入力してください</p>
      <form action="/login" method="post" name="login">
          ログイン&nbsp;&nbsp;&nbsp:<input type="text" name="user" /><br>
          パスワード:<input type="password" name="pwd" /><br>
          <button type="submit" name="submit" > LOGIN </button>
          <button type="button" class="close"> CANCEL </button>
      </form>
  </div>

</body>
</html>