2012年2月13日月曜日

PythonでWebページをスクレイピング+スクレイピングしたデータをメールで送信

「ページを1日1回必ずチェックしなきゃ 」

Webページがちゃんと表示されてるか、アプリのレビューはどうなってるか、ダウンロード数はどうなっているか、などなど。
・・・理由はともあれ、そんな方は多いのではないでしょうか。

筆者もいろいろあって(?)とあるページがちゃんと表示されているかどうかを1日1回チェックすることになりました。

が、いちいち見に行くのはとっても面倒なうえに大変です。
しかも「あ、昨日チェックするの忘れてた・・・」なんてこともリスクとして容易に想像できますね。

そこで、先日公開したWM3500Rのバッテリー残量をチェックするスクリプトをベースに、Webページをスクレイピング+スクレイピングしたデータをメールで送信(レポート)するスクリプトを作成してみました。
スクレイピングにはBeautifulSoup、メール送信にはメールに関するモジュール(email.MIMEText/email.Header/email.Utils)を使いました。

メールを送信するには「受信者(送信先)のアドレス」はもちろんのこと、「送信元アドレス/SMTPサーバー」の指定/設定が欠かせません。
ここでは送信元に「Gmailのアドレス/サーバーを設定する」ことを想定してスクリプトを作成してみました。
#そのためSMTPサーバーの指定がGmailのものになっています。

このスクリプトのポイントは下記3点です。
  1. スクレイピングするページの有効/無効を「HTTPステータスコード」ではなく「取得したページに文字列が存在するかどうか」で判断条件としています。(ページによってはコンテンツが見つからない場合に、HTTP200+白紙ページを返すものがあるため)
  2. pythonは内部文字列をUnicodeとして扱っているため、内部文字列とスクレイピングした文字列を連結させたい場合には「スクレイピングした文字をUnicodeへデコード」するようにしてください。
  3. メールのメッセージをつくるときには、Subjectの位置に注意してください。SubjectをToより先に書いてメールを送信すると、To部分が "undisclosed-recipients:" となってしまう場合があります。

サンプルスクリプトはこちら。
とあるWebページの<h1>要素をスクレイピングして、その内容をメールで送るようにしています。
メールのSubjectやMessage部分は、送りたい内容が入るように main 部分を書き換えてください。


このスクリプトをcronに登録しておけば、忘れることもないですね。
ここでは毎朝5時にチェックするようにしています。
お約束ですが、過度なスクレイピングはしないようにしてください。
$ vi crontab.txt
0 5 * * * /usr/bin/env python /path/to/scrape2email.py > /dev/null 2>&1
$ crontab ./crontab.txt

筆者はPerlをよく使うのですが、こうやってPython/Rubyをたまに使ってみるのも面白いですね。
#機会があればPerlに関連するエントリも書いてみようと思います。

ステキなスクレイピングライフを!

■参考ページ
http://labs.unoh.net/2007/06/python_2.html

2012年1月19日木曜日

Android4.0で画面回転時にActivityが再起動するのを防ぐ

Android2.x 向けに作成していたAndroidアプリをGalaxyNexusで動作確認してたところ、画面を縦横に切り替えるとActivityが再起動する現象に遭遇しました。

下記のサンプルコードで画面を回転させた時のLogCatを確認したところ、API Level 13 から追加になったscreenSize を android:configChanges に指定してあげないといけないことがわかりました。


画面を回転させたときのLogCatは下記の通りでした。
※0x00000400:screenSize / 0x00000080:orientation となります。
ビットマスクの定義は下記で確認してください。
http://developer.android.com/reference/android/R.attr.html#configChanges
01-18 22:44:06.305: I/ActivityManager(193): Config changed: {1.0 440mcc20mnc en_US layoutdir=0 sw360dp w598dp h360dp nrml land finger -keyb/v/h -nav/h s.54}
01-18 22:44:06.336: I/SampleApp(11060): Configurations : [1152] / 0x00000400 / 0x00000080

ちなみにAndroidManifest.xmlは下記のようにしていました。
Android2.x系のまま手を加えていなかったため、Activityが再起動したのですね...
<activity android:name="WebViewActivity" android:configChanges="keyboard|keyboardHidden|navigation|orientation" />
そこでscreenSizeをconfigChangesに追加してあげると、画面を縦横に切り替えてもActivityが再起動することなく無事動作するようになりました。
<activity android:name="WebViewActivity" android:configChanges="keyboard|keyboardHidden|navigation|orientation|screenSize" />

これで一安心です。

■参考
http://developer.android.com/reference/android/content/pm/ActivityInfo.html#CONFIG_SCREEN_SIZE

2012年1月18日水曜日

FreeNAS0.7.2でパッケージのインストールを行う

FreeNAS(0.7.2 revision 8191)で、pkg_addを使ってunzipをインストールしようとしたところ...
# pkg_add -r unzip
Error: Unable to get ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-7.3-release/Latest/unzip.tbz: File unavailable (e.g., file not found, no access)
pkg_add: unable to fetch 'ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-7.3-release/Latest/unzip.tbz' by URL

こんな感じでエラーが出てできませんでした。
参照する先のサイト(PACKAGESITE)が存在しないのが原因のようです。

ということでPACKAGESITEを ftp.freebsd.org から ftp-archive.freebsd.org に書き換え、インストールできるようにします。
# setenv PACKAGESITE ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-7.3-release/Latest/
# pkg_add -r unzip

Fetching ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-7.3-release/Latest/unzip.tbz... Done.

できました。
パッケージをインストールしたらalias登録して使えるようにすれば完了です。
上記でインストールしたunzipは /usr/local/bin 配下に入っていたので、下記のようにalias登録します。
# alias unzip /usr/local/bin/unzip
# which unzip
/usr/local/bin/unzip

ちなみに上記でsetenvしたPACKAGESITEはログアウトしたら使えなくなるので、.profile に入れておくと入力する手間が省けて便利です。
# echo "PACKAGESITE=ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-7.3-release/Latest/" >> ./.profile
# echo "export PACKAGESITE" >> ./.profile

おつかれさまでした。

2012年1月15日日曜日

Galaxy NexusのRoot取得とbuild.propの変更方法

#完全に個人的メモ。

Galaxy Nexus(SIM Free版/Android4.0)でVMサイズとか変更したくて、Rootの取得を行いbuild.propを変更するところまでやります。

※ここでのGalaxy NexusはSIM Free版を利用しています。
(docomoさんのSC-04Dではないため注意!)
※fastbootの解除に伴う作業ならびにRoot化は、最悪起動しなくなるなどの事象が発生する可能性があります。またこの手順は個人的メモな一例となるため完全ではありません。
お約束ですが、導入/実行は自己責任でお願いいたします。


■手順
  1. Superbootのダウンロード(fastboot導入/Root取得用イメージ取得)
  2. BootLoaderのアンロック
  3. Galaxy Nexusのクリーンインストール
  4. Rootの取得
  5. busyboxインストール
  6. build.prop書き換え/反映
*前提条件:ターミナルなどが使える環境にある+AndroidSDKなど最低限必要なツールを導入済み
*筆者の環境:MacBook Air + Galaxy Nexus (SIM Free版) + USBケーブル を準備


2012年1月4日水曜日

WM3500Rのバッテリー残量をGrowl1.3+pythonで通知する

最近出先でコードを書く機会が多くなってきて、WM3500Rの使用機会が増えてきました。
DNSが少し不安定な気もしますが、コンパクトなWM3500Rとてもかわいいです。

バッテリーが意外ともつので常時ONにして持ち歩いていると
「バッテリー残量どれくらいだろう・・・(と思ってたらバッテリー切れ)」
なんてことが多くなってきました。バッテリー残量がわかりにくいのはちょっと致命的です。。

と思ってたところにユウタさんのはてダで、バッテリー残量をGrowl通知するpythonスクリプトを発見。
私の環境でも使わせていただくことにしました。

http://d.hatena.ne.jp/yutamoty/20110226/1298706870
#ユウタさんありがとうございます。


が、私の環境(Growl1.3+python2.7)では下記2点で動作しないことが発覚。
  • Growl1.3 SDK では python Binding が付属していないため import Growl が使えない
  • scrapemark が動作しない(python2.7 でインストールできませんでした...)
そこで動作するようにちょこっと改造しました。
  • SDK python Binding の代わりに gntp を利用
  • scrapemark の代わりに BeautifulSoup を利用
どちらも easy_install でかんたんにインストールできます。
sudo easy_install gntp
sudo easy_install beautifulsoup

コードは下記のようにしました。WM3500Rを接続していないときの処理も入れています。
なお、username/passwordは適宜書き換えて利用してくださいね。


あとは、cronに登録して完了です。
私は5分間隔でチェックするようにしました。
もし10分間隔に延ばしたい場合には、 */5 を */10  に書き換えてください。
vi cron.txt
*/5    *    *    *    *    /usr/local/bin/python /path/to/script/wm3500r_batterychecker.py > /dev/null 2>&1
crontab ./cron.txt

以上で設置完了です。
あとはWM3500Rに接続して、定期的にGrowl通知されることを確認してください。







おつかれさまでした。