Polymer.dart の transformer のソースコード見てみたら、ふと思いついたのでメモ。
スクレイピングには html5lib を使う。これは dart:html (クライアントサイド dart)と似た API を持ち、使い慣れた感じでスクレイピングできる。
こんな感じで書ける
http://comic-walker.com/ をスクレイピングしてみる:
main() {
final url = 'http://comic-walker.com/';
getHtml(url).then((document) {
// ページタイトル
print(document.querySelector('title').text);
// 新着コミックタイトル一覧
document.querySelectorAll('#bookList > li').forEach((e) {
print(e.querySelector('.list_bookName').text);
});
});
}
実装
html5lib には HTML 取得部分までは実装されていないので getHtml
はちょっとした実装が必要。
import 'dart:io';
import 'dart:async';
import 'package:html5lib/parser.dart';
import 'package:html5lib/dom.dart';
/// [url] で指定された HTML を取得しパースする
Future<Document> getHtml(String url) =>
new HttpClient()
.getUrl(Uri.parse(url))
.then((req) => req.close())
.then((res) => res
.asyncExpand((bytes) => new Stream.fromIterable(bytes))
.toList())
.then((bytes) => parse(bytes, sourceUrl: url));
これだけ。
実際はタイムアウト、Content-Type チェック、文字エンコーディングの明示的な指定、みたいなのもあったほうが良さそう。
html5lib は Polymer.dart の tramsformer の重要な部分を担っているので、開発止まった詰んだ。。。みたいなことはしばらく起きなさそう。
クライアントサイドで動く言語は、それを基準としたスクレイピング API が扱いやすく向いていると思うし、Node, Dart は相性よいのかも。