Rawlerフレームワーク
XAMLで自己完結するwebスクレイピングフレームワーク
伊藤貴一(@kiichi54321)
Webスクレイピングとプログラミング技術
 Webにはテキストマイニングの対象になる、大量の情報があ
る。
 Webは人々の書き込みで満ち溢れている。
 しかし、そのデータを取ってくるためには、プログラミングの習
得が必要。
 いまどきのどの言語もWebスクレイピングできるライブラリーはある。
 しかし、プログラミング内で使うため、言語の習得とライブラリーの
習得をしないといけない。
 プログラムはいろいろなことができるけど、できすぎて大変。
 通信から文字列処理、入出力関係までやらないといけないから躓く。
 いきなりの素人には敷居が高い。
 素人が、データを取りたいと思った時取れない。
 できたらすごいよなぁと、ぼんやり考えて過ごすことになる。(アカン)
Webスクレイピングのプログラマー側の事情
 Webスクレイピングは、同じことの繰り返しで楽しくない。
 結局はパラメータの調整だけなので。
 どこの部分を取ってきて・・・の繰り返しなので。
 その割には、いろいろ書かないといけない。
 変数の宣言、データの一時格納、関数の作成、ループ処理、後処理、
データの入出力関係などなど。
 対象のサイトに合わせて作るので、毎回違うものになる。
 共通部分はそのまま使いまわしたい。
 コピペプログラムサイコー
 でも、コピペはバグの発生もとでよくない。危険!
 デザインの変更で取得不能になったりする。
 そのため、外部化できれるとうれしい。
 後に保守しやすいように、見通しの良いものがいい。
データフロープログラミング
 データの流れを記述することでプログラミングをする手法
 データ中心にプログラミング
 関数の合成によってプログラミング
 UNIXのパイプもその一種。
 メソッドチェーンもある意味そう。ちょくちょく使われてはいる。
 関数型言語の一種。
 LISP,Haskellなどの系統。C,Javaなど多くは手続き型。
 記述が美しい、と言われながら、マイナーだったが、大規模並列処理関
係で注目を集め始めている。
 ビジュアルプログラミングとの相性がいい。
 データの流れを機能間の有向グラフで表現すればいいから
 テキストを中心としたデータフロープログラミング言語を作れば、
webスクレイピングを簡単にできる!
 関数の記述とパラメータの設定だけでいいから、使いまわしやりやすい。
 ドメイン特定型言語(DSL)
Rawlerフレームワーク
 オープンソースで公開
 https://github.com/kiichi54321/Rawler
 C#で作成
 XAMLで記述するフレームワーク。
 XMLのMS拡張。オブジェクトがXMLのタグになる。
 手順の木構造を作るだけのプログラミング。
 木構造なので、一つのテキストに対して複数の処理ができる。
 子は親のテキストを使用してテキストを生成することの連鎖。
 再利用性を高める
 変数、ループ記述を追い出している。関数型言語っぽいつくり。
 これだけで自己完結することを目指す。
 XAMLの記述だけでwebスクレイピングが完結する。
 通信、テキスト処理、繰り返し処理、データの構造化、ファイルの入出力、エ
ラー処理ができる。
 プログラミング(C#)との連携もできる。
 コードビハインドが使え、イベント処理の追加ができる。
 DBとの連携はこれを使うことで可能。
XAML
(Extensible Application Markup Language)
 XAMLとは、MSの開発した、多数のオブジェクトの状態と関係をテキスト
で記述するためのXMLみたいなもの。
 主に、UIのデザインで使われる。(WPF, Silverlightなど)
 複数のオブジェクトの記述をコピペできるのが強み。
 親子関係の入れ替えとか、コードとして書くとすごく面倒。それがコピペで済むなんて!
 C#4.0からSystem.XAML空間が追加され、UIだけのものでもなくなった。
(はず)
 そんなに使われていない?オブジェクトの状態保存には便利。
 開発動機的にはこれが大きい。
 Webスクレイピングは動作の組み合わせなので、XAMLとの相性はいい。
 Visual Studioは優秀なXAML編集ソフトである。インテリセンスも使える。
 そのため、 このフレームワークには、Visual Studioが必要。優秀なXAML編集
コントロールがあれば、不要になるのだけど…
 また、 Visual Studioでは、単純なXAMLだけではなく、コードビハインドとして
コードも書けるので拡張性がよすぎる。
 コピペ以上の優秀なUIを用意することが難しいので、XAMLの記述で満
足しちゃった。
XAMLの具体例
木構造XAML
上の等価なコード
•XAMLの記述は木構造を作る。
•XAMLはタグがクラス名なので、コー
ド的には、クラスをNewして、インスタ
ンスを作り、それから木構造を作ること
と同じことである。
•子要素がChildrenの要素になる
ことは別のところで指定してある。
•XAMLは木構造とインスタンスのパラ
メータを見やすくしている。
•木構造の入れ替え、追加は、コピペで
すむ。実際のコードでは書き変え箇所
が多くて面倒な作業である。
XAMLはオブジェクトと
対応している。
Rawlerはほんとに関数型言語?
 おそらくは、関数型言語っぽいにとどまる。
 理由
 メソッドチェーン的な世界は表現できているので、関数型言語っぽ
いとはいえる。
 とはいえ、副作用がなんだかんだいろいろある。
 関数自体に状態を持つものがある。(DataやPageなど)
 Tree構造の、親子関係、祖先関係を利用しているので、どこで切り
取っても同じ挙動ができるとは限らない。
 Dataを格納するために、子孫のDataWriteからDataの呼び出し。
 再帰的にページ取得を行うためのNextPage(祖先のPageにURLを投
げる)
 Tree構造の親子、祖先関係を利用するのは、手続き言語的発想w
 記述の簡単さ故に作ったGlobalVar。
 Tree構造無しで、一時変数や、固定変数などを扱えて便利。
 でも実装は静的変数の読み書きなので、staticおじさんである。(並列化
危険)
導入方法
RawlerTreeの作成と実行環境
 XAMLのコードの作成は、 VisualStudioを使うのが望ま
しい。
 DLLを読み込み、その情報から入力補助をしてくれるので。
 XAMLは型制約が強いので、入力補助が効果的で、それと比
べるとただのエディタでは作りにくい。
 実行環境は、RawlerToolを使う。(下の図)
 http://goo.gl/Mm58cY
 コードをコピペして使用。
 実行、キャンセル、一時停止
 Dataクラスの中身表示
 下のテキストボックスに
レポート・エラーを表示
RawlerTool の画面
導入方法1
 VisualStudioをインストール
 MSのアカウントを作る。スカイプIDと一緒。
 Visual Studio Online Basic(無償)から、 Visual Studio
Express for Desktopを選択、ダウンロード&インストール
 WPFアプリケーションを作成
 VisualStudio起動後、メニューの「ファイル」→「新規作成」→
「プロジェクト」から、WPFアプリケーションを選択し、名前とか
適当につけ、作成する。
 NugetからRawlerを導入。
 ソリューションエクスプローラーから、プロジェクトを選択後、右
クリック。Nugetパッケージ管理を選択。
 オンラインを選択し、検索窓から、「rawler」と打ち込む。
 そして、「Rawler」を選択し、インストール。
導入方法2
 RawlerTree1.xamlを選択
 選択すると右のようなものになる。
 デザインビューは不要なので、ド
ラッグでXAML部分のみを表示す
るようにする。
 水色のところをからプログラムを
記述していく。
ここを中心に編集していく
具体的なRawlerTree
具体的なRawlerTree
 パターン
基本的に上から順番
に進む
複数の出力があるも
のは、複数回実行さ
れる。
具体的なRawlerTree
 ブログ記事のコメントを取ってくる例
 コメント内容、書いた人のペアの情報のすべてがDataに蓄積
される。
PageでHTMLの取得、
Tagsで範囲の指定。
Comments-bpdyは複数ある
ので複数取得
Comments-bpdy内から、コメ
ント内容の取得。
DataWriteでDataに書き込み。
同様に、名前のところを取得
し、書き込み。
一つの組が終わる時、
NextDataRowで次の塊に移
行。
NextPageで次のページに移
動し、Pageが繰り返し。
具体的なRawlerTree
 TSVファイルからの読み込みとファイルへの書き込み機
能の追加。
前と同じ
ファイル名、ブログ記事URL
という列名をもつTsvファイル
を作り、実行すると、ダイアロ
グが開き、そのファイルを指
定すると、その内容に沿って
実行が行われる。
Pageで囲まれるところは前の
スライドのものと同じである。
コピペした。
このような形で機能拡張が行
える。
具体的なRawlerTree
 Pageは親がURLならそのページを読み込む。
 そのため、ページをたどっていくこともこんな感じで書ける。
 一覧ページ、詳細ページの構成のサイトではこれが威力
を発揮する。
具体的なRawlerTree
 ログイン必要なPixivにログインして取得
ヒント:ブラウザゲームは、POSTを多用しています
Rawlerの基本設計
超プログラマより
基底クラス(RawlerBase)の設計
 XAMLで書けるようにするために一番根っこのクラス、
RawlerBaseクラスを設計した。
 すべてはこれを継承している。
 オブジェクト指向言語のポリモーフィズム(多態性)
 木構造を表現するためにRawlerBase自身一つの親、多数の子を
もつ(Parent,Children)
 XAMLは木構造。
 木構造にそって、親のTextを
参照して、自身のTextを作る
 Run()から深さ優先で実行
 前処理のPreTree
 木構造が深くなると可読性が
落ちるので親テキストの前処理を
RawlerBaseで記述する。
 Run()とTextを継承時、 override 。
•RawlerBase
•プロパティ
•Parent( RawlerBase )
•Childern
( RawlerBase )
•Text(String)
•PreTree
( RawlerBase )
•メソッド
•Run
繰り返し処理のRawlerMultiBase
 例えばLinkの取得のように一つのテキストから複数の結
果を得られるものがある。これを扱えるようにしたい。
 そのため、RawlerBaseを継承したRawlerMultiBaseを
作り複数処理の時はこれを継承する。
 命名規則としては単複を意識させるため、複数形にして
ある。 (Links、Tags、ReadLines)
 クエリー機能(RawlerQuery)
 集合に対しての処理をしたい。
 重複削除、フィルタ処理、
n番目の取得などができる。
 C#のLINQ相当
 複数の組み合わせができる。
重複削除(Distinct)して
ソート(Orderby)して
初めから20個取る(Take)
複数の変数の指定
 RawlerTreeの設計上、親の一つ
のテキストしか入力に持てない。
 これはこれで不便だ。複数の入力
をしたい。
 XAMLのプロパティの中まで
XAMLで記述できる機能を使う。
 ルールは、対象のオブジェクトを
親としたRawlerTree
 そのため、祖先をさかのぼって扱
える。
 命名規則としては、Treeと名前の
つくフィールドは、RawlerTreeで、
XAMLで記述できます。
 通常のフィールドよりも、Treeが
存在したらそちらを優先します。
HTMLのTableタグのTHタグを動
的な変数として、DataWriteを使う
例。
DataWrite.AttributeTreeで変数を
指定する。
対象HTML
よく使う機能紹介
目次
 ページ取得
 HTML解析
 データ蓄積
 テキスト処理
 ファイル入出力
 繰り返し処理
 条件分岐
 ユーティリティ
 簡易自然言語処理
 拡張
 YahooAPIを使ってキーフ
レーズ分析
ページ取得
 Page
 親テキストをURLとして、そのURLにアクセスし、HTMLを自身のTextにもつ
 POSTもできるようになって無敵。
 InputParameterTreeからAddInput系コマンドを配置。
 一応、祖先のPageのURLをReferenceに加えるとかの処理もしている。
 GetPageHtml (祖先のPageのHTMLを取得)
 GetPageUrl (祖先のPageのURLを取得)
 WebClient
 Pageなどで、URLを読み込むとき使う。
 WebClientを宣言しなくても動きます
 クッキーなどを保持する。そのため、ログインするページには必須。
 UserAgentの指定などができる。
 NextPage
 親テキストのURLとして、祖先のPageに次に読むページを加え、Page以下の
Treeを再実行される。
 作った人の良心として、デフォで3秒ほど停止します。(変更可)
HTML解析
 Tags
 指定したTagで囲まれたものを複数取得する。
 ClassNameでクラスの指定、IdNameでIdの指定ができる。(完全マッチ)
 ParameterFilter,ContextFilterで大雑把な絞り込みができる。(部分マッチ)
 TagVisbleTypeで、子に渡すテキストをタグ全体、タグ内部、タグだけを指定で
きる。
 Links
 リンクを複数取得する。
 各種フィルタがある。
 UrlFilter(URL) TagFilter(タグ) LabelFilter(中身) これらは部分マッチ
 VisbleTypeで、子に渡すテキストを、URL,中身,全体かを指定できる。
 XPath
 xPathを使う。これも該当するのを複数取ってくる。
 ClipText
 StartとEndで挟んだ文字列を取ってくる。最終手段。
 XAMLの性質上、特殊文字の扱いが面倒なので使いづらい。
データ蓄積
 Data
 データを蓄積する所。内部的に一つのデータの塊を表す、DataRowを持ってい
る。
 ファイル名を指定すると、完了時Saveが行われる。(蓄積型)
 複数の配置をすると複数テーブルに対応する。
 DataWrite
 親のテキストを祖先のDataに属性付きで追加する。上書きではなく追加なので、
一つの属性に付き、複数のデータが入る。
 AttributeTreeを使うと、動的な属性名をつけられる。表の一括取得に使う。
 NextDataRow
 これの実行時、次の塊に移る。これが発動時のイベントも拾えてそれを使うと
DBとの連携ができる。
 FileSave (名前変更あるかも・・・)
 Dataを継承したクラス。結果をファイルに書き込む。(逐次型)
 大量のデータの取得にはDataよりこちらを使う。
 ファイルの指定がない時、ダイアログがひらく。
テキスト処理
 ApendText
 親テキストの前と後ろに文字列の追加。
 Replace (置換処理)
 TagClear(タグをすべて消す。)
 Trim(前後の空白削除)
 StringFormat
 複数のテキストをテンプレートの中に落としこむ。超便利。
 ReadLines
 テキストを改行で分ける。
 Split
 テキストを指定の区切りで分ける。
 RemoveWordByRegular
 正規表現に基づいて文字列の取り除き
ファイル入出力
 FileReadLines(ファイルから一行づつ読む)
 ファイルの指定がない時、ダイアログが開く
 TsvReadLines(Tsvファイルを読む)
 子孫に GetTsvValue があると、その指定した列名の文字列
を取得する。(便利)
 対象のTSVファイルは、UTF8エンコード。
 ContainTextInFile(指定したファイルの中に親の文字列
が含まれているか?改行区切り)
 すでに取得したデータのチェック用に。
 これを使うと、続きから実行可能になる。
 ContainTextInFileAddTextで、親のテキストを祖先の
ContainTextInFileが指定したファイルに追加する。
繰り返し処理
 Iterator (繰り返し処理)
 Textsに繰り返す内容の直書き
 SourceTreeで柔軟な繰り返す内容を記述できる。
 Range (数字の連続を作り出す。扱いは文字列)
 URLのパラメータの生成や、繰り返し回数の指定に使う。
 Loop(子のツリーを無限に繰り返す)
 Bot用かなぁ・・・
 ランダムにSleepしてくれるという無駄機能付き。
 Break?なんですか?ソフトを落とせばいいんじゃないですか
ねぇ・・。
条件分岐
 Contains
 指定したのが含まれている)
 Equal
 指定したのと同じ
 ChangeText
 以前のテキストと違う
 Switch
 複数の条件分岐を行う。
 これにより、構造化プログラミングの順列、繰り
返し、分岐のすべてを満たすことになる。
 順列
 ツリー構造での実行
 繰り返し
 RawlerMultiBaseを継承したクラス群
 分岐
 条件分岐機能群。
Switch構文例
画像のダウンロード
 ImageLinksとDownloadを組み合わせる。らくちん。
 ImageLinks
 Imgタグの取得。子には、URLを返す。
 Download
 親をURLとしてダウンロードして、ローカルに保存。
 フォルダの変更やファイル名の変更などいろいろやれる。
 拡張子の変更は行いません。(つまり気にしなくていい)
ユーティリティ
 Sleep(一時停止)
 過アクセスはやめましょう\(^o^)/
 Report
 親のTextを出力する。デバック、動作監視用。
 SetWorkFolder
 作業フォルダの指定。指定したところにファイルが作られます。
 必ず指定しましょう。フルパスもできます。
 KeyValueStore
 変数を格納する場所。SetKeyValueで格納。GetKeyValueで呼び
出す。
 SetGlobalVar、GetGlobalVar
 KeyValueStoreなしで呼び出せるもの。Static変数なので、わりと危
険だが、楽ちんに変数を扱える。
簡易自然言語処理
 テキストを変数としてテキストを返すのがRawlerなので、自然言語処理も
やれる。
 名前空間はNPL
 NPL:PreprocessingForJapanese
 前処理。半角、全角を揃えるなどの文字種の統一をやってくれる。
 NPL:TinySegmenter
 辞書を使わないフリーの軽量形態素解析器。
 Mecabの工藤さん作(元はJS)
 NPL:GetWordsInSouce
 ソースに指定した単語のみを返す。
 抽出したいものが予めあるときに
 顔文字の抽出などに。
「適当なテキスト」を前処理をして
形態素解析し、標準出力する例
拡張:YahooAPIのキーフレーズ分析を使う
 YahooAPIの使用登録をする。
 http://developer.yahoo.co.jp/
 Gitから、Rawlerのソースコードを落とす。
 RawlerYahooAPIをプロジェクトに追加。コンパイルする。
 下の感じでTreeを組み立てる。
 KeyPhreseはJsonを複数返します。
追加
書き換える
そのうちNuget化します
Rawlerの拡張性
 C#のプロジェクト内で使うとコードビハインドが使えて、イベン
ト処理の追加が行える。
 DBとの連携処理がこれで行える。
 クロール部分とDB処理がわかれるので可読性がいい。
 RawlerBaseを継承すればこのフレームワークに乗っかる。
 テキストを引数で、テキスト(単複)を返す関数であればいい。
 WebAPIを使うもの作ると便利かも
 Twitter、Facebook、googleなど
 他の処理と組み合わせが可能となり、利便性が増す。
 複数の検索語で検索したのをファイルに書き込むとか
 テキスト分析と組み合わせる
 形態素解析(実装済み)、テキスト分類、プラス表現マイナス表現・・
 分析処理の可視化、データの前処理ツールになるかも。
 このような拡張性があるためオープンソースで公開している。
Rawlerまとめ
 XAMLで記述するwebスクレイピングフレームワーク作った。
 変数、ループを排除して、やりたいことを中心とした見通しのいい記述
 これだけで自己完結できる仕組みになっている。
 VisualStudioからNugetを使うと簡単に導入できる。
 すでに多数のサイトでデータ取得経験あり。
 さくさくっと手早く作れます。30分程度。
 対象のHTMLの分析のみに集中できる。
 機能拡張も基底クラスを継承したものをつくればいいだけ
 そのため、オープンソースにしている。
 課題・問題点
 ドキュメントが不足。ソースコードがドキュメント・・
 人に作り方を教えるより、自分がやった方が圧倒的に速い。
 ドメイン特定型言語のため、本当に教えていいものかとも思う。
 XMLって結局冗長じゃね?
 今のところWindows専用。
 Mono(cross-platform用C#)でもたぶん動きそうだけど。やったことない。
FAQ
 過去の記事を見つけてそれをコピペしたのですが、動きませ
ん
 名前を弄っています。そのため同じ機能でも動きません。
 ドメイン特定言語に期待すんな。
 ソースコードが一番のドキュメントだ(あかん)
 このサイトでの取得の仕方がわかりません。
 頭の体操でなんとかなるよ。(たぶん)
 俺に聞け。(@kiichi54321)
 挙動がよくわかりません。
 ReportかViewTextを使い、表示させよう。
 タグの入れ子関係が多くなると読みにくい
 そうだね。PreTreeを使うとちょっとはましになる。
 XAMLエディタの折りたたみ機能を使うとよい。
FAQ
 クロールしていたら垢バンくらいました。
 しりません。
 遅いんじゃないですか?
 対象のサーバが遅い場合もあるし、早過ぎると相手のサーバ
から切られることがあるかものよ。
 一応、NextPageに、Sleep時間がデフォで入っているから、そ
れを小さくすれば、早くはなるよ。
 Mac版はないのですか?
 Monoで動くらしいよ?(未確認)
今後の予定
 簡単な自然言語処理関係の命令の追加
 TFIDFくらい何とかならんかな。
 TwitterAPIを使う命令群のNuget化
 今まで使っていたライブラリが更新停止のようなので、使用ライブラ
リを変更する予定。
 データバインディング
 できたら記述力が上がるけどどう実装したらいいかわからない。
 並列実行
 ぶっちゃけ複数クライアントを立ち上げればできるけどねぇ・・・。
 もうちょっと、露出を増やしていきたい・・
 いや、前書いたドキュメントが2年前でさ・・・・。

Webスクレイピング用の言語っぽいものを作ったよ