趣味プログラムの補助ツールを作った。
前段
ツイッターの画像クローラ。
twitter4j使ってメディア(画像)URLを拾って来る、いわゆるクローラを作ってまして。
今は毎朝四時にそのツールを叩くようにタスクスケジューラ組んで、自分のツイート、或いはリツイートした画像ファイルを収集してまして。
正確に言うと、画像じゃなく画像URLの収集。
画像を直接落としてくるツールではなく、画像URLをひたすら拾って来るツール、と言う形で作っています。
画像URL(と、幾つかのメタデータ)を拾ってきて、それをテキストファイルに吐き出しまくるだけのもの。
で、これを別なツールで読み込んでダウンロードする、と言う形にしています。
URLログファイルが溜まっていく
TwitterのSearchAPIの一週間制限を突破する方法がどうしても解らなくて、仕方ないのでもう今後定期的にクロールして溜めていこう、という発想に至りました。
で、そうなるとですね、結構大量なテキストファイルが溜まっていくんですね。
単純にテキストファイルの数が多いってのも問題ですし、その中のデータは結構な率で重複していると言うのも問題。
ということで、以下の目的でファイルをマージしたいと言う要件が発生したわけですね。
- 単純にテキストファイルの数を減らしたい。
- ファイル内の重複データを減らしたい。
まぁ、ダウンロードツールはスキップ機能も持たせてるので、重複データが存在する事自体は別に問題ないッチャ無いんですけどね。
本題
ということで
やっと本題ですが、テキストファイルをマージして、ついでに重複排除する処理を組みました。
ツールと言うようなレベルじゃなく、単にやりたい事をダッと書いた、って程度ですね。
static void Main( string[] args ) { try { Execute( args ); } catch ( Exception ex ) { Console.WriteLine( ex.Message ); Console.WriteLine( ex.StackTrace ); } } private static void Execute( string[] args ) { string timestamp = DateTime.Now.ToString("yyyy-MMdd-HHmmss"); string path = $"archived-text-{timestamp}.txt"; var files = args .AsEnumerable() .Select( x => new FileInfo(x) ) .Where( file => file.Exists ); // 取り敢えず最低限、重複排除するだけで実装。 HashSet<string> unique = new HashSet<string>(); using ( StreamWriter writer = File.CreateText( path ) ) { foreach ( var file in files ) { var lines = File.ReadAllLines(file.FullName); foreach ( var line in lines ) { // 初出なら作ったファイルに書き込み。 if ( unique.Add( line ) ) { writer.WriteLine( line ); } } } } }
とにかくまず動かしてファイルを減らしたいと言う事で、スピードだけ最優先して突貫で作ったので、機能的にはもっと色々と拡張したり、汎用性を持たせたり、オプション機能を作ったり、 最終的にはクローラの定時処理と合わせて、自動的にアーカイブしてくれるような、そんな仕組みにしたいなぁとか思ってますが。
まぁそれはいずれやる事にしましょう。
ある程度形になったら、またGitHubにでも置いときましょう。