コロラド大学からのサバイブ — コーディング編

前回の準備編に続いて、今回はコーディングに移りますが、まず最初に完成形となるコードを掲載します。

# coding: UTF-8

import os
import datetime
import mechanize
import urllib

# Set directory name.
directory_name = "images"

if not os.path.isdir(directory_name):
    os.mkdir(directory_name)

# Set dates.
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2010, 12, 31)

current_date = start_date

while current_date <= end_date:
    
    print current_date
    
    browser = mechanize.Browser()
    browser.set_handle_robots(False)
    
    # Open web page.
    response = browser.open("http://argo.colorado.edu/~realtime/modis/")
    
    # print "=== HTML Source ==="
    # print response.read()
    
    # Check forms.
    # print "\n=== Fomrs ==="
    # for form in browser.forms():
    #     print form
    
    # Select first form.
    browser.select_form(nr=0)
    
    # Set day.
    browser["month"] = [current_date.strftime("%m")]
    browser["day1"] = [current_date.strftime("%d")[0]]
    browser["day2"] = [current_date.strftime("%d")[1]]
    browser["year"] = [current_date.strftime("%y")]
    # Set location.
    browser["alon0"] = "135"
    browser["alon1"] = "160"
    browser["alat0"] = "30"
    browser["alat1"] = "45"
    # Set options.
    browser["day_opt"] = ["7"]
    browser["cont_opt"] = ["T"]
    browser["cont_anot"] = ["T"]
    
    # Check forms.
    # print "\n=== Forms ==="
    # for form in browser.forms():
    #     print form
    
    # Submit.
    response = browser.submit()
    
    # print "=== HTML Source ==="
    # print response.read()
    
    # Check links.
    # print "\n=== Links ==="
    for link in browser.links():
        # print link
        if link.url[-4:] == ".gif":
            print link.url
            urllib.urlretrieve(link.url, directory_name + "/" + current_date.isoformat() + ".gif")
    
    current_date += datetime.timedelta(7)

print "Ended."

ここからはこのコードを目指して、どういった手順で書いていくかを説明します。
 

Python でプログラムを書いてみる

エディタを使って、適当にプログラムを書きます。以下は、“Survival from the Colorado University.” という文字列を出力するだけのプログラムです。

1
print "Survival from the Colorado University."

これを “colorado.py” などと名前を付けて保存しましょう。“py” は Python プログラムの拡張子です。

ターミナルで “colorado.py” を保存したフォルダまで cd で移動し、以下のように python コマンドを用いてプログラムを実行します。

$ python colorado.py
Survival from the Colorado University.

実行すると文字列が出力されました。

日本語を使うときは注意が必要です。プログラムの1行目か2行目に文字コードを指定する必要があります。またファイル自体も同じ文字コードで保存してある必要があります。ここでは、便利がよい “UTF-8” を使います。

$ pydoc -w mechanize
wrote mechanize.html
$ open mechanize.html

これで HTML ファイルのドキュメントが生成されます。

ちょっと見にくいので、

$ pip install epydoc
...
$ epydoc --html mechanize
...
$ open html/index.html

という画期的な方法もあります。

mechanize で Web サイトにアクセスする

“colorado.py” を以下のように書き換えて、実行します。

1
2
3
4
5
6
7
8
# coding: UTF-8

import mechanize

browser = mechanize.Browser() # Create an instance of Browser class.
browser.open("http://www.google.com") # Open Google with open() method.

print browser.title() # Print title of web page with title() method.
$ python colorado.py
Google

となります。3行目で mechanize モジュールをインポートして、5行目で、mechanize モジュールから Browser クラスのインスタンスを生成しています。クラスとかインスタンスというのは、オブジェクト指向プログラミングの考え方からくる概念で、これを説明すると本が数冊書けるので、ここではごく手短に、いろいろなものをオブジェクトとして扱っていて、クラスオブジェクトっていうオブジェクトの設計図から、インスタンスオブジェクトっていう実際に使われる製品を生産する感じです。ということで、いま browser 変数に、Browser クラスのインスタンスが入っていて、これを使って色々やります!

6行目では、browseropen() メソッド(クラスに内包された関数のこと)に Google の URL 文字列を引数として渡しつつ呼び出し、要するに Google 開け、ってことです。

8行目では、browsertitle() メソッドを呼び出し、これは Web ページのタイトルを返すので、それを print しています。

ここまでで、とにかく Web ページを開けるようになりました。

自動化したい流れの確認

では、どういった処理を自動化すれば、生き残ることができるのでしょう。“Global Near-Real-Time SSH Anomaly/Ocean Color Data Viewer” のページを開いて、衛星画像を得るところまで、人力で進めてみます。

まずブラウザでページを開きます。いろいろとオプションがありますが、ターゲットとなる日付や緯度経度、“Image Source” には7日間の合成、コンターは両方をオンに、これらのフォームを埋めて “Submit values” をクリックすると、ページが遷移して、表示された画像がリンクになっているからそれをクリックすると、GIF 形式の画像が開ける。これを保存する。

これを自動化すれば、生き残れる。

Web ページのフォームを埋める

colorado.py を次のように書き換えて実行してください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# coding: UTF-8

import mechanize

browser = mechanize.Browser()
browser.set_handle_robots(False)

response = browser.open("http://argo.colorado.edu/~realtime/modis/")

print "\n=== HTML Source ==="
print response.read()

print "\n=== Fomrs ==="
for form in browser.forms():
    print form

6行目で、browserset_handle_robots() メソッドで、“robots.txt” に従わないように設定しています。これは、コンピュータによる自動収集プログラムのことをロボットということがあり、この自動収集に対するルールを Web サイト側が設定できます。これを True にするとこの Web サイトを開けませんし、今回は継続的に自動収集するわけではなく、一時的に必要なものを得るだけですから、False に設定します。このように、mechanize には実際のブラウザに偽装するための仕組みがいくつかあり、これを設定しないとアクセスできないケースがあります。

8行目で今回利用するサービスの URL (http://argo.colorado.edu/~realtime/modis/) を開き、またこのメソッドは response_seek_wrapper クラスのインスタンスを返すので、それを response 変数に入れています。

11行目で responseread() メソッドを呼び出し、HTML のソースを出力しています。

14から15行目では for ループの構文で、browser.forms() は、browser が現在開いているページにある、HTML の form 要素を抜き出し、HTMLForm オブジェクトのイテレータのかたちで返します。イテレータというのは繰り返し処理の手がかりとなるもので、Python ではこのイテレータを手がかりに、for ... in ... で簡単に走査できます。この場合では、個々のループ処理の中で form 変数に実際の HTMLForm クラスのインスタンスが入っています。16行目では実際に form を出力しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
=== HTML Source ===
...

=== Fomrs ===
<POST http://argo.colorado.edu/cgi-realtime/modis/real-timeVr1.pl application/x-www-form-urlencoded
<SelectControl(month=&#91;01, 02, 03, *04, 05, 06, 07, 08, 09, 10, 11, 12&#93;)>
<SelectControl(day1=&#91;0, *1, 2, 3&#93;)>
<SelectControl(day2=&#91;0, 1, 2, 3, *4, 5, 6, 7, 8, 9&#93;)>
<SelectControl(year=&#91;93, 94, 95, 96, 97, 98, 99, 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, *11&#93;)>
<TextControl(alon0=262)>
<TextControl(alon1=280)>
<TextControl(alat0=18)>
<TextControl(alat1=31)>
<RadioControl(day_opt=&#91;8, 7, 5, 3, *1&#93;)>
<RadioControl(cont_opt=&#91;T, *F&#93;)>
<RadioControl(cont_anot=&#91;T, *F&#93;)>
<RadioControl(degree_format=&#91;0, 1, 2, *3&#93;)>
<SelectControl(palette=&#91;*0, 1&#93;)>
<TextControl(sshcont=5)>
<TextControl(color_min=1)>
<TextControl(color_max=5)>
<TextControl(color_scale=0.01)>
<RadioControl(page_orientation=&#91;*P, L&#93;)>
<RadioControl(plot_format=&#91;*G, P&#93;)>
<SubmitControl(<None>=Submit Values) (readonly)>
<IgnoreControl(<None>=<None>)>>

出力結果を確認すると、HTML の form 要素が一つあり、それが print form で整形されて出力されていることが分かります。この出力結果を頼りにコードを書いていきます。

画像をダウンロードする