Lightweight Language Saturday P3 発表資料

RSSビューアー■Pytnon 2.2以上
要JapaneseCodecs
http://www.python.jp/Zope/download/JapaneseCodecs■使用モジュール
xml.sax.handler
XMLパーサのハンドラモジュール
xml.sax
SAXモジュール
■説明
このプログラムは、http://slahdot.jp/slashdot.rdf を解析し、情報を整形してHTML出力をします。
また、オリジナルをもとにしたRSS3形式のものも処理することができます。
rssget.py
1 #!/usr/bin/env python
72 # RSS3形式のパース
2 """Slashdot JapanのRSSを解析するモジュール
733
74 class RSS3Parser:
4 サイトにあるオリジナルのRSSやそれをもとにしたRSS3形式のものを解析する。 75
def parse_block(self, block):5 """76"ブロックを辞書オブジェクトのリストにする"
677
7 from xml.sax.handler import ContentHandler78
dic = {}
8 from xml.sax import make_parser
79
for key, val in [line.split(':', 1) for line in block.split('\n')]:9 from cgi import escape80
dic[key] = val.strip()
10 from StringIO import StringIO
81
return dic
1182
12 class RSSHandler(ContentHandler):83
def parse(self, fp):
13
"RSSパーサハンドラ"
84"ファイルオブジェクトを読みこんで辞書のリストに加工する"
14
85
15# データのブロックとして認識する要素名
86# 従来の表記方式
16
BLOCK_ELEMENTS = ('channel', 'item')87# blocks = []1788
# for block in open(RSSFILE).read().split('\n\n'):18# ブロック内のデータとして認識する要素名
89#block = block.strip()
19
ACCEPT_ELEMENTS = (90#if block: blocks.append(parse_block(block))20'title', 'link', 'description', 'language', 'rights',
91
21'created', 'publisher', 'creator', 'subject',92# リスト内包表記
22'updatePeriod', 'updateFrequency', 'updateBase')
93
return [self.parse_block(block)23
94
for block in fp.read().split('\n\n') if block.strip()]24# エンコード時のコデック名
95
25
ENCODING = 'utf-8'
96 def parse_rss3(fp):26
97
return RSS3Parser().parse(fp)27
def __init__(self):28
self.blocks = []#ブロックのリスト
rssget.cgi
29
self.block = {}#処理中のブロックデータがはいるバッファ
30
self.nowtext = None #現在のテキストノード情報
1 #!/usr/bin/env python
31
self.in_block = 0#ブロック内かどうかのフラグ
2 """Slashdot JapanのRDFをHTMLに変換して表示するCGI
32
self.buf = StringIO()
3
33
4 RSS解析モジュール(rssget.py)でRSSを解析し、表示する。
34
def characters(self, text):
5 """35"文字列データが出現したときのハンドラ"
636
7 from rssget import parse_rss37
if self.in_block:8 from urllib import urlopen
38
self.buf.write(escape(text.encode(self.ENCODING)).strip())
939
10 RSSFILE_URL = 'http://slashdot.jp/slashdot.rdf'40
def startElement(self, name, attrs):
11
41"開始タグが出現したときのハンドラ"
12 def render_html(title, value):42
13
if title == 'link':
43
if name in self.BLOCK_ELEMENTS:
14value = '<a href="%s">%s</a>' % (value, value)
44
self.in_block = 1
15
return '<tr><th>%s</th><td>%s</td></tr>' % (title, value)45
16
46
def endElement(self, name):
17 # HTMLの出力47"終了タグ出現したときのハンドラ"184819 # ヘッダ部
49
if self.in_block:20 print 'Content-Type: text/html; charset=utf-8'
50
name = name.encode(self.ENCODING).split(':', 1)[-1]
21 print '''51
if name in self.ACCEPT_ELEMENTS:
22 <html>
52
self.block[name] = self.buf.getvalue()
23 <head>53
self.buf = StringIO()
24 <title>RSS feed</title>
54
if name in self.BLOCK_ELEMENTS:
25 </head>55
self.in_block = 0
26 <body>
56
if self.block:27 '''
57
self.blocks.append(self.block)28
58
self.block = {}29 # サイト情報
59
30 blocks = parse_rss(urlopen(RSSFILE_URL))
60
def getblocks(self):
31 header = blocks[0]61"処理済のブロックのリストを返す"
32 print '<table border="1">'62
33 for key in header.keys():63
return self.blocks
34
print render_html(key, header[key])64
35 print '</table>'
65 def parse_rss(fp):3666parser = make_parser()37 print '<hr>'67
handler = RSSHandler()
38
68
parser.setContentHandler(handler)
39 # ニュースサマリ
69parser.parse(fp)40 bodies = blocks[1:]70
return handler.getblocks()41 for body in bodies:71
42
print '<table border="1">'43
for key in body.keys():44
print render_html(key, body[key])
45
print '</table>'46
47 # フッタ部
48 print '''49 </table>
50 </body>51 </html>
52 '''

Copyright (c) 2001-2002 Python Japan User GroupLightweight Language Saturday P3 発表資料

Apacheログ解析■Pytnon 2.2以上■使用モジュール
time
時間や時間の書式のフォーマットを処理するためのモジュール■説明
このプログラムは、ApacheのCombinedアクセスログを解析し、IPアドレスごとの滞在時間と、全体の平均滞在時間を求めます
analyze.py
1 #!/usr/bin/python
2
3 from __future__ import generators
4 from time import strptime, strftime
5
6 LOGFILE = 'access_log_masked'
78 #9 STILLTIME = 60 * 5
10
11 def parse_access_time(line):
12"It is parse to log line, so it returns timestamp and client address."
13
14
tokens = line.split()
15
return long(strftime(
16'%s', strptime(tokens[3][1:], '%d/%b/%Y:%H:%M:%S'))), tokens[0]17
18 def make_accessdata1():
19
items = []20
for line in open(LOGFILE).readlines():21
items.append(parse_access_time(line))
22
return items
23
24 def make_accessdata2():25
return [parse_access_time(line) for line in open(LOGFILE).readlines()]26
27 def make_accessdata3():
28
for line in open(LOGFILE).readlines():29
yield parse_access_time(line)
30
31 make_accessdata = make_accessdata1
32
33 def analyze():34
ctable = {}35
exist_times = []36
accessdata = make_accessdata()
37
accessdata.sort()
38
for accesstime, client in accessdata:
39
for exit_client in ctable.keys():40
lastaccess, firstaccess = ctable[exit_client]41
if STILLTIME < accesstime - lastaccess:42del ctable[exit_client]
43
print '%s:%d sec' % (exit_client, lastaccess - firstaccess)44
exist_times.append(lastaccess - firstaccess)45
cur = ctable.get(client)46
if cur:47
lastaccess, firstaccess = cur
48
ctable[client] = accesstime, firstaccess
49
else:
50
ctable[client] = accesstime, accesstime
51
52
print 'Total AVG sec:', float(reduce(lambda a,b: a+b, exist_times)) / len(exist_times)
53
54 if __name__ == '__main__':55
analyze()

Copyright (c) 2001-2002 Python Japan User GroupLightweight Language Saturday P3 発表資料

じゃんけんクライアント■Pytnon 2.2以上■使用モジュールsocket
低レベルの socket モジュール
random乱数を扱うモジュール
thread低レベルの thread モジュール■説明
このプログラムは、socket モジュールを使って、じゃんけんサーバとデータを送受信します。
tcp でじゃんけんサーバからの CALL を受けて手を送信する部分は thread を使って メインループのudpで勝敗を受ける部分から分離しています。
Python には SocketServer や asyncore という、よりハイレベルな socket プログラミング用の標準モジュー
ルがあります。
jankenclient.py
1 #!/usr/bin/env python
2
3 import sys, socket, random, thread
4
5 HOST = sys.argv[1]6 PORT = 2003
7 LISTEN_PORT = 2004
8910 def sendClientInfo():
11addr = socket.gethostbyname(socket.gethostname())
12s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
13
s.connect((HOST, PORT))
14
s.send('%s:%s\r\n' % (addr, LISTEN_PORT))
15
16
17 def Janken():18
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
19
s.bind(('', LISTEN_PORT))
20
s.listen(1)21while True:
22
conn, addr = s.accept()23
f = conn.makefile("r+b")
24
data = f.readline()
25
if data=='CALL\r\n':26
hand = random.choice(['PAPER', 'SCISSORS', 'ROCK'])
27
conn.send(hand+'\r\n')28
29
30 thread.start_new_thread(Janken, ())
31
32 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
33 s.bind(('', LISTEN_PORT))
34
35 sendClientInfo()
36
37 while True:
38
data += s.recv(1)39
if data[-2:] == '\r\n':40
if data.startswith('100'):
41
print '一人勝ち'
42
elif data.startswith('110'):43
print '勝ち'44
elif data.startswith('120'):
45
print '負け'46
elif data.startswith('130'):
47
print ''
48
data = ''Copyright (c) 2001-2002 Python Japan User Group