Level 4 テスト・データベースの構築

テスト用のデータベースを構築する。最低でも1万件以上、大きさにして、10MB以上1GB以下の大きさのテスト・データベースを生成する必要がある。 これらを手で入力することは不可能である。プログラムを作成し、乱数、または、WWW上のデータなどを利用しながら、テスト・データベースを作成する。 ヒント: 最初からデータベースにするのではなく、一度、テキスト(CSVなどか?)としてテストデータを生成する方が良い。そして、そのテキストを読み込んで、データベースに insert するプログラムを作成する。

ヤマダ電機の通信販売ページから、データを抽出する事にした。入力データは、ヤマダ電機の商品ID、商品名、会社名、型番(CDはJAMコード)、値段、ポイント、定価を抽出し、全てのデータが揃っている商品のみ、データベースに登録する。
データの抽出は、AVデジカメ館、家電健康館、パソコン館、文具オフィス館、CDDVD館から抽出する。それ以外のカテゴリは、条件に合ったデータを得る期待値が低いため、除外した。CDDVD館においても、DVDに関しては、期待値が低かったので同じく除外した。

データの抽出においては、文字列の扱いに優れているjavaを用いて行った。
おおまかな流れとしては、あらかじめ作成したindexファイルを参照し、それぞれのカテゴリへwgetで読み込み、それを解析し、商品リストをwgetで読み込み、解析する。無効なデータの抽出も多く予想されるので、目標取得件数を120%の12万件と定めた。
実際に取得したデータは138,540件で、うち有効なデータ107,049件の入力を試みた。しかし、商品名が長すぎるといった、我々の定義したテーブルに格納不可能なデータも含まれているので、実際はこれより少なくなる事が予想される。

データの取得ルーチン

目標とするデータを取得するために、いくつかのステップに分けて説明する。使用したプログラムは、web_get.javaFunction.javayamada_data.javaである。
ステップ1
4-1 まず、YAMADA電機のインデックスページから、使用するカテゴリのみをファイルに書き込む。これについては手動で作成した。青い枠で囲った部分がカテゴリ名である。
ファイルには以下のようにして書き込んだ。
AV・デジカメ館
http://www.yamada-denkiweb.com/contents.php/category/10/
家電・健康館
http://www.yamada-denkiweb.com/contents.php/category/11/
パソコン館
http://www.yamada-denkiweb.com/contents.php/category/12/
ステップ2
4_2 次に、先に作成したファイルを参照しながらリンクをたどる。左の画像は、AV・デジカメ館のリンクをたどったら現れる。
ここで重要なのは、2度手間をかけないように、青の四角でかこった部分を除外する事である。この部分は、赤で囲った部分のデータを並び替えただけなので、不要である。
まず、htmlファイル中に、<!-- カテゴリーリスト Start -->といったフレーズが出ると、解析を開始する。プログラム中では、web_get.filter1(String root,String uri,String to);で行っている。rootはダウンロードしたページのURLで、uriは、ダウンロードしたファイルの保存先、toは書き出し先を指している。
写真の青い部分は、この場合、『機種からデジカメを選ぶ』といった文字が出てきたら、次のカテゴリまでスキップする。このような文字は、<td colspan="4" valign="top" class="t12l">タグで始まるので、これを用いて判別している。基本的に、uriはtempファイルとして保存し、toは、作業ディレクトリ/カテゴリ名.list、として保存される。
データの保存形式を以下に記す。
##roothttp://www.yamada-denkiweb.com/contents.php/category/10/
##category:デジタルカメラ
500万画素デジカメ
/item/list.php/category/10/315/16/
600万画素デジカメ
/item/list.php/category/10/315/17/
700万画素デジカメ
/item/list.php/category/10/315/18/
800万画素デジカメ
/item/list.php/category/10/315/19/
##category:衛星放送機器・アンテナ
BSアンテナ
/item/list.php/category/10/81/10/
BSチューナー
/item/list.php/category/10/81/11/
BSデジタルチュー
/item/list.php/category/10/81/12/
ステップ3
4_3
4_4
4_5
作業ディレクトリ/カテゴリ名.listを参照し、さらに下ると、左の画面に出る。左の画面は、AVデジカメ館の500万画素の商品リスト家電健康館の冷蔵庫の商品リストCDDVD館のソウル/RandBの商品リストのページである。商品リストのページには、この3パターンが存在する。
この3種類のページそれぞれに対して、自動で判別する機能は装備していない。なので、手動での切り替えでプログラムを実行した。 web_get.filter2(String base,String category,String from,String to,boolean bool);を再帰的に実行してリンクを辿っていった。 baseはベースアドレスで、ホームページのURLが書かれている。categoryにはカテゴリ名、fromはファイル読み込み先、toは書き出し先、boolはリンクを辿るかどうかである。一般的に、toは作業ディレクトリ/カテゴリ名/サブカテゴリ名xx.list として保存される。
このページでは、<!-- 商品情報 START -->がキーワードとなっていて、ページ中にこれを発見した場合、web_get.filter2_analysis(BufferedReader br,String category,String write,my_file_writer file_write));でパターン1を、filter2_analysisaでパターン2、filter2_analysisaaでパターン3を解析している。
データの保存形式例を以下に記す。
##category:デジタルカメラ
会社名 :キャノン
商品名 :Canon500万画素デジタルカメラIXYDIGITAL60
型番  :IXYDIGITAL60
商品番号:3150692019
特価  :38,800円
ポイント:9,700
定価  :オープンプライス
会社名 :カシオ
商品名 :CASIOEXILIMZOOM500万画素EX-Z500シルバー
型番  :EXZ500S
商品番号:3150676019
特価  :35,200円
ポイント:7,744
定価  :オープンプライス
##category:キャンプ・スキー用品
会社名 :
商品名 :スキー
型番  :RDメンズタートル
商品番号:9972426016
特価  :990円
ポイント:99
定価  :オープンプライス

取得したデータをlist_analysis.javaを用いて、sqlへ入力用に変換し、入力した。上のデータをINSERT INTO item_deji VALUES(1351078014,'MS-PD','SONY',19800,2376,'オープンプライス','MSXM2GS');といった形に変換した。

在庫テーブルのデータを追加する。在庫テーブルのITEM_IDは上で追加したデー タに対応していなければならないため、商品テーブルからITEM_IDを読み込む必 要がある。在庫の数はとりあえず全て100個にした。下記にデータを追加するphp プログラムを示す。

ソース : zaiko.php
<?php
define('USER','SYSTEM');
define('PASS','XXXXX');
define('DB','');

//Oracleデータベースに接続
$con=oci_connect(USER,PASS,DB);

/*SQL文を生成 TABLE_NAMEは商品テーブル名を変更して実行する。※デバッグのため*/
$sql="select ITEM_ID from TABLE_NAME";
/*SQLの実行*/
$stmt=oci_parse($con,$sql);
oci_execute($stmt,OCI_DEFAULT);

/*指定した商品テーブルのITEM_IDを受け取る*/
$i=0;
while(oci_fetch($stmt)){
    $data[$i++]=oci_result($stmt,"ITEM_ID");
}
/*在庫テーブルにデータを追加する*/
for($i=0;$i<count($data);$i++){
    $sql="insert into stock values(".$data[$i].",100)";
    $stmt2=oci_parse($con,$sql);
    if(!oci_execute($stmt2,OCI_DEFAULT)){
    oci_rollback($con);
    }else{
    oci_commit($con);
    }
}
//Oracleデータベースと切断する。
oci_close($con);
? >

データを追加した後下記のSQL文を実行してデータがちゃんと格納されているか 確認する。

SQL> select count(ITEM_ID) from stock;

COUNT(ITEM_ID)
--------------
        104964
SQL>

上記のようにちゃんと追加されていることが確認できた。 データは全部で10万4千件以上追加されていて1レコード約220byteなので 実験条件の"最低でも1万件以上、 大きさにして、10MB以上1GB以下の大きさのテスト・データベースを生成する必 要がある。"をクリアしている。


level3 index Level5