読み書きプログラミング

日常のプログラミングで気づいたことを綴っています

Herokuで無料でたくさんTwitter Streamingボットを実装する方法

Herokuでは、ここ2年ほどで無料のdynoに関して変遷がありましたが、今はアカウント毎に毎月所定の時間のdyno hourを割り当てるということに落ち着いたようです。

Twitterでリプライやフォローバックをリアルタイムで自動でしようと思うと、Streaming APIを利用するのが効率的ですが、Streaming APIを毎日24時間モニタするには24時間*31日のdyno hourをworkerで消費します。

無料分でやろうと思うと1つが限度ですね。
でも、もしもボットがCPUもメモリもそれほど食わないなら、フリーのdynoには512MBのメモリと4core-8threadのCPUが味方ですから、複数のボットを1つのdynoで動かせるはずです。

その方法をご紹介します。

使用言語はPythonを仮定しました。

1. PythonのForemanクローン、honchoを使う。
Herokuアプリの基本になるProcfileは以下のようになります。

worker: honcho -f ProcfileHoncho start

(*ProfileHochoは任意のファイル名です)

2. 続いてProcfileHonchoに動かしたいボットアプリを記述します。

mimiaka1846: python3 mimiaka/stream.py
retweet_ramen: python3 retweet_ramen/retweeter.py

(*注
mimiaka1846は私が運営している耳赤サイト用アカウントmimiaka1846の自動フォローバックアプリです。
retweet_ramenは私が運営しているラーメンなう。(@retweet_ramen)の自動リツイートアプリです。)

Python3を使いましたのでruntime.txtは以下の通りです。

python-3.6.0

後は、それぞれのアプリをコーディングして、使用したパッケージ情報まとめたrequirements.txtを用意すれば完了です。

CPUパワーとメモリが許す限り、ProcfileHonchoに何個アプリを追加しても、消費する無料dyno hourは変わりません。

RustによるWeb Assembly事始め

2018/02/14 追記
去年の11月25日にRustのnightly本体でwasm32-unknown-unknownサポートされたようです。なので、本記事はobsoleteです。

Rustが安定版1.14.0でWeb Assemblyを実験的にサポートしました。

blog.rust-lang.org

asm.js関連技術を使うにはC/C++に戻らないといけないのかとげんなりしていたので、これほどありがたいことはありません^^

EmscriptenによるWeb Assembly

早速、Web Assemblyから試してみました。macOSでのメモです。

1. Emscriptenをインストール

EmscriptenC/C++JavaScriptコンパイルするコンパイラです。RustもWeb Assemblyを出力する際にEmscriptenを利用します。

Emscripten SDKをダウンロードしてドキュメントのインストラクションに従うのが一番問題がないです。HomeBrewとか考え出すとLLVMのインストール時のコンパイルオプションとか色々ハマります。
Download and install — Emscripten 1.37.33 documentation

2. Firefox Developer Editionをインストールする

2017年1月5日現在、Web Assemblyをネイティブサポートしているのは、Developer Editionだけのようです。(製品版は有効化するフラグはあったのですが、ネイティブサポートされていませんでした)

www.mozilla.org

アドレスバーでabout:configを開き、javascript.options.wasmをtrueに設定します。
これでWeb Assemblyが有効になります。

3. hello.cをコンパイルする
#include <stdio.h>

int main(void)
{
  printf("Hello, World!\n");
  return 0;
}

という内容のhello.cを用意して、

emcc hello.c -o hello.html -s BINARYEN=1
chmod a+r hello.js

を実行します。
(初回は、Binaryenのインストールが実行されます(と思います))
生成されたhello.jsのパーミッションがユーザーオンリーになってるのでchmodしています。

4. 実行する

コンパイルして生成されたファイルをウェブサーバーがアクセスできるようにしてください。
それが終わったら、hello.htmlをFirefox Developer Editionでブラウズします。

以上です。
上記手順から外れると意外と苦労するかもしれませんよ(体験談)

RustによるWeb Assembly 実行編

続いてRustで同じことをします。

Rustはrustupを使って最新版(1.14.0以降)がインストールされているとします。

1. hello.rsをコンパイルする
fn main() { println!("Hello, World!"); }

という内容のhello.rsを用意して、

rustc --target=wasm32-unknown-emscripten hello.rs -o hello.html
chmod a+r hello.js

を実行します。

2. 実行する

Emscriptenの時と一緒です。hello.jsのパーミッションに注意。

RustによるWeb Assembly 関数呼び出し編

DOM関連の操作はJavaScriptでするのがよいかと思うので、RustのライブラリをJavaScriptから呼び出す方法が必要になるかと思います。やってみましょう。

1. hello.htmlを変更する
「RustによるWeb Assembly 実行編」で生成したhello.htmlに関数呼び出しを組み込みます。
具体的には

  script.src = "hello.js";
  document.body.appendChild(script);

の2行の間に

  script.onload = function() {
    var hello_world = Module.cwrap('hello_world', 'number', ['number']);
    console.log(hello_world(41));
  };

を追加します。これが、Rustで書かれた関数hello_worldをJavaScriptから呼び出す方法です。

2. hello.rsを変更する

#![feature(link_args)]
#[link_args = "-s EXPORTED_FUNCTIONS=['_hello_world']"]

extern {}

#[no_mangle]
pub extern fn hello_world(n: i32) -> i32 {
    n + 1
}

fn main() { } // ダミー。関数をエクスポートすると実行されない模様

link_argsでエクスポートする関数を指定します。
extern {}や#[no_mangle]はおまじないと思ってください。

3. rustをnightlyに変更
featureを使う場合、rustをnightlyバージョンにする必要があります。

rustup override set nightly

を実行してください。

4. コンパイルする

rustc --target=wasm32-unknown-emscripten hello.rs
chmod a+r hello.js

上記例と違い、オプション -o hello.htmlを省略することに注意してください。

5. 実行する
hello.htmlをFirefox Developer Editionでブラウズします。
ウェブコンソールを開くと、計算結果42が表示されていることを確認できるはずです。
(ウェブコンソールを開いたまま、ページを再読込するとページがクラッシュするようです。)

WGoエディタ

追記(2016-11-14]
SabakiというElectronベースの良さげなSGFエディタがありました。

github.com

こちらを利用させていただきます。なのでWGoエディタの開発は中止します_o_

version 0.19.0のmacOSバイナリはうまく動かないようです。githubレポジトリをcloneしてnpm run build:osxしてできるアプリはうまく動きました。

WGo.jsを使ってSGFエディタを作りました。

github.com

NW.jsを使いました。NW.jsいいですね。クライアントサイドのウェブアプリがそのまま載って、システムにアクセスする部分だけNode.jsのAPI使って追加したらいい。メニュー部分で少し悩みましたが、簡単に作ることができました。

Excite翻訳非公開APIの変更があったようです

Exciteの翻訳は特に中国語、韓国語の翻訳の精度が高く重宝しています。
また、URLにクエリパラメータを指定すると指定の翻訳ができるのも便利でした。
最近、(6月20日頃から)この、クエリパラメータ指定がうまくいかなくなって、原因を調べたところ、HTTPメソッドがGETでいけていたところがPOSTに変更になったようです。

URL: http://www.excite.co.jp/world/chinese/
parameters:
    before: <翻訳したい文章>
    wb_lp: <言語指定>

でHTTP POSTすると翻訳を載せたウェブサイトを取得できます。<言語指定>は、例えば中国語を日本語に翻訳するなら、"CHJA"と指定します。

Mac用外付けSSDドライブ

[2016年7月6日追記]
以下の内容間違っていました。
trimforceを使わない(disable)状態でもその後フリーズが起こるようになりました。
どうもネットワーク絡みのようです。フリーズした時にWiFiルータを再起動すると復帰する感じがあります。



要約

  • ELECOM SSD ESD-E0256U3はMacの起動ディスクとしては使えなかった。
  • Transcend Thunderbolt対応 USB3.0/2.0 SSD StoreJet for Mac TS256GSJM500はMacの起動ディスクとして良好。ただし、sudo trimforce enableはしてはいけない。

27インチ iMac Late 2012を愛用しています。
最近のOS Xへの不満は置いておいて、ハードディスクのスピード以外全く不満ありません。
ただ、MacBook AirSSDに慣れたせいか、特に起動時のハードディスクの遅さだけは不満でした。
(円安が進んだ時に、未カスタマイズの型落ち品を買ったのでフュージョンディスクではないのです)

購入して3年近く経って、外付けSSD付けたら解決することに気がつきました^^;
今年の4月に購入して色々あって最近安定してきたので、メモを残します。

最初に、ELECOM SSD 外付けSSD 256GB USB3.0 MLC ESD-E0256U3Fを購入しました。
起動用ディスクで速度を求める場合、MacならI/FとしてUSB3.0かThunderboltの選択肢があります。
Thunderboltはまだまだ割高なのでUSB3.0を選びました。

結論ですが、この製品は追加ドライブとして使用した場合十分な性能が出たのですが、起動ドライブとしてしようすると速度が出ませんでした。ハードディスクより遅いぐらい。
初期不良かと一度交換してもらいましたが、現象は変わらず。返金ということになりました。

次はTranscend Thunderbolt対応 USB3.0/2.0 SSD StoreJet for Mac 256GB TS256GSJM500を購入しました。USBコントローラの相性問題があるかと思うと他のUSB3.0製品を試す気持ちになれなかったので、少し奮発したということです。

この製品は、起動ドライブとして使っても素晴らしいスピードで、ずいぶん快適になりました。
巷の記事に従って、早速trimをenable。(使用しているうちにSSDのスピードが遅くなる現象を回避できるらしいです)
これがよくなかったようです。

満足して使っていたのですが、どうも2日に1度ぐらいの頻度でOSがフリーズします。おかしいなと思いつつ、電源を落として入れ直せばすぐ起動してくれるのでまあいいかと^^;

最近、流行りのディープラーニングをやり始めました。これがまた2日3日と走らせる必要があります。
フリーズされたら何時間何十時間が無駄になります。

なので、フリーズの原因を探るべく、最初にやったのがtrim disable。
1週間以上経ちますがフリーズしなくなりました。

Maxima日本語マニュアル更新

5.38.1に更新しました。

http://maxima.osdn.jp/maxima.html

トップページに\input texinfoと表示されていて、マクロの処理がおかしい感じです。
オリジナルでもそうなるので、申し訳ないですが放置しています^^;