VNC自動起動 Raspberry Pi2 Raspbian8 systemd

諸事情からRaspberry PiでVNCを使いたくなったのですが、VNCの自動起動に躓いたのでメモしておきます。

Raspberry Pi2に入れたRaspbian8なのですがDebian8がベースなのでinit.d方式でなくてsystemd方式で起動プロセスが走ります。

古いRaspberry Piの記事だとRaspbian7のinit.d形式で自動起動のスクリプトが書かれていたりします。。。
しかし本来、systemdでも/etc/init.d内の起動スクリプトも実行されるはずなのですが、うまく実行されませんでした。

取りあえず、”郷に入れば郷に従え”の教えに従い、systemd方式で設定ファイルを作成したら正常に起動しました。

$ sudo su –

# apt-get install tightvncserver

# vncserver :1
※ 初回起動時はパスワードを聞かれると思いますので設定してください

# vi /etc/systemd/system/vncserver@.service

[Unit]
Description=Remote desktop service (VNC)
After=syslog.target network.target

[Service]
Type=forking
User=pi
PAMName=login
PIDFile=/home/pi/.vnc/%H:%i.pid
ExecStartPre=-/usr/bin/vncserver -kill :%i > /dev/null 2>&1
ExecStart=/usr/bin/vncserver -depth 24 -geometry 1280x800 :%i
ExecStop=/usr/bin/vncserver -kill :%i

[Install]
WantedBy=multi-user.target

# systemctl daemon-reload
# systemctl enable vncserver@1.service

これで自動起動するはずです。。。

参考サイト
Raspberry Pi • View topic – VNC server in Jessie (using a systemd service)

ESXi6.0 + CentOS7.0 に vmware-tools をインストールする

気づいたらESXi6.0が出ていたので現在試しているのですが最小構成でインストールしたCentOS7.0にvmware-toolsをインストールしてみたのでメモしておきます。

必要なパッケージをインストールします
# yum -y install perl net-tools
※ net-tools は vmware-tools で ifconfig が必要なようなのでインストールします。

あとは基本的にCentOS6以前と同じ手順で、vmware-tools をインストールするだけです。
※ インストーラを起動すると open-vm-tools でなく vmare-tools を本当にインストールするか訪ねますが”yes”と答えればインストールできます。

WordPress + SQLite3 + Docker で1分もかけずにブログを作る

最近、Dockerイメージの作成がマイブームかも知れません。
今回はイメージさえあればWordPressを1分もかけずに構築できるイメージを作成してみました。

# vi Dockerfile

FROM centos:7

# 必要なパッケージをインストール
RUN yum -y update
RUN yum -y install httpd httpd-devel zip unzip tar wget
RUN yum -y install php php-xml php-pdo php-gd php-mbstring sqlite sqlite-devel

# WordPressをインストールしてSQLite3で動作するように設定
RUN wget https://ja.wordpress.org/latest-ja.tar.gz
RUN wget https://downloads.wordpress.org/plugin/sqlite-integration.1.8.1.zip
RUN tar xvfz ./latest-ja.tar.gz
RUN unzip ./sqlite-integration.1.8.1.zip
RUN rm -f ./latest-ja.tar.gz
RUN rm -f ./sqlite-integration.1.8.1.zip
RUN mv wordpress /var/lib/wordpress
RUN chown -R apache.apache /var/lib/wordpress
RUN mv /var/lib/wordpress/wp-config-sample.php /var/lib/wordpress/wp-config.php
RUN mv sqlite-integration /var/lib/wordpress/wp-content/plugins/
RUN mv /var/lib/wordpress/wp-content/plugins/sqlite-integration/db.php \
       /var/lib/wordpress/wp-content/

# ひな形を公開ディレクトリにコピーする
RUN cp -rpf /var/lib/wordpress/* /var/www/html/

# ログイン時にひな形から展開するように定義する
RUN echo "yes n | cp -ripf /var/lib/wordpress/* /var/www/html/ > /dev/null 2>&1" >> /root/.bash_profile

EXPOSE 80
VOLUME /var/www/html

RUN systemctl enable httpd

EXPOSE 80

# docker run --privileged -itd -p 8080:80 -v /root/wordpress/public_html:/var/www/html wordpress-sqlite bash -l -c "/sbin/init"

ブログの実態はホスト側で持つので保管先のディレクトリを作成
# mkdir -p /root/wordpress/public_html
# chmod 777 /root/wordpress/public_html

コンテナ起動
# docker run –privileged -itd -p 8080:80 -v /root/wordpress/public_html:/var/www/html wordpress-sqlite bash -l -c “/sbin/init”

ブラウザで http://127.0.0.1:8080 にアクセスしてWordPressのインストール画面が表示されれば成功です。

MySQLのコンテナを作成してDBとユーザを作ってボーリュームの指定をして・・・
というのが面倒だったので小規模ならSQLite3でもいいでしょ?っというノリで作ってみました。

Apacheを使いましたが、よくよく考えて見ればNginxでも良かったなと失敗した感が・・・。
そのうち、Nginxとphp-fpmとSQLite3を組み合わせたDockerイメージを作成してみたいと思います。

Go言語で画像ダウンローダを書いてみた

先ほどのGo言語で皆大好き htpdate を書いてみたに続いて画像をダウンロードするスクリプトを書いてみました。
PerlやRuby、Pythonほどスクレイピングをするライブラリは充実していないものの”goquery”というライブラリがGo言語でソコソコ使えそうだったので使用してみました。

ライブラリ(goquery)のインストール
# go get github.com/PuerkitoBio/goquery

ソースコード(事情は下に書きますが殴り書きです)
# vi downloader.go

package main

import (
  "os"
  "fmt"
  "path"
  "net/url"
  "net/http"
  "io/ioutil"
  "github.com/PuerkitoBio/goquery"
)

func GetImgUrl(base string) []*url.URL {
  var src_url_list []*url.URL

  doc, _ := goquery.NewDocument(base)
  doc.Find("img").Each(func(_ int, s *goquery.Selection) {
    src, exists := s.Attr("src")
    if exists {
      base, _ := url.Parse(base)
      srcs, _ := url.Parse(src)
      src_url_list = append(src_url_list, base.ResolveReference(srcs))
    }
  })

  return src_url_list
}

func DownloadFiles(url_list []*url.URL) {
  for id, url := range url_list {
    raw_url := url.String()

    _, filename := path.Split(raw_url)
    filepath := path.Join("download", filename)

    response, err := http.Get(raw_url)
    body, err := ioutil.ReadAll(response.Body)

    if err != nil {
      fmt.Println(err)
    }

    file, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY, 0666)

    if err != nil {
      fmt.Println(err)
    }

    file.Write(body)
    file.Close()

    fmt.Printf("[%d]%s %s\n", id, raw_url, filename)
  }
}

func main() {
  url := "http://akiba-pc.watch.impress.co.jp/"
  url_list := GetImgUrl(url)

  DownloadFiles(url_list)

}

ダウンロード先のディレクトリの作成
# mkdir download

スクリプトの実行
# go run downloader.go

[0]http://akiba-pc.watch.impress.co.jp/include/common/p01/images/logo/ah.l.png ah.l.png
[1]http://akiba-pc.watch.impress.co.jp/include/common/p01/images/global-nav/gn_headline.png gn_headline.png
[2]http://akiba-pc.watch.impress.co.jp/include/common/p01/images/global-nav/gn_clw.png gn_clw.png
[3]http://akiba-pc.watch.impress.co.jp/include/common/p01/images/global-nav/gn_pcw.png gn_pcw.png
[4]http://akiba-pc.watch.impress.co.jp/include/common/p01/images/global-nav/gn_dcw.png gn_dcw.png
[5]http://akiba-pc.watch.impress.co.jp/include/common/p01/images/global-nav/gn_ah.png gn_ah.png
~~~以下省略~~~

実は、Go言語の”channel”や”goroutine”など並列処理に関する実装方法について勉強するつもりで殴り書きしてたのですが、今日は時間がなさそうなので書いたところまでメモがてらに記事を書いていたりします(汗

Go言語で皆大好き htpdate を書いてみた

PCやサーバの時間合わせにntpdateを通常用いますが、80番と443番しか外部接続を許されないネットワークだとNTPが使えない事があります。そんな時にNTPの代替としてWEBサーバの時間を元にマシンの時間を合わせるコマンドが”htpdate”です。

仕組はHTTPのレスポンスヘッダに含まれる”Date”を元にソコソコ正確な時間を取得してOSの時間を設定します。
とても単純明快で清々しいくらいです。

例えばこのサーバだと、このようなレスポンスヘッダが帰ってきます。
この中の「Date: Wed, 08 Apr 2015 11:35:10 GMT」がサーバの時間となります。

HTTP/1.1 200 OK
Date: Wed, 08 Apr 2015 11:35:10 GMT
Server: Apache/2.2.3 (CentOS)
Last-Modified: Fri, 29 Jun 2012 10:40:46 GMT
ETag: "16e07e-5-4c39a14ab6780"
Accept-Ranges: bytes
Content-Length: 5
Connection: close
Content-Type: text/html

# vi htpdate.go

package main

import (
  "os"
  "fmt"
  "time"
  "syscall"
  "net/http"
)

// HTTPサーバへアクセスしてヘッダーからアクセス日時を取得する関数
func get_http_date(url string) (string, error) {
  response, err := http.Get(url)
  if err != nil { return "", err }

  access_time := response.Header.Get("Date")
  return access_time, nil
}

// 引数として受け取ったUNIXタイムをOSの時間に設定する関数
func settime(sec int64, usec int64) error {
  tv := syscall.Timeval{ Sec: sec, Usec: usec }

  return os.NewSyscallError("settimeofday", syscall.Settimeofday(&tv))
}

func main() {
  if len(os.Args) > 1 {
    // とりあえずHTTPサーバを1個だけ引数に受け取る
    host_name  := os.Args[1]
    target_url := "http://" + host_name

    // HTTPサーバからアクセス日時を取得
    access_time, err := get_http_date(target_url)
    if err != nil {
      fmt.Fprintln(os.Stderr, "Failed to access the HTTP server.")
      os.Exit(1)
    }

    // 取得した時間をパーズする
    server_time, err := time.Parse(time.RFC1123, access_time)
    if err != nil {
      fmt.Fprintln(os.Stderr, "Time of format is not a RFC1123.")
      os.Exit(1)
    }

    // 取得した時間をOSの時間として設定する
    if err := settime(server_time.Unix(), 0); err != nil {
      fmt.Fprintln(os.Stderr, "Failed to set the date and time.")
      os.Exit(1)
    }

    fmt.Println(time.Now())
    os.Exit(0)
  } else {
    fmt.Fprintln(os.Stderr, "Please set the HTTP server to argument.")
    os.Exit(1)
  }
}

実行してみると時間が設定される事が分かるはずです。
# go run htpdate.go orsx.net

2015-04-08 21:05:18.000046645 +0900 JST

Proxyなどは対応していませんがGo言語を勉強するうえで良い教材になりそうな気がしたので簡単に実装してみました。

[HTTP Time Protocol / htpdate] Webプロキシを経由して時刻を同期するの巻 – TrippyBoyの愉快な日々
Introduction | HTTP Time Protocol

CentOS 7.0 Go言語 + revel な環境をDockerで構築する

revelとはGo言語で作られたWebアプリケーションフレームワークです。

Go言語自体はC++の代用を試みて開発されている言語なので高速で処理を行えます。
さらに、スクリプト言語に近い形で記述することができて並列処理も得意としています。

そんなGo言語を使って作られたフレームワークは当然のごとく爆速らしいです。

そんなGo言語+revelを最近流行りのDockerを使って開発環境を作りたいと考えました。

イメージとしては、こんな感じにしたいと思います。

1,「Go言語+revel」のイメージ
2,「MySQLなどのデータベース」のイメージ
2, ソースコードやデータベースファイルなどを管理する環境
※ 取りあえず、今回は(1)のみを作成します。

CentOS7.0にDockerのインストールを行う場合は特にリポジトリの追加も必要なく以下のような感じに行う事ができます。

# yum -y update
# yum -y install docker
# systemctl enable docker
# systemctl start docker

※ SELinuxやファイアウォールは各自で設定を行ってください。

雛形となるDockerイメージを作成します。
Dockerfileと呼ばれるファイルにコンテナの構成内容をガリガリ書いていきます。

# vi Dockerfile
FROM centos

RUN useradd revel

RUN yum -y update
RUN yum -y install golang git mercurial sqlite sqlite-devel

ENV GOPATH /var/gocode/
RUN echo 'export GOPATH="$GOPATH"' >> /etc/profile
RUN echo 'export PATH="$PATH:$GOPATH/bin"' >> /etc/profile

RUN mkdir /var/gocode/

RUN go get github.com/revel/revel
RUN go get github.com/revel/cmd/revel
RUN go get github.com/mattn/go-sqlite3

RUN source /etc/profile; revel help

USER revel

ENV HOME /home/revel/
ENV GOPATH /home/revel/gocode/

RUN mkdir -p /home/revel/gocode/{bin,pkg,src}

RUN echo 'export GOPATH="$GOPATH"' >> ~/.bash_profile
RUN echo 'export PATH="$PATH:$GOPATH/bin"' >> ~/.bash_profile
RUN echo 'yes no | cp -ripf /var/gocode /home/revel/ > /dev/null 2>&1' >> ~/.bash_profile

EXPOSE 9000
VOLUME /home/revel/gocode/src/

# docker run -it -p 9000:9000 revel bash --login
# docker run -it -p 9000:9000 --volume /root/src:/home/revel/gocode/src revel bash --login
# docker run -it -p 9000:9000 --volume /root/src:/home/revel/gocode/src revel bash --login -c 'revel run sample'

※ revelの実行は原則的にrevelユーザが行います。
※ revelの雛形は/var/gocode/の中に存在していてそれを元にログインのたびに初期化して使用します。
※ revelのソースコードはホスト側や別のコンテナなど外部のボリュームで管理できるようにします。

Dockerfileを元にイメージをビルドします。
イメージにはrevelというイメージ名を付けました。

# docker build --no-cache -t revel .

※ キャッシュを使用しないオプションをつけていますが必要なければ外してしまっても問題ありません。

イメージ一覧はこのように確認できます。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
revel               latest              fb1a981ee328        About an hour ago   753.7 MB
centos              7                   88f9454e60dd        2 weeks ago         223.9 MB
centos              centos7             88f9454e60dd        2 weeks ago         223.9 MB
centos              latest              88f9454e60dd        2 weeks ago         223.9 MB

ホストOS側にソースコードを格納するディレクトリを作成します。

# mkdir /root/src
# chmod 777 /root/src

イメージを元にコンテナを作成してシェルを起動し、フレームワークのサンプルを生成してみます。

# docker run -it -p 9000:9000 -v /root/src:/home/revel/gocode/src revel bash --login
$ revel new sample
$ revel run sample

ブラウザからアクセスできる事を確認します。
URLの例) http://127.0.0.1:9000

WS000010

このような画面が表示できたら一度終了して、ホスト側にソースコードが保存されている事を確認します。

# ls -al /root/src
合計 4
drwxrwxrwx  6 root root   74  3月 20 21:56 .
dr-xr-x---. 3 root root 4096  3月 20 22:19 ..
drwxr-xr-x  3 1000 1000   14  3月 20 21:56 code.google.com
drwxr-xr-x  5 1000 1000   45  3月 20 21:56 github.com
drwxr-xr-x  3 1000 1000   24  3月 20 21:56 gopkg.in
drwxrwxr-x  7 1000 1000  100  3月 20 21:56 sample # <-- これ

新たにコンテナを作成して今度は直接フレームワークを起動します。

# docker run -it -p 9000:9000 -v /root/src:/home/revel/gocode/src \
  revel bash --login -c 'revel run sample'

これで先ほどと同じようにブラウザでアクセスできるはずです。

取りあえず、イメージを作成してみて・・・
予想以上に試行錯誤したので中々大変でしたが、今後の開発に大きく影響を及ぼすような可能性を感じました。

参考サイト
» Docker上でRailsアプリケーション開発 TECHSCORE BLOG
Go – 「最速」フルスタックWebフレームワーク「revel」の紹介 – Qiita

RC-S620/SをFeliCaカードに成りきらせて好きなIDmで応答するようにする

IMG_3999
※ ArduinoとRC-S620/Sの接続については(ArduinoでRELET(FeliCa電子マネー残高照会機)モドキを作ろう)で図を描いているのでそちらを参考にしてください。

ライブラリの拡張

公式で提供されているArduino用ライブラリを拡張する必要があります。

RCS620S.h 29行目付近に追加

int tginit(const uint8_t* idm);

RCS620S.cpp 80行目付近に追加

int RCS620S::tginit(const uint8_t* idm)
{
    uint8_t  response[RCS620S_MAX_RW_RESPONSE_LEN];
    uint16_t responseLen;

    /* TgInitTarget command parts */
    uint8_t command[RCS620S_MAX_RW_RESPONSE_LEN] = {0x00};
    uint8_t param_1[ 9] = {0xd4, 0x8c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40};
    uint8_t param_2[10] = {0xff};

    /* Make TgInitTarget command */
    memcpy(&command[ 0], param_1,  9);
    memcpy(&command[ 9], idm,      8);
    memcpy(&command[17], param_2, 10);
    memcpy(&command[27], idm,      8);

    /* Execute TgInitTarget */
    rwCommand(command, 41, response, &responseLen);

    return 1;
}

スケッチの作成

Arduino側のスケッチ

#include <RCS620S.h>
#include <string.h>

RCS620S rcs620s;

void setup()
{
  int ret;

  Serial.begin(115200);
  ret = rcs620s.initDevice();
  while (!ret) {}
}

void loop()
{
  int ret;
  
  // SET IDm
  ret = rcs620s.tginit((const uint8_t*)"\x08\x07\x06\x05\x04\x03\x02\x01");
  rcs620s.rfOff();
}

Burp Suiteを使ってスマホアプリの通信を調査する

目的
スマホアプリの作成やマルウエアが流行しているので手軽に通信を解析できる手段を確保しておきたいと思いました。
今回、Burp Suiteと呼ばれるHTTPやHTTPSを解析するソフトウェアの使い方を紹介したいと思います。

※ SSL/TLSの仕組みなどについてはある程度、知識があることが前提で解説を進めます。

準備
Burp Suiteのダウンロードページからburpsuite_free_v1.6.jarをダウンロードして実行します。
※ このソフトウエアの実行にはJavaのランタイムが必要です。

Burp Suiteの起動
ダウンロードしたjarファイルをダブルクリックしてBurp Suiteを起動します。

Burp Suiteの設定
標準設定ではローカルホスト内でしかアクセスできないため、他の端末からアクセスできるように設定します。

Burp Suiteを起動したら、以下の様なウインドウが表示されます。
WS000002

[Proxy]タブをクリックし、[Options]タブをクリックします。
8080番のポートを使う設定がデフォルトで入っているのでそれを選択し、[Edit]をクリックします。
WS000003

[All interfaces]にチェックを入れて[OK]をクリックします。
WS000004

これで他の端末からこの、PCで起動しているBurp Suiteへアクセスできるようになったはずです。

Burp Suiteの証明書作成
クライアント側のブラウザなどに導入するルート証明書を作成します。

[Proxy]タブをクリックして、[Options]タブをクリックします。

[CA certificate …]をクリックすると以下のようなウインドウが表示されます。
[Export]の中にある[Certificate in DER format]を選択して[Next]を押します。
WS000005

途中、保存先の選択などがありますがファイル名(拡張子:crt)などを指定するだけで特に困ることもないはずです。

証明書を作成すると以下の様なファイルが生成されます。
WS000007

Android端末への証明書導入
先ほど作成した証明書をSDカードなどにコピーしてAndroid端末に導入します。

[設定]から[セキュリティ]をクリックし、[SDカードからインストール]をクリックします。
2014_07_12_14.29.27

証明書を置いた場所まで移動し、証明書を選択します。
2014_07_12_14.44.22

証明書の名前を指定して[OK]をクリックします。
2014_07_12_14.45.30

Android端末のProxy設定
無線LANのアクセスポイント名からProxy設定(Burp Suiteを起動しているパソコンのIPアドレスとポート番号)を行います。
※ Android端末でのProxy設定については情報がありふれているので省略します。

Android端末で行われている通信の確認
Android端末上で動いているアプリが行った通信の内容が確認します。

[Proxy]タブをクリックして、[HTTP history]タブをクリックします。
HTTPだけでなくHTTPSの通信も複合されているためリクエスト・レスポンス双方の通信内容を確認する事ができます。
WS000009

今回、Android端末を用いて書いていますが、基本は対象がiPhoneでもパソコンでも行う事はさほど変わりません。

以下は、状況に応じて設定してください。

Burp Suiteで通信を毎回止めたくない時の設定
Burp Suiteを介して通信を行うとリクエストごとに毎回[Forward]ボタンを押さなければなりません。
リクエスト内容を書き換えたいときは便利なのですが、単純に通信を見たいときは邪魔なので以下の設定を行います。

[Proxy]タブをクリックして、[Options]タブをクリックします。

[Intercept Client Requests]で[Is in target scope]を選択して有効化します。
WS000008

Burp Suiteの日本語表示
Burp Suiteで解析した通信に日本語が混在していた場合、日本語が化けて見えなくなるため、見えるように設定します。

[Options]タブをクリックして、[Display]タブをクリックします。
[HTTP Message Display]のフォント設定を日本語用のフォントに変更します。
WS000006

※ 証明書の導入などもあるため大丈夫だとは思いますが、くれぐれも悪用などしないようお願い致します。

参考サイト
Burp Proxy で iPhone の通信をパケットキャプチャ
[改訂版] iPhoneアプリのSSL接続をパケットキャプチャする方法 | [ bROOM.LOG ! ]

CentOS7 ネットワーク設定 消えた ifconfig と system-config-network について

CentOS7がリリースされましたのでネットワークについて若干メモを残しておきます。

CentOS6以前は以下のコマンドでIPアドレスを確認していました

# ifconfig

CentOS7以降は以下のコマンドを使うようになるみたいです

# ip addr show

CentOS6以前は以下のコマンドを使用してネットワークやIPアドレスの設定をしていました

# system-config-network

CentOS7以降は以下のコマンドを使用してネットワークやIPアドレスの設定を行うようです

対話式の場合
# nmtui

コマンドラインベース
# nmcli

Python版 ぴくぴくダウンローダーを作成している夢を見た

完全オープンソースにするか悩みどころですが取りあえずモチベーション維持のためにもちょくちょくソースコードを公開していこうと思います。

単純にダウンロードするなら簡単なんですが、アレもできてコレもできてとなると中々大変なんですよね(汗

GUIを作るのがかなりしんどいので取りあえず、いつも通りCUI版を作ってGUIを上からかぶせる感じで行こうと思います。
実はTideSDKを使う予定だったけど暗礁に乗り上げてます。誰かアドバイスをください。
※ 毎回GUI後付でやってるけどうまく行っている気がしない・・・

今回の目標
・Pythonを触ったことがない人でも処理をおおまかに理解できるよう書く(そもそも自分がPythonド素人)
・Java版の時みたいに糞長いソースコードを力押しで書かない(今後の保守性を再優先)
・Perl版の時みたいに正規表現のスクランブルにしない(あれは黒歴史)

# vi PixivBrowser.py

# -*- coding:utf-8 -*-
#################################################################
#
# Pixivのブラウザエミュレータ
#
#  Pixivの接続情報を保持する
#  UA設定やProxy設定を組み込むかもしれない
# 
# 【制作開始日時】 2014/06/25
# 【   製作者   】 orbit
# 【  動作環境  】 Python 2.7 (Win, Mac, Linuxで動くのが理想)
#
# 【   更新日   】
#    2014/06/25    ログイン処理に関する部分を作成 
#                  seleniumを使うか悩んだがPixivへの負荷を考慮
#
#    2014/06/27    認証を行うメソッドの名前を変更
#
#################################################################
import mechanize

# Pixivのブラウザエミュレータを担当するクラス
class PixivBrowser(object):
  def __init__(self):

    # Pixivのログインページ
    self.loginurl = 'https://www.secure.pixiv.net/login.php'
    # Pixivのユーザーページ
    self.userpage = 'http://www.pixiv.net/mypage.php'

    # ブラウザエミュレータのインスタンス生成
    self.browser = mechanize.Browser()

    # 当然検索エンジンよけを無視
    self.browser.set_handle_robots(False)

  # Pixivの認証を行う
  def auth(self, username, password):
    # ユーザ情報
    self.username = username # ユーザー名
    self.password = password # パスワード

    # ログインページを開く
    self.browser.open(self.loginurl)
    
    # ユーザ名とパスワードを指定してログイン
    self.browser.select_form(nr=1)
    self.browser["pixiv_id"] = self.username
    self.browser[  "pass"  ] = self.password
    self.browser.submit()

    # ログインに成功した確認する
    res = self.browser.response() # レスポンスを受け取る
    url = res.geturl()            # 現在のURLを取得する

    # ログイン後にユーザページにいないのはログイン失敗
    if(url != self.userpage):
      # ログインに失敗した場合はどうしようもないので例外を投げる
      raise PixivBrowserException("login failed. please check you are account.")

    # ログインページのHTMLを取得
    html = self.browser.response().read()

    # 問題なくログインできたらドヤ顔でログインページのHTMLを返す
    return html

  # ブラウザエミュレータを返す
  def getBrowser(self):
    return self.browser

# PixivBrowserのプログラム内で処理継続が不能になったら呼ばれる例外クラス
class PixivBrowserException(Exception):
  def __init__(self, str):
    self.str = str   # strはraise文から受け取る引数

  def __str__(self): # エラーメッセージ
    return '%s' % (self.str)

## 以下、デバッグ用の処理 ##
if __name__ == '__main__':
  pb = PixivBrowser()
  pb.auth('**************', '**************')

# vi PixivSearch.py

# -*- coding:utf-8 -*-
#################################################################
#
# Pixivの絵画(絵・漫画)を検索・ページングするプログラム
#
#  検索で並び順の変更に対応するかもしれない
# 
# 【制作開始日時】 2014/06/27
# 【   製作者   】 orbit
# 【  動作環境  】 Python 2.7 (Win, Mac, Linuxで動くのが理想)
#
# 【   更新日   】
#    2014/06/27    検索とページングを行う部分を作成
#                  絵・漫画・小説の他にうごくイラストをサポート
#
#################################################################

# Pixivの絵画(絵・漫画)を検索するクラス
class PixivSearch(object):
  def __init__(self, browser):
    ## ページ情報 ##
    # Pixivのユーザーページ
    self.userpage = 'http://www.pixiv.net/mypage.php'
    # 検索ページベース
    self.pixibass = 'http://www.pixiv.net'
    
    # 並び順
    self.pagesort = '&order=date_d'
    
    # ページ番号
    self.pagenumb = 1;
    
    ##  ブラウザ  ##
    self.browser   = browser
  
  # 通常の検索(絵・漫画混在) 今回、仕様的に使うか微妙
  def search(self, keyword):
    # 検索キーワード
    self.keyword = keyword
    
    # 検索パラメータをつける
    self.searcurl = self.pixibass + '/search.php?word=' + keyword + self.pagesort + '&p='
    
    # ページ番号を付加して検索ページを開く
    self.browser.open(self.searcurl + str(self.pagenumb))
    
    # 検索結果ページのHTMLを取得
    html = self.browser.response().read()
    
    # 検索結果ページのHTMLを返す
    return html
  
  # 絵の検索
  def searchImage(self, keyword):
    # 検索キーワード
    self.keyword = keyword
    
    # 検索パラメータをつける
    self.searcurl = self.pixibass + '/search.php?word=' + keyword + '&manga=0' + self.pagesort + '&p='
    
    # ページ番号を付加して検索ページを開く
    self.browser.open(self.searcurl + str(self.pagenumb))
    
    # 検索結果ページのHTMLを取得
    html = self.browser.response().read()
    
    # 検索結果ページのHTMLを返す
    return html
  
  # 漫画の検索
  def searchComic(self, keyword):
    # 検索キーワード
    self.keyword = keyword
    
    # 検索パラメータをつける
    self.searcurl = self.pixibass + '/search.php?word=' + keyword + '&manga=1' + self.pagesort + '&p='
    
    # ページ番号を付加して検索ページを開く
    self.browser.open(self.searcurl + str(self.pagenumb))
    
    # 検索結果ページのHTMLを取得
    html = self.browser.response().read()
    
    # 検索結果ページのHTMLを返す
    return html
  
  # うごくイラストの検索
  def searchUgoku(self, keyword):
    # 検索キーワード
    self.keyword = keyword
    
    # 検索パラメータをつける
    self.searcurl = self.pixibass + '/search.php?word=' + keyword + '&type=ugoira' + self.pagesort + '&p='
    
    # ページ番号を付加して検索ページを開く
    self.browser.open(self.searcurl + str(self.pagenumb))
    
    # 検索結果ページのHTMLを取得
    html = self.browser.response().read()
    
    # 検索結果ページのHTMLを返す
    return html
  
  # 小説の検索
  def searchNovel(self, keyword):
    # 検索キーワード
    self.keyword = keyword
    
    # 検索パラメータをつける
    self.searcurl = self.pixibass + '/novel/search.php?s_mode=s_tag&word=' + keyword + self.pagesort + '&p='
    
    # ページ番号を付加して検索ページを開く
    self.browser.open(self.searcurl + str(self.pagenumb))
    
    # 検索結果ページのHTMLを取得
    html = self.browser.response().read()
    
    # 検索結果ページのHTMLを返す
    return html
  
  # ページ番号を前進
  def nextPage(self):
    # ページ番号をインクリメントする
    self.pagenumb = self.pagenumb + 1
    
    # 次のページ番号を返す
    return self.pagenumb
  
  # ページ番号を後進 今回、仕様的に使うか微妙
  def backPage(self):
    # ページ番号をデクリメントする
    self.pagenumb = self.pagenumb - 1
    
    # 次のページ番号を返す
    return self.pagenumb
  
  # 現在のページ番号を得る
  def getPage(self):
    # 現在のページ番号を返す
    return self.pagenumb
  
  # 現在のページ番号を変更する
  def setPage(self, page):
    # ページ番号を書き換える
    self.pagenumb = page
    
    # 現在のページ番号を返す
    return self.pagenumb

# PixivSearchのプログラム内で処理継続が不能になったら呼ばれる例外クラス
class PixivSearchException(Exception):
  def __init__(self, str):
    self.str = str   # strはraise文から受け取る引数

  def __str__(self): # エラーメッセージ
    return '%s' % (self.str)

## 以下、デバッグ用の処理 ##
if __name__ == '__main__':
  from PixivBrowser import *

  pb = PixivBrowser()
  pb.auth('**************', '**************')
  browser = pb.getBrowser()

  ps = PixivSearch(browser)
  #print ps.search("ミク")
  #print ps.searchImage("ミク")
  #print ps.searchComic("ミク")
  #print ps.searchUgoku("ミク")
  #print ps.searchNovel("ミク")
  ps.setPage(100)
  ps.nextPage()
  print ps.search("ミク")

進捗状態
次は検索結果のHTMLを構文解析するクラスと作品ごと情報を保持するクラスを作成する予定
ID検索の部分に入るまでもう少し時間がかかりそうな予感