Webスクレイピングとは
Web上にある情報を取得して何かしらの形にまとめるスクリプト類です。
PHPなどサーバーサイドで定期実行してDBに格納するなどが
よくある使われ方だと思われます。
Webスクレイピングをする上でのマナー
アクセス後の処理は$.ajaxで非同期ですが
低頻度となるよう、間隔を1秒間空くように実装します。
事例
美登利寿司という寿司店は行列が凄いが、Web上で待ち時間が見れるため
それをスクレイピングで観測して、なるべく並ばない時間帯に行きましょうという話。
渋谷のマークシティーにあるアレですね。
スクレイピングバンザイ!
jQueryで
Webブラウザ上でロードしたところで、×ボタンをおしたら消えてしまうわけですが。
それでもちょっと集計したい、なんてこともあると思います。
概要説明というか方針というか
- スクレイピング対象のWebページは一覧ページがあり、そこから個別ページ(子ページ)へのリンクがある
- まず一覧が書いてあるページを取得
- 一覧ページより個別ページのurlを抽出し、個別ページの情報を収集
シンプルですね。
表示については、空の<table>
タグに取得結果を追記していく方式で
まずは取得した一覧情報から
<tr><td id="row3">個別ページurl</td></tr>
を追加し、その後
<tr><td id="row3">個別ページurl</td><td>個別の情報</td></tr>
となるよう<td></td>
列を追加します。
実装 (wait用のfunction)
まずは遅延アクセス用のwait()
functionを用意します。
jQueryへのwait
functionの拡張を行っています。
setTimeoutで指定時間後にresolveされるような仕組みになっているため
呼び出す側は
$.wait( 【遅延時間】 ).done(function() { // 非同期で遅延実行したい処理をここに書く. });
と呼び出すことができるようになります。
実装 (取得処理)
次にメインとなる、一覧ページ取得からの個別ページ取得です。
ボタンクリック時、まず$.ajax()
で一覧を取得しにいきます。
取得後のdone
では
- 取得した一覧より、各個別ページへのurl取得
- 個別ページへidを採番します
(個別ページのアクセスも非同期で行われているため、一意なidの採番が必要) - 列を追加して
- 行*1000[msec]後に取得処理のgetDetailが実行されるようセットします
getDetail(detailUrl, rowid)
は指定された個別ページurlをロードし
取得した情報をrowid
行へ追加します。
動かしてみた
非同期で取得され、一覧取得後のアクセスが1秒置きに行われており
結果の取得順が違っても追加される行が正しいことが確認できます。
後記
ソース全文を見た方は大きなコメントアウトブロックを見て判ると思うのですが
個別ページのgetDetail
がもう少し洗練できそうです。
具体的には、getDetailがwaitを共通処理として持つような形が良いかと考えています。
というのも、現在は遅延させる単位が1000msec*取得したい行番号
となっており
この処理の中でその他に同じような処理があった場合や
特に、このボタンを2度押した時などは1秒ごとに二重に取得処理が走ることになり
それこそDDoSと変わらないなと。
つまり遅延実行処理そのものをスタックして1秒づつ処理していくような形がベストかなと。
そうなるとコールバック地獄にならないよう一工夫するか
結局グローバル変数になるのか。。
ちょっと正解は出ていないのですが、一旦この状態が正常かつある程度動くので
現在の状態を一つの解として掲載するに至りました。
相談にのってくれて、また、サンプルコードまで提供してくれたスーパー後輩に感謝ですm( )m