ツイートに含まれるURLを高速に抽出するライブラリ、つくりました
2016/03/13 お知らせ: このライブラリの内容を含めて twitter-text 完全互換のライブラリを作りました。こっちがメインになります。
お知らせ終わり。
URI教の皆さんへ: Twitter が URL って言ってるからこっちに統一しました。許して。
はい、タイトルの通りです。言いたいことは以上です。
twitter-text 問題
神(Twitter)は言われた。「ライブラリあれ。」こうして、 twitter-text があった。神は twitter-text を見て、良しとされた。
「よくねーよ C# 版出してくれよ!」
こんな声にお答えしたライブラリは数あれど(メンテナンスされてるとは言ってない)、そもそも twitter-text の Extractor(URLとかハッシュタグとか抽出してくるやつ)は正規表現頼りで、連続して動かすと非常に遅いわけです。
そもそも、 Twitter クライアント作者(僕は違う、よね)が twitter-text を求めるのは、あのクソみたいな t.co とかいうやつを考慮してツイートの文字数を計算し、 140 文字をオーバーしていないかをチェックするためですよね。つまりこのクソ長い正規表現を 1 文字入力するたびに走らせなければなりません。おえー
正規表現は文字列を順番に読み進み、一致しなければ少し戻り、をマッチする/しないが確定するまで繰り返します。単純な文字列ならいいんですけどね、 t.co の判定基準とかだるすぎるし、人間にとってだるいんだから、コンピュータにとってはつらすぎますよね。知らんけど。
そこで、つくりました
Azyobuzi.TwitterUrlExtractor(かっこいい名前が思いつかなかった)は、最も効率的な方法(だと僕が思っている方法)で URL を抽出します。これでツイート内容のテキストボックスに「ああああああああああああ(x1000くらい)」と無駄に入力しても重くならないようになりますね!
仕組みは簡単(ではない)。
- 「.」を探す (http://twitter.(←)com/azyobuzin)
- 逆戻りしてドメインとして有効な部分と「http://」があるかないかを探す ((→)http://twitter.com/azyobuzin)
- 「.」の後ろもドメインとして有効な部分を探す (http://twitter.com(←)/azyobuzin)
- 有効な TLD かどうかチェック
- ポート・パス・クエリを読み取る
- 完了!
と書くのは簡単だけど、イレギュラーな判定基準が多すぎて死にそうになりましたが、見事 twitter-text に入ってる extract.yml のテストを全部通過させることができました!
まとめ
(たぶん)twitter-text 互換の URL 検出を結構高速(twitter-text-csの17倍, Releaseビルドだともっとやばい)に行うことができます。強い!
追記
twitter-text の正規表現に RegexOptions.Compiled をつけてやったら逆に低速化したんだけど
— 櫻井桃華 (@azyobuzin) February 23, 2016
なんでや!なんでコンパイルしたほうが正規表現遅くなってるんやおかしいやろwww
— 櫻井桃華 (@azyobuzin) February 23, 2016