@@この投稿は、[某秘密結社](https://github.com/ShellShoccar-jpn/)の幹部が、世を忍ぶ仮の一般人としてお送りします。APIに対応すべく、小鳥男が改造手術を受けているようです。明後日、金曜ロードSHOW!に、アイツがまた来る!今週(2016/01/15)、[金曜ロードSHOW!](https://kinro.jointv.jp/)であの[**「天空の城ラピュタ」が放送される**](http://www.ghibli.jp/10info/009891.html)ってご存知でしたか?そうです。あの、伝説のクジラを呼び覚ます禁断の呪文「バルス」をTwitter民に唱えさせる、それはそれは恐ろしい映画です。![ah_kujira.jpg](https://qiita-image-store.s3.amazonaws.com/0/9113/1d38027c-77e9-7362-7758-509da7f98133.jpeg)この呪文が唱えられる予想時刻は、**[日本時間で2015年1月15日23時21分頃](http://www.danshihack.com/2016/01/06/junp/balus-2015.html)**と言われています。シェルスクリプトで戦いを挑みたい!あの「バルス」に、無謀にもシェルスクリプトで戦いを挑もうと目下準備中であります。戦いとは何か......、**上映中にTwitter民が唱える「バルス」を含むツイートを全部集める。**というそれはそれは恐ろしい計画です。それができたら......、(AWKやsedやgrepやらで)データマイニングして、Twitter民の何か面白い習性を見つけることができるかもしれません。いうことでこの投稿では、そのために開発したシェルスクリプトを紹介します。進化を遂げたTwitterクライアント[「恐怖!小鳥男」](https://github.com/ShellShoccar-jpn/kotoriotoko)昨年のクリスマスイブ、POSIX原理主義に基づくシェルスクリプト製Twitterクライアント[「恐怖!小鳥男」](https://github.com/ShellShoccar-jpn/kotoriotoko)の[正体が明らかになりました。clone一発で超簡単、他言語のインストール不要、依存ソフトウェアは[cURL](http://curl.haxx.se/)(または[Wget](http://www.gnu.org/software/wget/))と[OpenSSL](https://www.openssl.org/)(または[LibreSSL](http://www.libressl.org/))だけ、という**導入までの敷居の低さ**、即ち、**動作可能な環境の多さ**、にあります。実はその小鳥男は、年末のコミケに向けて密かに進化していたのです。コミケに、シェルスクリプトで戦いを挑む!「コミケに戦いを挑む」とは、コミケ期間中にコミケ会場(東京ビッグサイト)とその周辺から発信されたツイートを全部かき集めるというという挑戦でした。最終的には無事成功し、手元には収集したたくさんのツイートデータが貯まりました。分析してみると面白いです。これ、![CXXAL18UkAIsm8x.png](https://qiita-image-store.s3.amazonaws.com/0/9113/6c46754c-98b7-91e1-ad01-cc448b5f0793.png)これはコミケ初日の朝10時台に発せられたツイートの座標をAWKやgrepで抜き出し、[tree-maps](http://www.tree-maps.com/)にコピペしてプロットしたものです。東ホールのツイートはまばらですが西ホールのツイートは比較的多めです。皆、企業スペースから攻めていたのではないでしょうか。認証方法によるアクセス制限違いで、このようなツイートをかき集めるためのシェルスクリプトを作ったわけですが、最初は[小鳥男のツイート検索コマンド](https://github.com/ShellShoccar-jpn/kotoriotoko/blob/master/BIN/twsrch.sh)を、Twitterの検索アクセス制限である2秒間隔(厳密には15分で450回)でぶん回せばいいと思っていました。ところが、2秒に1回の頻度でイケると思っていたのに、何度やっても15分後にアクセス頻度に引っかかってしまいました。auth”という2種類があることがわかります。ここで両者の認証方式の特徴を次にまとめます。|ユーザー認証は、投稿操作にも使えて、非公開ツイートも見られるのでこちらにさえ対応していればいいと思い込んでいたのですが、実は**高いアクセス頻度で使いたい場合は向かない**ということに、私は後から気付きました。ユーザー認証とアプリケーション認証の具体的な処理内容コミケ本番が差し迫る中、小鳥男のアプリケーション認証への対応に急いで着手しましたが、ユーザー認証(OAuth1.0a)に比べるとアプリケーション認証(OAuth2.0)は驚くほど単純でした。両認証のデータフロー図を掲載します。![TwitterAPI_flow1.png](https://qiita-image-store.s3.amazonaws.com/0/9113/c2045faf-a475-26f7-f09a-765c76731c7a.png)![TwitterAPI_flow2.png](https://qiita-image-store.s3.amazonaws.com/0/9113/cebefb26-6cd8-44d2-6fe7-02a4ba42f6ad.png)図を比較すると、アプリケーション認証は矢印線(データの流れ)と台形(処理手順)がだいぶ少ないです。1の部分は最初に一度だけやっておけばいいので、通常時は1を省略できます。して小鳥男のコマンドとして新たに作ったのが、1の部分を担う[getbtwid.sh](https://github.com/ShellShoccar-jpn/kotoriotoko/blob/master/BIN/getbtwid.sh)と、アプリケーション認証版の検索コマンド[btwsrch.sh](https://github.com/ShellShoccar-jpn/kotoriotoko/blob/master/BIN/btwsrch.sh)でした。実際に2秒間隔でぶん回してもアクセス頻度制限に引っかかることはなくなりました。10並列でぶん回す!しかしまだ完璧ではありません。Twitterサーバー、あるいはプロバイダーを含めた途中の回線が混雑していると1回の検索に2秒以上かかる恐れがあります。そこで、検索コマンドを10並列にし、各々20秒に1回の割合で2秒ずつずらしながら検索APIを叩く作戦にしました。これなら1つのコマンドの猶予は20秒まで延びます。仮に20秒以内に終わりそうになければcURLやWgetのタイムアウト機能を使って強制切断し、他のプロセスに任せます。最終ツイートIDを共有Twitterの検索APIには、ある時刻(ツイートIDで指定)以降のツイートだけ取得するための検索条件設定項目がありますので、各プロセスは自分が取得した最後のツイートIDを報告しあうことにより、極力重複なしでツイートを取得できるようになります。これはデータサイズを無駄に増やさないのみならず、検索プロセスの所要時間短縮のためにも重要です。IDの共有にはファイルで十分です。特定のファイルを直接読み書きするだけ。プロセス間通信など大げさなことは全く必要ありません。ツイートIDなどたかだか十数バイトのテキストデータですので、読み書きは実質的にアトミックに行われます。**事実上排他制御はカーネルがやってくれている**といえます。そのうえ、サイズも小さいのでオンメモリ。カーネルの機能をしゃぶり尽くすのもシェルスクリプトの醍醐味です。(取得したデータ置き場、ある程度整理したデータ)```このようなアイデアに基づいて作ったのが、小鳥男のAPPSディレクトリーに収録した[comike_search.sh](https://github.com/ShellShoccar-jpn/kotoriotoko/blob/master/APPS/comike_search.sh)コマンドです。並列化はシェルで一発comike_search.shコマンド自体は並列動作に対応しているだけで、それ自身が並列動作をしかけるようには作っていません。並列動作は次のようにしてシェルに任せれば十分だからです。&```第1引数は「検索実行間隔=20秒」、第2引数は「プロセス間の起動時間差の単位=2秒」、第3引数は「自分は何単位目で検索を実行させるか」を表しています。各々第3引数が1ずつ異なるので2秒(第2引数)の時間差で検索しにいくというわけです。ちなみに、停止させたい場合も、次のようにしてやはりシェルで一発です。kill```簡単ですね。