<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
		xmlns:xhtml="http://www.w3.org/1999/xhtml"
>

<channel>
	<title>Azrael &#187; program</title>
	<atom:link href="http://zafiel.wingall.com/archives/tag/program/feed" rel="self" type="application/rss+xml" />
	<link>http://zafiel.wingall.com</link>
	<description>日常と非日常</description>
	<lastBuildDate>Sat, 04 Feb 2012 05:01:40 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://zafiel.wingall.com/archives/tag/program/feed" />
		<item>
		<title>Flask+MongoDBのてきとーアプリ書いた (Python)</title>
		<link>http://zafiel.wingall.com/archives/2012011720252437.php?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=flaskmongodb%25e3%2581%25ae%25e3%2581%25a6%25e3%2581%258d%25e3%2581%25a8%25e3%2583%25bc%25e3%2582%25a2%25e3%2583%2597%25e3%2583%25aa%25e6%259b%25b8%25e3%2581%2584%25e3%2581%259f-python</link>
		<comments>http://zafiel.wingall.com/archives/2012011720252437.php#comments</comments>
		<pubDate>Tue, 17 Jan 2012 11:25:39 +0000</pubDate>
		<dc:creator>wg_koro</dc:creator>
				<category><![CDATA[Program]]></category>
		<category><![CDATA[program]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://zafiel.wingall.com/?p=2437</guid>
		<description><![CDATA[MongoDBをさわり始めたんですが、シンプルでいいすな(・∀・)！ つーわけで、Flask + MongoDBのてきとーアプリをざくっと書いてみた。 超手抜き適当コード(所要時間20分ｗ)。 https://githu &#8230; <a href="http://zafiel.wingall.com/archives/2012011720252437.php">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src='http://zafiel.wingall.com/img/python-logo.png' width='211' height='71'><br />
MongoDBをさわり始めたんですが、シンプルでいいすな(・∀・)！<br />
つーわけで、Flask + MongoDBのてきとーアプリをざくっと書いてみた。<br />
超手抜き適当コード(所要時間20分ｗ)。<br />
<a href="https://github.com/wgkoro/flask_mongodb" target='_blank'>https://github.com/wgkoro/flask_mongodb</a></p>
<p>MongoDBとFlaskとPyMongo入ってれば<br />
$ python app/app.py<br />
で動くはず。</p>
<p>「データが存在していればUPDATE, 無ければINSERT」<br />
ってこんな風に書いちゃったけど(↓)、もっと効率的な方法あるよなぁきっと…。</p>
<pre class="brush: python; title: ; notranslate">
user = coll.find_one({ 'user_id' : uid })
if user:
    coll.update(user, data, upsert=True)
else:
    coll.insert(data)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://zafiel.wingall.com/archives/2012011720252437.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://zafiel.wingall.com/archives/2012011720252437.php" />
	</item>
		<item>
		<title>割と知られていないような気がするurlparseとoptparse (Python)</title>
		<link>http://zafiel.wingall.com/archives/2011120202302358.php?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e5%2589%25b2%25e3%2581%25a8%25e7%259f%25a5%25e3%2582%2589%25e3%2582%258c%25e3%2581%25a6%25e3%2581%2584%25e3%2581%25aa%25e3%2581%2584%25e3%2582%2588%25e3%2581%2586%25e3%2581%25aa%25e6%25b0%2597%25e3%2581%258c%25e3%2581%2599%25e3%2582%258burlparse%25e3%2581%25a8optparse-python</link>
		<comments>http://zafiel.wingall.com/archives/2011120202302358.php#comments</comments>
		<pubDate>Thu, 01 Dec 2011 17:30:47 +0000</pubDate>
		<dc:creator>wg_koro</dc:creator>
				<category><![CDATA[Program]]></category>
		<category><![CDATA[program]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://zafiel.wingall.com/?p=2358</guid>
		<description><![CDATA[もう12月ですよ。 月日の経つのは早い早い…。 つい先ほど浅草で飲んできました。 一緒に飲んだのはプログラミング大好きな友人(・∀・) 途中、Pythonの話になったので「urlparse」と「optparse」を紹介し &#8230; <a href="http://zafiel.wingall.com/archives/2011120202302358.php">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://zafiel.wingall.com/img/python-logo.png"><img src="http://zafiel.wingall.com/img/python-logo.png" alt="" title="python-logo" width="211" height="71" class="alignnone size-full wp-image-2362" /></a></p>
<p>もう12月ですよ。<br />
月日の経つのは早い早い…。</p>
<p>つい先ほど浅草で飲んできました。<br />
一緒に飲んだのはプログラミング大好きな友人(・∀・)</p>
<p>途中、Pythonの話になったので「urlparse」と「optparse」を紹介してみた。<br />
optparseを知っている人は結構いそうだけど、<br />
urlparseは意外と知られていない気がする。</p>
<p>というわけで、簡単に紹介。<br />
<span id="more-2358"></span><br />
<strong>urlparse</strong>はURL形式の文字列を操作しやすくしてくれるモジュールです。<br />
例えば、↓のような文字列。<br />
&#8216;http://www.google.co.jp/search?gcx=c&#038;sourceid=chrome&#038;ie=UTF-8&#038;q=googlemap&#8217;<br />
これをURLとして扱いやすくしませう。<br />
あ、このモジュールはPython2.6.xからは標準で入っているはず…。</p>
<pre class="brush: bash; title: ; notranslate">
&gt;&gt;&gt; from urlparse import urlparse, parse_qs, urljoin
&gt;&gt;&gt; url = 'http://www.google.co.jp/search?gcx=c&amp;sourceid=chrome&amp;ie=UTF-8&amp;q=googlemap'
&gt;&gt;&gt; parsed = urlparse(url) # パースする

# こんな感じに解析してくれます(・∀・)
&gt;&gt;&gt; print parsed
ParseResult(scheme='http', netloc='www.google.co.jp', path='/search', params='', query='gcx=c&amp;sourceid=chrome&amp;ie=UTF-8&amp;q=googlemap', fragment='')

&gt;&gt;&gt; print parsed.netloc
www.google.co.jp

&gt;&gt;&gt; print parsed.query
gcx=c&amp;sourceid=chrome&amp;ie=UTF-8&amp;q=googlemap

# パラメータも、parse_qs使うと辞書にしてくれます。
&gt;&gt;&gt; params = parse_qs(parsed.query, True)
&gt;&gt;&gt; print params
{'sourceid': ['chrome'], 'gcx': ['c'], 'ie': ['UTF-8'], 'q': ['googlemap']}
</pre>
<p>知っておくとURL文字列を処理するときにすごく楽ですよ(・∀・)！オススメ。</p>
<p>あ、<strong>urljoin</strong>ってのもあります。</p>
<pre class="brush: bash; title: ; notranslate">
&gt;&gt;&gt; url = 'http://aaa.bbb.com/ddd/eee.html?hoge=fuga'
&gt;&gt;&gt; print urljoin(url, 'fff.html')

http://aaa.bbb.com/ddd/fff.html

&gt;&gt;&gt; print urljoin(url, '../ggg.html')

http://aaa.bbb.com/ggg.html

&gt;&gt;&gt; print urljoin(url, '/js/script.js')

http://aaa.bbb.com/js/script.js
</pre>
<p>使いやすいですよ！</p>
<p><strong>optparse</strong>は、バッチなど、コマンドラインで使うようなpythonを書いている人なら知ってるかと思います。<br />
コマンド解析器ですね(・ω・)。結構使いやすいです。</p>
<p>以下、簡単なスクリプト。<br />
test.py</p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from optparse import OptionParser

if __name__ == '__main__':

    &quot;&quot;&quot; コマンドエラー時に表示する文字列 &quot;&quot;&quot;
    usage = u'%prog [Args] [Options]\nDetailed options -h or --help'

    version = 0.1
    parser = OptionParser(usage=usage, version=version)

    &quot;&quot;&quot; test.py -d 20111201 のように、オプションの後に整数値を入力させたい場合 &quot;&quot;&quot;
    parser.add_option(
        '-d', '--date',
        action = 'store',
        type = 'int',               # 受け取る値の型を指定する
        dest = 'download_date',     # 保存先変数名
        help = 'Set date(yyyymmdd) you want to download.(ex.20110811)'  # --help時に表示する文（見れば分かるかｗ)
    )

    &quot;&quot;&quot; 文字列が欲しい場合 (test.py -f hoge.txt) &quot;&quot;&quot;
    parser.add_option(
        '-f', '--file',
        action = 'store',
        type = 'str',           # 型指定
        dest = 'file_name',     # 保存先変数名
        help = 'Set filename (ex. hoge.txt)'
    )

    &quot;&quot;&quot; -s を指定した場合、trueを保存する &quot;&quot;&quot;
    parser.add_option(
        '-s', '--sleep',
        action = 'store_true',      # store_trueの場合、Trueが'dest'で指定された変数へ格納される。(false時はstore_false)
        dest = 'hoge_flg',
        help = 'set sleep flag'
    )

    &quot;&quot;&quot; 各オプションのデフォルト値をセット &quot;&quot;&quot;
    parser.set_defaults(
        download_date = None,
        file_name = None,
        hoge_flg = False
    )

    &quot;&quot;&quot; オプションをパース &quot;&quot;&quot;
    options, args = parser.parse_args()

    &quot;&quot;&quot; 単純な引数(例: test.py a b)はargs[index]で取得できる &quot;&quot;&quot;
    if len(args) &gt; 0:
        for i, v in enumerate(args):
            print 'Args[%s] is: %s' % (i, v)

    &quot;&quot;&quot; オプションで指定した値は options.&lt;変数名&gt;で取得できる &quot;&quot;&quot;
    date = options.download_date
    if date:
        if len(str(date)) != 8:
            # エラーを発生させるときは↓こんな感じ
            parser.error('Date must be yyyymmdd')

    print 'date: %s, file: %s, sleep: %s' % (options.download_date, options.file_name, options.hoge_flg)
</pre>
<p>このファイルを &#8211;help オプションをつけて実行すると</p>
<pre class="brush: bash; title: ; notranslate">
$ python test.py --help

Usage: test.py [Args] [Options]
Detailed options -h or --help

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -d DOWNLOAD_DATE, --date=DOWNLOAD_DATE
                        Set date(yyyymmdd) you want to download.(ex.20110811)
  -f FILE_NAME, --file=FILE_NAME
                        Set filename (ex. hoge.txt)
  -s, --sleep           set sleep flag
</pre>
<p>このように、自動で説明文を生成してくれます。</p>
<p>parser.add_option の type で型を指定しておくと、<br />
指定外の入力値の時に自動で弾いてくれます。</p>
<pre class="brush: bash; title: ; notranslate">
$ python test.py -d abc

Usage: test.py [Args] [Options]
Detailed options -h or --help

test.py: error: option -d: invalid integer value: 'abc'
</pre>
<p>Pythonでバッチ書く場合はオススメ(・∀・)<br />
というわけで、使ってみて下さいね！！</p>
<p>さて寝よう。眠いし。</p>
]]></content:encoded>
			<wfw:commentRss>http://zafiel.wingall.com/archives/2011120202302358.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://zafiel.wingall.com/archives/2011120202302358.php" />
	</item>
		<item>
		<title>よく忘れるPython細かいことアレコレ</title>
		<link>http://zafiel.wingall.com/archives/2011111101252338.php?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e3%2582%2588%25e3%2581%258f%25e5%25bf%2598%25e3%2582%258c%25e3%2582%258bpython%25e7%25b4%25b0%25e3%2581%258b%25e3%2581%2584%25e3%2581%2593%25e3%2581%25a8%25e3%2582%25a2%25e3%2583%25ac%25e3%2582%25b3%25e3%2583%25ac</link>
		<comments>http://zafiel.wingall.com/archives/2011111101252338.php#comments</comments>
		<pubDate>Thu, 10 Nov 2011 16:25:12 +0000</pubDate>
		<dc:creator>wg_koro</dc:creator>
				<category><![CDATA[Program]]></category>
		<category><![CDATA[program]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://zafiel.wingall.com/?p=2338</guid>
		<description><![CDATA[Pythonを公私ともにちょこちょこ触ってます。 …で、毎回細々としたものを忘れてしまい、そのたびに調べまくるのでいい加減メモ。 日付を整形して出力 文字列マッチング ランダム文字列生成 Unix Time生成 Unix &#8230; <a href="http://zafiel.wingall.com/archives/2011111101252338.php">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://zafiel.wingall.com/img/python.png"><img src="http://zafiel.wingall.com/img/python.png" alt="" title="python" width="152" height="158" class="alignnone size-full wp-image-2004" /></a><br />
Pythonを公私ともにちょこちょこ触ってます。<br />
…で、毎回細々としたものを忘れてしまい、そのたびに調べまくるのでいい加減メモ。<br />
<span id="more-2338"></span><br />
日付を整形して出力</p>
<pre class="brush: python; title: ; notranslate">
&gt;&gt;&gt; from datetime import datetime
&gt;&gt;&gt; datetime.now().strftime('%Y/%m/%d %H:%M:%S')
'2011/11/11 00:37:23'
</pre>
<p>文字列マッチング</p>
<pre class="brush: python; title: ; notranslate">
&gt;&gt;&gt; import re
&gt;&gt;&gt; p = 'aaabbbccc'
&gt;&gt;&gt; str = re.match(r'aaa', p)
&gt;&gt;&gt; print str.group()
aaa

# マルチバイト
&gt;&gt;&gt; s = u'あいう9876えお'
&gt;&gt;&gt; c = re.compile(u'.+う[0-9]+')
&gt;&gt;&gt; string = re.match(c, s)
&gt;&gt;&gt; print string.group()
あいう9876

# 複数箇所から一致した文字列を取得
&gt;&gt;&gt; s = u'あいうえかきくあいうさしす'
&gt;&gt;&gt; c = re.compile(u'あいう.')
&gt;&gt;&gt; for m in re.finditer(c, s):
...     print m.group()
あいうえ
あいうさ
</pre>
<p>ランダム文字列生成</p>
<pre class="brush: python; title: ; notranslate">
import string
import random

def make_rand_str(n):
    str = string.digits + string.letters
    return ''.join(random.choice(str) for i in xrange(n))
</pre>
<p>Unix Time生成</p>
<pre class="brush: python; title: ; notranslate">
import datetime, time

def get_unix_time():
    d = datetime.datetime.now()
    return time.mktime(d.timetuple())
</pre>
<p>Unix Timeからdatetimeオブジェクトへ変換、その後整形</p>
<pre class="brush: python; title: ; notranslate">
import datetime, time

def reverse_unix_to_datetime(unix):
    return datetime.datetime.fromtimestamp(unix)

d = datetime.datetime.now()
unix_time = time.mktime(d.timetuple())
print reverse_unix_to_datetime(unix_time).strftime('%Y')
</pre>
<p>ハッシュ作成</p>
<pre class="brush: python; title: ; notranslate">
import hashlib

def create_sha1():
    string = 'abcdefg'
    return hashlib.sha1(string).hexdigest()

print create_sha1()
</pre>
<p>dict()はうまく使えば超便利(・∀・)</p>
<pre class="brush: python; title: ; notranslate">
&gt;&gt;&gt; example = 'p1=a&amp;p2=b&amp;p3=c&amp;p4=d'
&gt;&gt;&gt; print dict([(s.split('=')) for s in example.split('&amp;')])
{'p2': 'b', 'p3': 'c', 'p1': 'a', 'p4': 'd'}
</pre>
<p>まぁURL文字列なら、素直にurlparseやparse_qsを使いましょうｗ</p>
<p>こういうのって書こうとすると<br />
「あれ、pythonだとどう書くんだっけ」<br />
とかなりやすいんだよね。。。</p>
<p>lambda式やmap関数も便利だけど、<br />
今は眠いのでまた今度まとめようｗ</p>
<p>じゃ寝る。</p>
]]></content:encoded>
			<wfw:commentRss>http://zafiel.wingall.com/archives/2011111101252338.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://zafiel.wingall.com/archives/2011111101252338.php" />
	</item>
		<item>
		<title>Apache+mod_wsgi+Flaskインストール</title>
		<link>http://zafiel.wingall.com/archives/2011110419102309.php?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mod_wsgiflask%25e3%2582%25a4%25e3%2583%25b3%25e3%2582%25b9%25e3%2583%2588%25e3%2583%25bc%25e3%2583%25ab</link>
		<comments>http://zafiel.wingall.com/archives/2011110419102309.php#comments</comments>
		<pubDate>Fri, 04 Nov 2011 10:10:47 +0000</pubDate>
		<dc:creator>wg_koro</dc:creator>
				<category><![CDATA[Program]]></category>
		<category><![CDATA[mod_wsgi]]></category>
		<category><![CDATA[program]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://zafiel.wingall.com/?p=2309</guid>
		<description><![CDATA[はいこんばんは。 生きてます生きてます。 ここ一週間、またPythonごりごりやってます。 今度は小さーいシステムなんでFlask (Python製マイクロフレームワーク)でさくっと作ってます。 Flaskはマイクロと名 &#8230; <a href="http://zafiel.wingall.com/archives/2011110419102309.php">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://flask.pocoo.org/"><img src="http://zafiel.wingall.com/img/eaead6238693f2a2dfec41bb009f140e-150x150.png" alt="" title="top image" width="150" height="150" class="alignnone size-thumbnail wp-image-2317" /></a></p>
<p>はいこんばんは。<br />
生きてます生きてます。</p>
<p>ここ一週間、またPythonごりごりやってます。<br />
今度は小さーいシステムなんで<a href="http://flask.pocoo.org/" target='_blank'>Flask</a> (Python製マイクロフレームワーク)でさくっと作ってます。<br />
Flaskはマイクロと名前がついているだけあって、インストールは楽だしアプリ作成手順もシンプルだし&#8230;で、触ってて楽しいですね(・∀・)。</p>
<p>今回、Flaskをサーバーにインストールして動かしたのでそのメモ。<br />
環境:<br />
サーバー： EC2, Apache + mod_wsgi<br />
Pythonバージョン: Python2.6.6 (EC2デフォルトのバージョン)</p>
<p>あ、ついでなので、PythonでできたWebアプリケーションを扱う時に言われる<br />
「ファイル更新したらApacheリロードしなきゃいかんのめんどくさー！」<br />
って誤解も解いておきますね。<br />
<span id="more-2309"></span></p>
<h3>インストール・設定方法</h3>
<pre class="brush: bash; title: ; notranslate">
sudo easy_install pip
sudo pip install flask
sudo yum install httpd-devel python-devel
</pre>
<p>※pip使っているのは単純に好みからです</p>
<p>EC2のyumで入るmod_wsgiはバージョンが古くて変なエラーが出るので<br />
最新版をソースからインストールする。</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/src
sudo wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz
tar xzvf mod_wsgi-3.3.tar.gz
cd mod_wsgi-3.3
sudo ./configure --with-apxs=/usr/sbin/apxs --with-python=/usr/bin/python
sudo make
sudo make install
</pre>
<p>/etc/httpd/modules<br />
に<strong>mod_wsgi.so</strong>があるか確認。</p>
<p>Flaskアプリをてきとーに書く。<br />
<strong>flasktest.py</strong></p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Flaskいっちょあがりー'

if __name__ == '__main__':
    app.run()
</pre>
<p>Flaskアプリケーションはどこに置いてもいいけど<br />
今回は <strong>/home/foo/flask/flasktest.py</strong> に置いてみる。</p>
<p>次はwsgiファイルを書く。<br />
<strong>flasktest.wsgi</strong></p>
<pre class="brush: python; title: ; notranslate">
# -*- coding:utf-8 -*-
# Updated: 2011/11/03
# Version: 0.1.1

# Flaskアプリケーショントップのパスをpathに追加
import sys, os
sys.path.append('/home/foo/flask') 

from flasktest import app as application
</pre>
<p>こいつはアプリケーショントップに置きます。<br />
<strong>/home/foo/flask/flasktest.wsgi</strong></p>
<p>httpd.confを書き書き。<br />
基本はドキュメント( <a href='http://flask.pocoo.org/docs/deploying/mod_wsgi/' target='_blank'>http://flask.pocoo.org/docs/deploying/mod_wsgi/</a> )通り。<br />
※WSGI部分だけ書いてます</p>
<p><strong>httpd.conf</strong></p>
<pre class="brush: plain; title: ; notranslate">
LoadModule wsgi_module modules/mod_wsgi.so

WSGISocketPrefix /var/run/wsgi
&lt;VirtualHost *:80&gt;
    ServerName example.com

    DocumentRoot /var/www/html
    &lt;Directory /var/www/html&gt;
        Order allow,deny
        Allow from all
    &lt;/Directory&gt;

    WSGIDaemonProcess example.com user=apache group=apache threads=5
    WSGIScriptAlias / /home/foo/flask/flasktest.wsgi

    &lt;Directory /home/foo/flask&gt;
        WSGIProcessGroup example.com
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
    &lt;/Directory&gt;
&lt;/VirtualHost&gt;
</pre>
<p>ここのDocumentRootは指定しなくてもいい気はするんだけど。<br />
なんか設定しないと変な挙動になったので一応。。</p>
<p>で。やたらとハマるのはWSGIのDaemonモード。<br />
EC2だと<br />
<strong>WSGISocketPrefix /var/run/wsgi</strong><br />
なんだけど、<br />
<strong>WSGISocketPrefix run/wsgi</strong><br />
とする環境もあるっぽい。<br />
これをきちんと設定しないとPermission deniedほげほげ<br />
と言われて先に進めない。</p>
<p>あと<br />
WSGIDaemonProcess example.com <strong>user=apache group=apache</strong> threads=5<br />
のuserとgroupはきちんと指定しましょう。<br />
指定し忘れると怒られます。</p>
<p>WSGIDaemonProcess <strong>example.com</strong> &#8230;<br />
と<br />
WSGIProcessGroup <strong>example.com</strong><br />
の太字部分は合わせましょう。でないと<br />
<strong>No WSGI daemon process called &#8216;ほにゃらら&#8217;</strong><br />
と怒られます。</p>
<p>と、ここまで書いたら</p>
<pre class="brush: plain; title: ; notranslate">
sudo /usr/sbin/apachectl configtest
</pre>
<p>で確認。</p>
<p>ＯＫであればApache(リ)スタート。</p>
<pre class="brush: plain; title: ; notranslate">
sudo service httpd restart
</pre>
<p>これでブラウザからアクセスすれば動くはず(・ω・)<br />
<a href="http://zafiel.wingall.com/img/bb.png"><img src="http://zafiel.wingall.com/img/bb.png" alt="" title="bb" width="281" height="110" class="alignnone size-full wp-image-2321" /></a></p>
<h3>ファイル更新時、コマンドラインを使わずにプロセスを再起動</h3>
<p>そういえばPythonはPHPと違って、ファイル更新しただけだと反映されませんよね。<br />
で、Apache再起動しなきゃーってなる。<br />
これは<strong>非常に面倒くさい orz</strong></p>
<p>ところがDaemonモードでmod_wsgiを動かしている場合、<br />
SSHでコマンドを叩く必要はありません。<br />
wsgiファイルの日付が更新されると自動でプロセス再起動が発生します。</p>
<p>pythonファイルを一通り更新し、最後に日付を更新したwsgiファイルをつっこむと、次回アクセス時にプロセスが再起動されて更新完了。<br />
参考：<a href='http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIScriptReloading' target='_blank'>modwsgi wiki</a></p>
<p>PythonでできたWebアプリケーションの運用は、これを知っておくと大分楽だと思いますヨ。<br />
あ、mod_wsgiで動かすアプリケーションであれば、どれも同じ方法で更新できます。(Djangoとかもね)</p>
<p>環境ができあがってしまえばFlaskたのしーっす。<br />
SNSのような、ログインが必要なアプリケーションであればDjango使ったほうが楽かもだけど、ちょっとしたアプリケーションならFlaskで十分。</p>
<p>…というわけで、そこのあなたもFlaskいかが(・∀・)？</p>
]]></content:encoded>
			<wfw:commentRss>http://zafiel.wingall.com/archives/2011110419102309.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://zafiel.wingall.com/archives/2011110419102309.php" />
	</item>
		<item>
		<title>お手軽ダウンローダー PyCherryPick 作ってみた (Python)</title>
		<link>http://zafiel.wingall.com/archives/2011081621022195.php?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e3%2581%258a%25e6%2589%258b%25e8%25bb%25bd%25e3%2583%2580%25e3%2582%25a6%25e3%2583%25b3%25e3%2583%25ad%25e3%2583%25bc%25e3%2583%2580%25e3%2583%25bc-pycherrypick-%25e4%25bd%259c%25e3%2581%25a3%25e3%2581%25a6%25e3%2581%25bf%25e3%2581%259f-python</link>
		<comments>http://zafiel.wingall.com/archives/2011081621022195.php#comments</comments>
		<pubDate>Tue, 16 Aug 2011 12:02:11 +0000</pubDate>
		<dc:creator>wg_koro</dc:creator>
				<category><![CDATA[Program]]></category>
		<category><![CDATA[program]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://zafiel.wingall.com/?p=2195</guid>
		<description><![CDATA[相変わらずめちゃめちゃ湿度高くて暑いですねコニャチワワorz 湿度高いと汗疹できるからツライー･･･。 先週末の話ですが。 調べ物のためにあっちのページのPDF, こっちのページのPDFをぽちぽちダウンロードしてたんす。 &#8230; <a href="http://zafiel.wingall.com/archives/2011081621022195.php">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://zafiel.wingall.com/img/python.png"><img src="http://zafiel.wingall.com/img/python.png" alt="" title="python" width="152" height="158" class="alignnone size-full wp-image-2004" /></a><br />
相変わらずめちゃめちゃ湿度高くて暑いですねコニャチワワorz<br />
湿度高いと汗疹できるからツライー･･･。</p>
<p>先週末の話ですが。<br />
調べ物のためにあっちのページのPDF, こっちのページのPDFをぽちぽちダウンロードしてたんす。<br />
･･･量が多い(＝ω＝)<br />
右クリック→「リンク先を名前をつけて保存」<br />
このアクションが１つや２つならいいけど、５つ６つ７つとかなってくるとひたすら面倒くさい。</p>
<p>ダウンロード専用ツールを探して、インストールして、使い方調べｔ･･･これまた面倒くさい。</p>
<p>なんかないか。･･･ないか(＝ω＝)。<br />
じゃあ作ってしまえホトトギス。<br />
→→作った。</p>
<p>名前は <strong>PyCherryPick</strong> にしました。<br />
この名前、なんかエロいね(＊・∀・＊)<br />
※ちなみにcherrypickってのは英語で「つまみ食い」って意味ｗ</p>
<p>ソースコードはコチラ<br />
<a href="https://github.com/wgkoro/PyCherryPick" target='_blank'>github: https://github.com/wgkoro/PyCherryPick</a></p>
<p>ちなみにコマンド実行するとこうなります↓  (各画像クリックで拡大)<br />
<a href="http://zafiel.wingall.com/img/7f3fd44bdd399189fbc4cf2112a47104.png"><img src="http://zafiel.wingall.com/img/7f3fd44bdd399189fbc4cf2112a47104-300x180.png" alt="" title="実行の様子" width="300" height="180" class="alignnone size-medium wp-image-2196" /></a><br />
ページから欲しいファイルを抜き出して、自動ダウンロードします。</p>
<p><a href="http://zafiel.wingall.com/img/b4e778ef4534df5d00eefbe903aa218c.png"><img src="http://zafiel.wingall.com/img/b4e778ef4534df5d00eefbe903aa218c-300x169.png" alt="" title="ダウンロードされたファイル群" width="300" height="169" class="alignnone size-medium wp-image-2197" /></a><br />
↑保存された画像達。</p>
<p>以下、使い方。<br />
<span id="more-2195"></span></p>
<h3>必須条件</h3>
<p>・Python2.x<br />
・BeautifulSoup (パッケージにバンドルしてあります)<br />
Macの方はダウンロード後、コマンドラインたたけば使えるはず。デフォルトでPython入ってるので。<br />
Windowsの方は、Pythonインストールしないとダメかな･･･。</p>
<h3>基本的な使い方</h3>
<p>基本的にコマンドラインで利用します。<br />
本体(pycherrypick.py)があるディレクトリまで移動して<br />
$ python pycherrypick.py [ターゲットのURL]</p>
<p>例：<br />
<code><br />
$ python pycherrypick.py http://zafiel.wingall.com/archives/2011071715282121.php<br />
</code><br />
これで<a href="http://zafiel.wingall.com/archives/2011071715282121.php" target='_blank'>http://zafiel.wingall.com/archives/2011071715282121.php</a>を走査し、リンク先が「jpg」のものを自動ダウンロードします。<br />
オプション無し、URLのみ指定だと、jpgファイルのみ取ってきます。<br />
<del datetime="2011-08-16T11:20:29+00:00">これなんてエロ画像ダウンローダ？</del></p>
<h3>応用 Options</h3>
<p>コマンド実行時にオプションを指定すると、処理が色々変わります。<br />
オプション一覧：<br />
  &#8211;version<br />
　　　　　バージョンを表示<br />
  -h, &#8211;help<br />
　　　　　このヘルプを表示<br />
  -f FILE, &#8211;file=FILE<br />
　　　　　ローカルのHTMLファイルのパス。<br />
　　　　　これが指定されているとローカルHTMLファイルを走査します。<br />
　　　　　もしURLと両方指定されている場合、ローカルを優先します。<br />
  -t TYPE, &#8211;type=TYPE<br />
　　　　　ダウンロードするファイルタイプを指定。pngファイルが欲しい場合はpngと指定します。<br />
　　　　　jpg,gif,png とカンマ区切りにすると複数タイプをまとめてダウンロードします。<br />
　　　　　-r オプション(正規表現)が指定されている場合、-t オプションは無視されます。　　　　　<br />
  -i INTERVAL, &#8211;interval=INTERVAL<br />
　　　　　複数ファイルをダウンロードする際のインターバル(秒)を指定。デフォルトは2(秒)<br />
  -d DOWNLOAD, &#8211;download=DOWNLOAD<br />
　　　　　ダウンロードファイルの保存先を指定。（フルパスで指定)<br />
　　　　　デフォルトは、pycherrypick.pyのディレクトリにあるdownloadsフォルダに格納されます。<br />
  -e ENCODE, &#8211;encode=ENCODE<br />
　　　　　ターゲットとするページの文字エンコードを指定。<br />
　　　　　カスタムスクレイピングする場合以外は指定の必要はありません。<br />
  -u UA, &#8211;ua=UA<br />
　　　　　ファイルダウンロードする際のユーザーエージェント変更。デフォルトはIE8がセットされています。<br />
  -r REGEX, &#8211;regex=REGEX<br />
　　　　　ダウンロードするURLをフィルタする正規表現。<br />
　　　　　-t オプションも指定されている場合、<br />
　　　　　この-rオプションが優先され、-tオプションは無視されます。<br />
　　　　　例: -r &#8216;http.+\/.jpg&#8217;</p>
<p>例：pdfファイルが欲しい！<br />
<code><br />
$ python pycherrypick.py http://zafiel.wingall.com/ -t pdf<br />
</code></p>
<p>例：pngとjpgファイル両方欲しい！<br />
<code><br />
$ python pycherrypick.py http://zafiel.wingall.com/ -t jpg,png<br />
</code></p>
<p>例：pngとgifとpdfファイルを /Users/Foo/Downloads に保存したい<br />
<code><br />
$ python pycherrypick.py http://zafiel.wingall.com/ -t png,gif,pdf -d /Users/Foo/Downloads<br />
</code></p>
<h3>リンク先だけでなく、他のファイルも欲しい！</h3>
<p>デフォルトは、リンク先のみを見ます。<br />
例えばページに貼ってあるimgタグのsrcが欲しい場合は、カスタマイズしちゃって下さい。</p>
<p>クラスPyCherryPickを継承した新しいクラスを作り、scrape()をオーバーライドすれば楽かと思います。<br />
PyCherryPick/python/custom_example.pyを参照して下さい。</p>
<p>custom_example.py</p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pycherrypick import PyCherryPick
import re

class CustomExample(PyCherryPick):
    def __init__(self):
        PyCherryPick.__init__(self)

    def scrape(self):
        &quot;&quot;&quot;
        新しいスクレイピング処理を書く。ダウンロード対象とするURLリストを返せばOK
        imgタグを取得して、それぞれのパスを返す
        &quot;&quot;&quot;
        reg = re.compile(self.regex)
        images = self.soup.findAll('img')
        results = []
        for img in images:
            try:
                url = dict(img.attrs)['src']
                url = self._make_url_path(url)
                if reg.match(url):
                    results.append(url)

            except:
                pass

        print 'Img tag scraping OK'
        return results

if __name__ == '__main__':
    f = CustomExample()
    f.main()
</pre>
<p>使い方はこんな感じ(・∀・)</p>
<p>毎回urllib.open()とかBeautifulSoupでスクレイピング書いてもいいけどめんどくさいからね･･･。<br />
これでファイル収集少しは楽になるかなー？</p>
<p>追記：<br />
友人から「wgetでいいやん」ってつっこまれた。<br />
wgetの機能がそんなに色々あると知らなかった･･･よ･･･ orz<br />
ま、コード書く練習になったからいいとしよう(・ω・)<br />
あ、ユーザーエージェント偽装できるのは強みか？ｗ</p>
]]></content:encoded>
			<wfw:commentRss>http://zafiel.wingall.com/archives/2011081621022195.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://zafiel.wingall.com/archives/2011081621022195.php" />
	</item>
		<item>
		<title>python楽しいよ？ (python+doctest+vim=ヒャッハー)</title>
		<link>http://zafiel.wingall.com/archives/2011060617022003.php?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=python%25e6%25a5%25bd%25e3%2581%2597%25e3%2581%2584%25e3%2582%2588%25ef%25bc%259f-pythondoctestvim%25e3%2583%2592%25e3%2583%25a3%25e3%2583%2583%25e3%2583%258f%25e3%2583%25bc</link>
		<comments>http://zafiel.wingall.com/archives/2011060617022003.php#comments</comments>
		<pubDate>Mon, 06 Jun 2011 08:02:42 +0000</pubDate>
		<dc:creator>wg_koro</dc:creator>
				<category><![CDATA[Program]]></category>
		<category><![CDATA[program]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://zafiel.wingall.com/?p=2003</guid>
		<description><![CDATA[まーたしばらく記事書いてなかったびっくりだ。筆無精にもほどがある。 さてさて。最近家ではPythonばかりいじっております。 もっぱらDjangoでWebアプリ作成。慣れるとなかなか楽しい。 このPython、海外だとメ &#8230; <a href="http://zafiel.wingall.com/archives/2011060617022003.php">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://zafiel.wingall.com/img/python.png"><img src="http://zafiel.wingall.com/img/python.png" alt="" title="python" width="152" height="158" class="alignnone size-full wp-image-2004" /></a><br />
まーたしばらく記事書いてなかったびっくりだ。筆無精にもほどがある。</p>
<p>さてさて。最近家ではPythonばかりいじっております。<br />
もっぱらDjangoでWebアプリ作成。慣れるとなかなか楽しい。</p>
<p>このPython、海外だとメジャーな言語なんですが日本じゃ非常にマイナーな存在。ぐぬぬ。おかげで日本語の資料が出てこない。ほとんど英語。まぁいいけど…。日本語の「Pythonやろうよ！楽だよ？」って記事が少ないので、ちょっとヨイショ記事を書こうと思います(・∀・)<br />
<span id="more-2003"></span><br />
細かい文法とかすっとばして、いきなりタイトルの内容に入りまーす。</p>
<p>Pythonだと単体テストがもんっのすごく書きやすい。<br />
= いいペースでプログラムを作っていける。<br />
そこにVimも混ぜるとなお素晴らしい。</p>
<p>実例。例えば hoge.py というファイルに関数addを作ります。</p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/env python
# -*- coding: utf-8 -*-

def add(a, b):
    return 0
</pre>
<p>docstring(説明文)もつけちゃいましょう。</p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/env python
# -*- coding: utf-8 -*-

def add(a, b):
    &quot;&quot;&quot;引数を足して返す&quot;&quot;&quot;
    return 0
</pre>
<p>さて、テストしましょう。<br />
他言語と同じようなUnit Testも使えますが、せっかくなのでここはPython特有のdoctestで行きます。<br />
doctestの下準備。ファイル hoge.py の下に数行追加(8〜10行目)。</p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/env python
# -*- coding: utf-8 -*-

def add(a, b):
    &quot;&quot;&quot;引数を足して返す&quot;&quot;&quot;
    return 0

if __name__ == '__main__':
    import doctest
    doctest.testmod()
</pre>
<p>追加したら、ちょっとPythonの対話シェルから関数を実行してみます。<br />
(対話シェル→コマンドラインで「python」と打つと起動します)<br />
<a href="http://zafiel.wingall.com/img/aef8939cf5765144e33f9ee4ad066906.png"><img src="http://zafiel.wingall.com/img/aef8939cf5765144e33f9ee4ad066906.png" alt="" title="cmd1" width="236" height="129" class="alignnone size-full wp-image-2015" /></a><br />
add(1, 3)が実行されて、上に書いた通り、ちゃんと0が返ってますね。</p>
<p>んでは、docstringの中に、対話シェルと同じ形式でテストを書きます。</p>
<p>「>>>」の文字の後に実行したい文を書きます。(下の例 8, 9行目)<br />
その直後の行(10行目)には期待する返り値を書きます。※下の例だと期待する返り値は「4」ですね。</p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/env python
# -*- coding: utf-8 -*-

def add(a, b):
    &quot;&quot;&quot;
    引数を足して返す

    1と3足したら4が返ってくるだろJK
    &gt;&gt;&gt; add(1, 3)
    4

    &quot;&quot;&quot;
    return 0

if __name__ == '__main__':
    import doctest
    doctest.testmod()
</pre>
<p>はい、テストの記述終了。<br />
コマンドラインでこのファイルを実行してみると</p>
<p><strong>$ python hoge.py</strong><br />
<a href="http://zafiel.wingall.com/img/6af8be52f493466b03c407d2c679920b.png"><img src="http://zafiel.wingall.com/img/6af8be52f493466b03c407d2c679920b.png" alt="" title="cmd2" width="311" height="194" class="alignnone size-full wp-image-2023" /></a></p>
<p>さくっとテストが実行されちゃいます。<br />
期待する返り値(Expected)が4のところに0が返ってる(Got)のでFailedになってますね。</p>
<p>add()を書き直します。</p>
<pre class="brush: python; title: ; notranslate">
def add(a, b):
    &quot;&quot;&quot; 引数を足して返す

    1と3足したら4が返ってくるだろJK
    &gt;&gt;&gt; add(1, 3)
    4

    &quot;&quot;&quot;
    return a + b
</pre>
<p>OK、テストだ。<br />
<a href="http://zafiel.wingall.com/img/e54e45376b5cd52b0fc15ed89d86416e.png"><img src="http://zafiel.wingall.com/img/e54e45376b5cd52b0fc15ed89d86416e.png" alt="" title="cmd3" width="125" height="36" class="alignnone size-full wp-image-2024" /></a><br />
あれ何も表示されない…？<br />
というのは<strong>実は正常で、テストにパスすると何も表示されません</strong>。<br />
実行結果を見るには -v オプションをつけて実行します。</p>
<p><strong>$ python hoge.py -v</strong><br />
<a href="http://zafiel.wingall.com/img/85e7a31affaa8a6004fc208984969c17.png"><img src="http://zafiel.wingall.com/img/85e7a31affaa8a6004fc208984969c17.png" alt="" title="cmd4" width="196" height="196" class="alignnone size-full wp-image-2025" /></a><br />
vオプションをつけるとこんな具合に、実行結果詳細つきでテスト結果を見ることができます。</p>
<p>慣れたらテストをガシガシ追加していきましょう。</p>
<pre class="brush: python; title: ; notranslate">
def add(a, b):
    &quot;&quot;&quot; 引数を足して返す

    1と3足したら4が返ってくるだろJK
    &gt;&gt;&gt; add(1, 3)
    4

    他の数字でテスト
    &gt;&gt;&gt; add(5, 2)
    7

    文字でテスト
    &gt;&gt;&gt; add('a', 'b')
    'ab'

    比較テスト
    &gt;&gt;&gt; a = add(1, 1)
    &gt;&gt;&gt; a == 2
    True

    &quot;&quot;&quot;
    return a + b
</pre>
<p>テスト実行。<br />
<a href="http://zafiel.wingall.com/img/d0be3485e7c07b96ae6b82c86eda9aef.png"><img src="http://zafiel.wingall.com/img/d0be3485e7c07b96ae6b82c86eda9aef.png" alt="" title="cmd6" width="198" height="498" class="alignnone size-full wp-image-2027" /></a><br />
こんな感じで、処理記述、テスト、処理記述、テストと、順番にスルスルと組み立てていくことができます。</p>
<p>Vimを使っている方なら、わざわざターミナル(or コマンドプロンプト)に切り替えなくても<br />
<strong>:! python hoge.py -v</strong><br />
と打てばVim内でテスト実行、テスト結果を見ることができますね(・∀・)！<br />
<a href="http://zafiel.wingall.com/img/0e6f7ff6f98c5e013052381b2bc7ba2e.png"><img src="http://zafiel.wingall.com/img/0e6f7ff6f98c5e013052381b2bc7ba2e.png" alt="" title="vim1" width="248" height="262" class="alignnone size-full wp-image-2028" /></a><br />
　↓<br />
<a href="http://zafiel.wingall.com/img/25fbd7e5fc4baa601f14a7a987ee901b.png"><img src="http://zafiel.wingall.com/img/25fbd7e5fc4baa601f14a7a987ee901b.png" alt="" title="vim2" width="290" height="216" class="alignnone size-full wp-image-2029" /></a></p>
<p>テストの流れはこんな感じです。</p>
<p>doctestは基本的に簡単な比較テストしかできないし、テストが多すぎると逆に視認性が落ちる&#8230;というデメリットはありますが、この「テストの手軽さ、素早さ」はものすごく気持ちいいですよ。安心感も得られますしね。それにDjangoなどのフレームワークと組み合わせると、Webアプリをスンスンスーン♪と作っていけます。便利！</p>
<p>どうでしょう？ちょっとPython使ってみたくなりました？Djangoなどをつっこめるレンタルサーバーは数少ないですが、機会があったら是非使ってみて下さいね(。・∀・)ﾉ</p>
<p>というわけで、Python楽しいよ？というお話でした。さて、アプリの続き作ろうっと…。</p>
<p>今回書いたPythonはコチラ→<a href="http://zafiel.wingall.com/data/python/hoge.py">hoge.py</a><br />
※文字化けする場合は、ブラウザの文字エンコードをUTF-8に変えて下さい</p>
]]></content:encoded>
			<wfw:commentRss>http://zafiel.wingall.com/archives/2011060617022003.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://zafiel.wingall.com/archives/2011060617022003.php" />
	</item>
		<item>
		<title>Facebookの敬称を消すGreaseMonkey書いた</title>
		<link>http://zafiel.wingall.com/archives/2011020815091957.php?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=facebook%25e3%2581%25ae%25e6%2595%25ac%25e7%25a7%25b0%25e3%2582%2592%25e6%25b6%2588%25e3%2581%2599greasemonkey%25e6%259b%25b8%25e3%2581%2584%25e3%2581%259f</link>
		<comments>http://zafiel.wingall.com/archives/2011020815091957.php#comments</comments>
		<pubDate>Tue, 08 Feb 2011 06:09:02 +0000</pubDate>
		<dc:creator>wg_koro</dc:creator>
				<category><![CDATA[Program]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[greasemonkey]]></category>
		<category><![CDATA[program]]></category>

		<guid isPermaLink="false">http://zafiel.wingall.com/?p=1957</guid>
		<description><![CDATA[なんか今日寒いですな。 Facebook内で「そろそろ誰かが&#8221;さん&#8221;を取るグリモンのスクリプトを書く頃」と書いている人がいたのでカッとなって作った。反省はしていない。 http://zafiel. &#8230; <a href="http://zafiel.wingall.com/archives/2011020815091957.php">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>なんか今日寒いですな。</p>
<p>Facebook内で「<strong>そろそろ誰かが&#8221;さん&#8221;を取るグリモンのスクリプトを書く頃</strong>」と書いている人がいたのでカッとなって作った。反省はしていない。<br />
<a href="http://zafiel.wingall.com/js/fb/fb_remove_san.user.js<br />
">http://zafiel.wingall.com/js/fb/fb_remove_san.user.js</a><br />
※Firefox, Chromeで動きます。</p>
<p><a href="http://zafiel.wingall.com/img/before.png"><img src="http://zafiel.wingall.com/img/before.png" alt="" title="before" width="362" height="70" class="alignnone size-full wp-image-1958" /></a><br />
Facebookでは本来、それぞれの名前の後ろに「<strong>さん</strong>」がつきますが、このぐりもんを入れると</p>
<p><a href="http://zafiel.wingall.com/img/after.png"><img src="http://zafiel.wingall.com/img/after.png" alt="" title="after" width="359" height="69" class="alignnone size-full wp-image-1959" /></a><br />
「さん」が消えます。</p>
<p>一応、http, https両方で動くようにしてあります。10分くらいで作って、テストあまりしていないので不具合あったら教えて下さい。</p>
<p>さーて仕事にもどるか…((((。・ω・)</p>
<p>追記：<br />
いつのまにか、Facebookの「さん」がデフォルトで表示されなくなりましたね。このスクリプトもお役ご免ですなｗ</p>
]]></content:encoded>
			<wfw:commentRss>http://zafiel.wingall.com/archives/2011020815091957.php/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://zafiel.wingall.com/archives/2011020815091957.php" />
	</item>
		<item>
		<title>Facebookアプリ「TwitPonta」を作ってみた</title>
		<link>http://zafiel.wingall.com/archives/2011012310431899.php?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=facebook%25e3%2582%25a2%25e3%2583%2597%25e3%2583%25aa%25e3%2580%258ctwitponta%25e3%2580%258d%25e4%25bd%259c%25e3%2581%25a3%25e3%2581%25a6%25e3%2581%25bf%25e3%2581%259f</link>
		<comments>http://zafiel.wingall.com/archives/2011012310431899.php#comments</comments>
		<pubDate>Sun, 23 Jan 2011 01:43:28 +0000</pubDate>
		<dc:creator>wg_koro</dc:creator>
				<category><![CDATA[Program]]></category>
		<category><![CDATA[アプリ]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[program]]></category>

		<guid isPermaLink="false">http://zafiel.wingall.com/?p=1899</guid>
		<description><![CDATA[相変わらず寒いですねコンチクショイ。あー咳が止まらないorz ちょっと気晴らしにFacebookアプリ『TwitPonta for Facebook』を作ってみました。 Facebook内からTwitter、Facebo &#8230; <a href="http://zafiel.wingall.com/archives/2011012310431899.php">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://zafiel.wingall.com/img/twitponta.png"><img src="http://zafiel.wingall.com/img/twitponta.png" alt="" title="twitponta" width="73" height="73" class="alignnone size-full wp-image-1900" /></a><br />
相変わらず寒いですねコンチクショイ。あー咳が止まらないorz</p>
<p>ちょっと気晴らしにFacebookアプリ『<a href="http://www.facebook.com/apps/application.php?id=166481836715450">TwitPonta for Facebook</a>』を作ってみました。<br />
<a href="http://zafiel.wingall.com/img/desk.png"><img src="http://zafiel.wingall.com/img/desk-300x141.png" alt="" title="desk" width="300" height="141" class="alignnone size-medium wp-image-1917" /></a><br />
Facebook内からTwitter、Facebookの二カ所へ同時投稿できるアプリです。<br />
一応、URL短縮機能もついてます。</p>
<p>「HootSuiteとかでいぃじゃん」と言われればそれまでな、使いどころが難しいアプリなんですけどね！<br />
「<strong>Facebook内から、左下爆発を見つつ投稿できるもの</strong>」<br />
が探しても見当たらなかったので作ってみました(・∀・)<br />
<span id="more-1899"></span><br />
使い方は・・・説明するまでも無いとは思いますが、一応説明しておきます。<br />
<a href="http://zafiel.wingall.com/img/kyoka.png"><img src="http://zafiel.wingall.com/img/kyoka-300x190.png" alt="" title="kyoka" width="300" height="190" class="alignnone size-medium wp-image-1906" /></a><br />
初めて接続した場合は、上画像のようにFacebook情報への接続許可を求められますので「<strong>許可</strong>」を押して下さい。</p>
<p><a href="http://zafiel.wingall.com/img/twitponta_fb.png"><img src="http://zafiel.wingall.com/img/twitponta_fb-300x211.png" alt="" title="twitponta_fb" width="300" height="211" class="alignnone size-medium wp-image-1907" /></a><br />
Twitter側の許可も必要になります。「<strong>Connect Twitter</strong>」ボタンを押し、Twitter側でTwitPontaの接続を許可して下さい。</p>
<p><a href="http://zafiel.wingall.com/img/desk.png"><img src="http://zafiel.wingall.com/img/desk-300x141.png" alt="" title="desk" width="300" height="141" class="alignnone size-medium wp-image-1917" /></a><br />
全ての準備が整うと上図のようになります。<br />
「Facebook」「Twitter」どちらに投稿するかは<strong>上部のチェックボックス</strong>から制御できます。チェックボックスにチェックをつけているサービスに投稿します。<br />
「<strong>Shorten URL</strong>」ボタンでURL短縮ができます。<br />
「<strong>ゴミ箱</strong>」アイコンを押すと、現在入力中の文字をクリアします。<br />
クリア後、ボタンは「<strong>Undo</strong>」ボタンに変わります。Undoボタンを押すとクリアした文字を戻すことができます。</p>
<p>あ。Twitterに投稿する際、140字を超えていると、<strong>後ろの文字列は削除されるのでご注意下さい</strong>。</p>
<p>誰得なアプリですが、せっかく作ったので公開ってことで(・∀・)<br />
将来はTwitterタイムライン/Facebookのニュースフィードを並べて表示ってのもやりたいですね。<br />
「こういうのをつけて欲しい」ってなリクエストがあれば、教えて下さいまし。</p>
<p>アプリのプロフィールページは<a href="http://www.facebook.com/apps/application.php?id=166481836715450">コチラ</a></p>
]]></content:encoded>
			<wfw:commentRss>http://zafiel.wingall.com/archives/2011012310431899.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://zafiel.wingall.com/archives/2011012310431899.php" />
	</item>
		<item>
		<title>Delicious(del.icio.us)が終了らしいのでScuttleをすすめてみる</title>
		<link>http://zafiel.wingall.com/archives/2010121711251808.php?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=deliciousdel-icio-us%25e3%2581%258c%25e7%25b5%2582%25e4%25ba%2586%25e3%2582%2589%25e3%2581%2597%25e3%2581%2584%25e3%2581%25ae%25e3%2581%25a7scuttle%25e3%2582%2592%25e3%2581%2599%25e3%2581%2599%25e3%2582%2581%25e3%2581%25a6%25e3%2581%25bf%25e3%2582%258b</link>
		<comments>http://zafiel.wingall.com/archives/2010121711251808.php#comments</comments>
		<pubDate>Fri, 17 Dec 2010 02:25:36 +0000</pubDate>
		<dc:creator>wg_koro</dc:creator>
				<category><![CDATA[Program]]></category>
		<category><![CDATA[program]]></category>
		<category><![CDATA[scuttle]]></category>

		<guid isPermaLink="false">http://zafiel.wingall.com/?p=1808</guid>
		<description><![CDATA[ソーシャルブックマークサービスの大御所、del.isio.usが廃止されるかもしれないらしいですね。 ソース：Yahoo、サービスに大ナタ、Del.icio.us他多数を廃止する？ [Update: そのとおり] これを &#8230; <a href="http://zafiel.wingall.com/archives/2010121711251808.php">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://zafiel.wingall.com/img/delcious.gif"><img src="http://zafiel.wingall.com/img/delcious-300x129.gif" alt="" title="delcious" width="300" height="129" class="alignnone size-medium wp-image-1831" /></a><br />
ソーシャルブックマークサービスの大御所、<a href="http://www.delicious.com/">del.isio.us</a>が廃止されるかもしれないらしいですね。<br />
ソース：<a href="http://jp.techcrunch.com/archives/20101216is-yahoo-shutting-down-del-icio-us/">Yahoo、サービスに大ナタ、Del.icio.us他多数を廃止する？ [Update: そのとおり]</a></p>
<p>これを機に、自分用のソーシャルブックマークシステムをサーバーに設置しちゃうっていうのはどうでしょう？これだったら（自分がサーバー止めない限り）無くなるってことはないし。</p>
<p>ちなみに私がつかっているのは「<a href="http://sourceforge.net/projects/semanticscuttle/files/">SemanticScuttle</a>」というオープンソースのソーシャルブックマークです。こんな感じ（クリックで画像拡大）↓<br />
<a href="http://zafiel.wingall.com/img/9901b1a528caca90ea2223beb88c277f.png"><img src="http://zafiel.wingall.com/img/9901b1a528caca90ea2223beb88c277f-300x168.png" alt="" title="Scuttle" width="300" height="168" class="alignnone size-medium wp-image-1811" /></a></p>
<p>ブックマーク登録画面はこんな感じ<br />
<a href="http://zafiel.wingall.com/img/380abc8a3c09a86d98d09360d85a3140.png"><img src="http://zafiel.wingall.com/img/380abc8a3c09a86d98d09360d85a3140-300x187.png" alt="" title="ブックマーク登録画面" width="300" height="187" class="alignnone size-medium wp-image-1816" /></a></p>
<p>画面構成はdel.icio.usによく似てるんじゃないかな。<br />
実際に動いているのを見たい方はこちらへどうぞ → <a href="http://bookmark.wingall.com/">Azrael bookmark</a><br />
※自分専用なので、「ユーザ登録」画面は機能しません </p>
<p>ちなみに<br />
・多人数での利用<br />
・タグ付け<br />
・ブックマーク評価<br />
などが可能です。<br />
del.icio.usから出力したXMLを直接インポートすることもできますよ(。・ω・)ノ</p>
<p>あと、オープンソースなので自分で改造しちゃうことも可能です。<br />
私が設置しているものは以下の改造をしています。<br />
・ブックマークすると同時に、Evernoteで自動Webクリップ<br />
・AutoPagerize対応<br />
・「次へ」「前へ」などのナビゲーションを画面上下に配置<br />
・iPhone/Android用に画面最適化（↓こんなん）<br />
<a href="http://zafiel.wingall.com/img/android.gif"><img src="http://zafiel.wingall.com/img/android-180x300.gif" alt="" title="android" width="180" height="300" class="alignnone size-medium wp-image-1837" /></a></p>
<p>設置方法を書こうとしたけど、<a href="http://sourceforge.net/projects/semanticscuttle/files/">本家のバージョン</a>が自分が使っているバージョンから少し上がっているので調べなおさないと駄目っぽい。設置方法は週末に書こうかな。</p>
<p>サーバーへの設置作業がちょっとめんどくさいですが、一回設置しちゃえばずっと使えるのでオススメですよ。これを機に導入してみるってのはいかがでしょうか(・∀・)？</p>
<p>そうそう、現在私のScuttleは「人様のブックマーク預かるのもなぁ…」と考えてユーザ登録を停止していますが、もし「使ってみたい」という奇特な方がいらっしゃったら<a href="http://twitter.com/wg_koro">Twitter (@wg_koro)</a>か、このエントリーにコメントを下さい。多分、開放します。</p>
]]></content:encoded>
			<wfw:commentRss>http://zafiel.wingall.com/archives/2010121711251808.php/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://zafiel.wingall.com/archives/2010121711251808.php" />
	</item>
		<item>
		<title>Google App Engineでクロスドメイン通信</title>
		<link>http://zafiel.wingall.com/archives/2010101816041505.php?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=google-app-engine%25e3%2581%25a7%25e3%2582%25af%25e3%2583%25ad%25e3%2582%25b9%25e3%2583%2589%25e3%2583%25a1%25e3%2582%25a4%25e3%2583%25b3%25e9%2580%259a%25e4%25bf%25a1</link>
		<comments>http://zafiel.wingall.com/archives/2010101816041505.php#comments</comments>
		<pubDate>Mon, 18 Oct 2010 07:04:16 +0000</pubDate>
		<dc:creator>wg_koro</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[program]]></category>

		<guid isPermaLink="false">http://zafiel.wingall.com/?p=1505</guid>
		<description><![CDATA[前回「秋はまだですか」と書きましたが、その日のうちに気温下がったｗ これでちょっと過ごしやすくなったかも。…薄着で寝ててちょっと風邪引きそうになったのは内緒(・ω・) 本題。 クロスドメインでの非同期通信(XMLHttp &#8230; <a href="http://zafiel.wingall.com/archives/2010101816041505.php">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://zafiel.wingall.com/img/program.jpg"><img src="http://zafiel.wingall.com/img/program.jpg" alt="" title="program" width="313" height="110" class="alignnone size-full wp-image-1513" /></a><br />
前回「秋はまだですか」と書きましたが、その日のうちに気温下がったｗ これでちょっと過ごしやすくなったかも。…薄着で寝ててちょっと風邪引きそうになったのは内緒(・ω・)</p>
<p>本題。<br />
クロスドメインでの非同期通信(XMLHttpRequest Level2)をGoogle App Engineで実装したのでメモ。はまったポイントもいくつか書いておきます。</p>
<p>特にハマったのは出力ヘッダ周り。</p>
<p><strong>Access-Control-Allow-Origin</strong><br />
これはあちこちのサイトに書かれてますね。このヘッダを「*」で出力してあげると他ドメインからの通信を受け付けるようになります。・・・が、<strong>これだけじゃダメなんです。</strong></p>
<p><strong>Access-Control-Allow-Methods</strong><br />
こいつを指定してあげないとサーバーが受け付けてくれません。GETならGET、POSTならPOST・・・と指定してあげないといけません。これは複数を一括指定できます（例：「GET, POST」）。あと<strong>POST通信の時は「OPTIONS」も追加してあげる必要があります。</strong></p>
<p>FirefoxはPOSTする前にOPTIONSを投げるので、受信サーバー側でそれを受け取るようにしてあげることが必要です。POST時、Firebugで通信を覗くと「OPTIONS」が投げられているのが分かります（下図）。<br />
<a href="http://zafiel.wingall.com/img/method.jpg"><img src="http://zafiel.wingall.com/img/method.jpg" alt="" title="OPTIONS method" width="313" height="110" class="alignnone size-full wp-image-1512" /></a><br />
これFirefoxだけなんかな？</p>
<p><strong>Access-Control-Allow-Headers</strong><br />
上に書いた二種のヘッダ出力でいける・・・と思ったらIEが通らない。なんでじゃいと思って調べたら、この「Access-Control-Allow-Headers」に’*’を指定してあげないと動かなかった・・・。（本当はヘッダの中身をちゃんと調べて指定するべきなんだろうけど、めんどくさかったのでｗ）</p>
<p>そういえば自分も最初勘違いしてたんですが、これらのヘッダはデータ受け取り側のサーバー(GET/POST先のサーバ)が出力しないとダメですよ。発信側がjavascriptの&#8221;setRequestHeader&#8221;でこれらのヘッダをつけても無意味です。</p>
<p>そうそう、クロスドメインでの通信で忘れちゃならないのがCookie。<strong>クロスドメインでの通信にはCookieを付与できません。</strong>いや正確にいえば、<strong>「IE以外」</strong>は付与できます。 IE、ま た お 前 か orz<br />
このため、セッション保持は別の手法を取る必要があります。</p>
<p>参考になるかわかりませんがApp Engine側のサンプルコードをおいておきます。</p>
<pre class="brush: python; title: ; notranslate">
class Hoge(webapp.RequestHandler):
    def get(self):
        try:
            referer = self.response.headers['Referer']
        except:
            referer = ''

        try:
            origin = self.response.headers['Origin']
        except:
            origin = ''

        # この方法でOriginやRefererが取れるので
        # 必要に応じてチェック処理などを入れるといいのでは。
        # ちなみにtry〜exceptを使わないと、存在しない場合Key Errorが発生しますよ

        fugafuga()  # 何らかの処理

        # これはあちこちのサイトでよく言われている処理
        self.response.headers['Access-Control-Allow-Origin'] = '*'

        # IE8は、これがないとうまく動きませんでした。
        self.response.headers['Access-Control-Allow-Headers'] = '*'

        # GET/POSTなど、必要に応じて許可するメソッドを指定します。
        # POSTの場合はOPTIONSも指定する必要があります。
        self.response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
        self.response.headers['Content-Type'] = 'text/plain;charset=UTF-8'
        self.response.out.write('Hello, World')

    def post(self):
        # 何らかの処理を行う
        self.response.headers['Access-Control-Allow-Origin'] = '*'
        self.response.headers['Access-Control-Allow-Headers'] = '*'
        self.response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
        self.response.headers['Content-Type'] = 'text/plain;charset=UTF-8'
        self.response.out.write('Hello, World')

    def options(self):
        # 何らかの処理を行う
        # POSTの場合は、このoptionsも指定して下さい。
        self.response.headers['Access-Control-Allow-Origin'] = '*'
        self.response.headers['Access-Control-Allow-Headers'] = '*'
        self.response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
</pre>
<p>ご存じだとは思いますが念のための注意書き。<br />
XHR lv2はIE8以上, Firefox, Chrome, Safariでのみ有効です。IE6, 7, Operaでは使えません。<br />
あとIE8では独自オブジェクト<a href='http://msdn.microsoft.com/en-us/library/cc288060%28VS.85%29.aspx'>XDomainRequest</a>を使用する必要があります。他のブラウザは今までと同じXHRを使えばＯＫです。Microsoft、なぜ独自実装なんかしたんだオイ。めんどくさいったらありゃしないぞ。</p>
<p>…大体こんなもんだったと思いますが、他に何かあったかなぁ。思い出したら書きます。</p>
<p>クロスドメインに対応させた非同期通信だけを行うjsライブラリも書いたんだけど、需要あるかなぁ。あればいずれアップしますです(・ω・)ｂ</p>
]]></content:encoded>
			<wfw:commentRss>http://zafiel.wingall.com/archives/2010101816041505.php/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://zafiel.wingall.com/archives/2010101816041505.php" />
	</item>
	</channel>
</rss>

