世界的日曜WEBプログラマー日記 -27ページ目

世界的日曜WEBプログラマー日記

一年後に世界的なWEBサービスを運営するにはどうすればいいのか書いていく(予定)


pythonで正規表現を使う方法を簡単に記載する。

pythonの正規表現では良く
・compile
・findall
が使われる。とりあえずは、この二つだけを解説する。
compileは正規表現のマッチングパータンを記述し、登録するメソッドで
findallでそのパターンを使って、引数の文字列から情報を見つけるメソッドである。それぞれの使い方は以下のとおり。
■compile
regexp = re.compile( 正規表現をかく )
カッコの所に正規表現をかく。その正規表現にマッチしているものを探す。
■findall
ret = regexp.findall( string )
Stringのパターンを渡して、そのStringの中からコンパイルで指定した条件の文章を抽出する。

実際的な使い方を以下に示す。


import re # 正規表現ライブラリのインポート
re.findall
string='''&lttd>
&lta href="nline.htm">&ltimg height="16" alt="N Line Part Time Symbol"
src="images/n_cir_c.gif" width="16" border="0" /></a>
</td>
&lttd>
&lta href="rline.htm">&ltimg height="16" alt="R Line Part Time Symbol"
src="images/r_cir_c.gif" width="16" border="0" /></a></td>'''

regexp_td = re.compile( '&lttd>.*?</td>' ) # 検索するべき正規表現パターンの記述
td = regexp_td.findall( string ) # 見つける。結果をtdの中へ

確認してみる。


for lines in td:
print lines


compileに書いた正規表現の意味だが、
「<td>ではじまり、任意の一文字(改行以外)の0文字以上の繰り返しをしたあと</td>でおわる文字列」という意味である。
ドットが任意の一文字を表し、コメがあるパターンの0文字以上の繰り返しを表す。

また、?の意味は最小でマッチング行うということを意味する。この最小マッチングとは、例えば
&lttd&gta</td>
&lttd&gtb</td>
というのがあった場合に、?を使わないで記述すると(つまりcompile( '&lttd>.*</td>' ))
最初のtdと最後の/tdがマッチングされてしまう。(最長の部分のマッチングを探してしまう)。これが嫌な場合はパターンに?をいれる。そうすることで最小マッチング、上記の例で言えば二つ抽出される。

尚注意であるが、.は任意の一文字だが実は改行は含まれない。改行も含まれるようにするにはフラグを立てる。以下のようにする。
regexp = compile( '&lttd>.*?</td>', re.DOTALL )
とする。

他にもフラグとして以下のようなものがあり、複数のフラグを'|'で連結することで調整ができる
フラグ名フラグ名短縮形解説
DOTALL S'.'を改行を含む全ての文字とマッチするようにする
IGNORECASE I大文字・小文字を区別しない
LOCALE L\w, \W, \b, \Bを現在のロケールに合わせる
MULTILINE M'^'が文字列の先頭と各行の先頭に、'$'が文字列の末尾と各行の末尾にマッチするようにする
VERBOSE X(正規表現内に'#'を用いてコメントを書くことができる)
ASCII A\w, \W, \b, \B, \s, \SをユニコードではなくASCIIにマッチするようにする


パターンに関しては以下を参考のこと。

^文字列の先頭にマッチ
$文字列の末尾にマッチ
.改行を除く任意の一文字にマッチ(設定により改行にマッチさせることも可能)
*前の表現の0回以上の繰り返しの文字列にマッチ(greedy, 可能な限り長い文字列にマッチ)
+直前の表現の1回以上の繰り返しの文字列にマッチ(greedy, 可能な限り長い文字列にマッチ)
?直前の表現の0回(空文字列)または1回の繰り返しの文字列にマッチ(greedy, 可能な限り長い文字列にマッチ)
*?"*"のnon-greedy版
+?"+"のnon-greedy版
??"?"のnon-greedy版
{n,m}直前の表現のn回以上m回以下の繰り返しの文字列にマッチ(greedy, 可能な限り長い文字列にマッチ)
{n,m}?"{n,m}"のnon-greedy版
{n}直前の表現のn回の繰り返しの文字列にマッチ
{n,}直前の表現のn回以上の繰り返しの文字列にマッチ
[...]定義した文字集合の要素とマッチ
[^...]定義した文字集合の補集合要素とマッチ
(...)グループ化
\d任意の数字([0-9])にマッチ
\D任意の非数字([^0-9])にマッチ
\s任意のホワイトスペース([ \t\n\r\f\v])にマッチ
\S任意の非ホワイトスペース([^ \t\n\r\f\v])にマッチ
\w任意の英数字([a-zA-Z0-9_])にマッチ
\W任意の非英数字([^a-zA-Z0-9_])にマッチ


compile, findall 意外に関してはpythonの標準関数のドキュメントを参考にする。



株式会社OctOpt
コンピューターサイエンス会社OctOptの技術公式ブログ
等々力 康弘
@rocky_house

BeautifulSoupを用いてタグ間の情報を抜き出す方法を記載する。
後述の正規表現でもタグの抽出がきないことはないがBeautifulSoupを使った方が楽である。

BeautifulSoupの使い方は以下のとおり。
いまHTMLファイルがあり
&amp;amp;lt;div class="foobar"&amp;amp;gt;baz....(改行も含まれて色々書かれている)&amp;amp;lt;/div&amp;amp;gt; という内容のHTMLファイルがあった場合、このなかでclassのfoobarに書かれている内容を抽出したい場合は以下のように記述する。

import BeautifulSoup
import urllib2
url = 'http://ameblo.jp/ekispresso/entry-10799874551.html'
html = urllib2.urlopen( url ).read()
soup = BeautifulSoup.BeautifulSoup( html )
ret = soup.findAll("div", {"class": "foobar"})

上記のsoup.findAllに書かれている意味は「div属性でかつクラス名が'foobar'である要素を取り出せ」という命令である。
例えば他にも
の中身をまるまる取り出したい場合は,
 ret = soup.findAll("table")

とする。spanタグなども同様にして丸々抜き出せる。
尚、うまく抽出できなかったときは空のリストが返される(タグ名がHTMLファイルに無い場合など)

抽出された内容の確認は


for s in ret:
print s
*エラーログ
エラーでUnicodeEncodeError がでる場合の対策方法(以下を参照)
UnicodeEncodeError: 'ascii' codec can't encode characters in position

もしpythonのバージョンが2.6で、Linux のUbuntu環境である場合
/usr/lib/python2.6/sitecustomize.pyを開く。そして一番下に以下を追加。
import sys
sys.setdefaultencoding('utf-8')
これでそのエラーはなくなる。



株式会社OctOpt
コンピューターサイエンス会社OctOptの技術公式ブログ
等々力 康弘
@rocky_house
IS03を購入したけど何していいか解らない!そんな人のためにアンドロイドの初歩的な使い方やおすすめアプリを書きました。
アンドロイド初心者の方は参考にしてみてください。

アンドロイドの使い方(IS03を中心に)

インストールすべきソフト、簡単なAndroidの使い方などを記したつもりです。他にも解らないことや書いてほしいことなどがありましたら教えてください。

IS03は最初はタッチパネルの感度などが非常に悪かったけど2回のアップデートで本当に良くなった!やりゃあ出来るじゃないか。まぁでもユーザインターフェイスがひどすぎる。
僕のサイトにも書いたけどADWランチャーは必須って感じ。その筋のひとから聞いたけど昔からSHARPのUIは遅いと有名らしいね。まぁIS03みたら納得かも。
さて、来週明けにはAndroidOS2.2のアップデートを開始するという噂がTwitter上で発生しているしどうなるか気になる。
Iphoneの精度にはまだまだ及ばないAndroid…でもまぁ未来はアンドロイドだろうなぁ。




株式会社OctOpt
コンピューターサイエンス会社OctOptの技術公式ブログ
等々力 康弘
@rocky_house