e-learning、オラクル研修、LMS(学習管理システム)のiStudy

e-learning、オラクル研修、LMS(学習管理システム)のiStudy

第88回 「PL/SQLでWEBページを検索する!~本メルマガのバックナンバーの検索~」

2014.02.27

こんにちは。インストラクターの蓑島です。

前回は、PL/SQLを使って httpプロトコルでWEBページにアクセルする手順(ACLへの登録)ついて解説し、実際に簡単な問い合わせで、WEBページの先頭2000バイトが取得できることを確認しました。

その問い合わせで使ったのは、UTL_HTTPパッケージのREQUESTファンクションです。
このファンクションは簡単に使えますが、指定したURLの先頭2000バイトまでしか取得できないという欠点があります。

そこで今回は、PL/SQLのプログラミングで、指定したURLの先頭2000バイトではなくHTMLドキュメント全体を取得する方法について解説します。
同時にその応用例として、WEBページの検索をするプログラミングをします。

まず、HTMLドキュメント全体を取得する方法ですが、前回と同じUTL_HTTPパッケージをつかいます。しかしファンクションは前回と違って、REQUEST_PIECESというファンクションを使います。
このファンクションは指定したURLのHTMLドキュメントの2000バイトづつのピースを、コレクション(配列)にして返します。
ですから2000バイトを超えるHTMLドキュメントでも取得可能です。

では早速、きわめて簡単な例で、これを使ってみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
DECLARE
    -- 最大2000バイトの文字列のコレクションの宣言
    REC  UTL_HTTP.HTML_PIECES;
BEGIN
     -- そのコレクション変数にHTMLドキュメント全体が複数ピースで取得される
    REC := UTL_HTTP.REQUEST_PIECES( 'http://www.istudy.ne.jp/training/serial/plsql/' );
    -- 取得したコレクションのピースの数や大きさを表示する
    DBMS_OUTPUT.PUT_LINE( '取得したピースの数' || REC. COUNT );
    FOR I IN 1..REC. COUNT  LOOP
        DBMS_OUTPUT.PUT_LINE( 'ピース ' || TO_CHAR(I) || ' の大きさ' ||
                                                TO_CHAR(LENGTHB(REC(I))));
    END LOOP;
END ;
/
取得したピースの数19
ピース 1 の大きさ1999
ピース 2 の大きさ1999
ピース 3 の大きさ1999
ピース 4 の大きさ1999
ピース 5 の大きさ1999
ピース 6 の大きさ1999
ピース 7 の大きさ1999
ピース 8 の大きさ1999
ピース 9 の大きさ1999
ピース 10 の大きさ2000
ピース 11 の大きさ1999
ピース 12 の大きさ1999
ピース 13 の大きさ1999
ピース 14 の大きさ1999
ピース 15 の大きさ1999
ピース 16 の大きさ1999
ピース 17 の大きさ1999
ピース 18 の大きさ1999
ピース 19 の大きさ1811
 
PL/SQLプロシージャが正常に完了しました。

簡単に解説します。
まず、3行目でコレクションの宣言を行っていますが、型をUTL_HTTP.HTML_PIECESとして宣言しています。
このHTML_PIECES型は、UTL_HTTPパッケージの仕様部で以下のように定義されています。

TYPE html_pieces IS TABLE OF VARCHAR2(2000) INDEX BY BINARY_INTEGER;

すなわち、単純にVARCHAR2(2000)までの文字列のコレクション(PL/SQL表、索引付き表)です。自分でこの型を定義してもいいのですが、せっかくパッケージに用意された型ですからそれを使うのが簡単でしょう。

そして、6行目で、http://www.istudy.ne.jp/training/serial/plsql/ のWEBページ全体をこのコレクションに代入しています。
このURLは、前回、ACLに登録したネットワークホストに該当するので、アクセス可能なものです。

そのあと、8行目でこのコレクションのピースの数を表示し、9行目から12行目でこの各ピースの大きさを表示しました。

ご覧のように全部で19のピースがあり、各ピースの大きさがほぼ2000バイトですね。

これでUTL_HTTPパッケージのREQUEST_PIECESファンクションの基本的な使い方がわかったと思います。

次にこれを応用して、WEBページの検索を行うプログラミングをしてみます。
具体的には、本メルマガ「PL/SQLを使ってみよう」のすべてのバックナンバーのWEBページから特定の文字列を持つものを検索するプログラミングです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
DECLARE
   V_URL    VARCHAR2(300);
   REC  UTL_HTTP.HTML_PIECES;
   KEYWORD  VARCHAR2(100) := '&キーワード' ;
BEGIN
   FOR I IN 1..87  LOOP   -- 本メルマガ第1回~87回を対象にして検索
      V_URL := REPLACE (BASE_URL, 'AAA' ,TRIM(TO_CHAR(I, '000' )));   -- 回の番号をURLにセット
      REC. DELETE ;
      REC := UTL_HTTP.REQUEST_PIECES(V_URL);  -- HTMLドキュメント全体を取得
      FOR J IN 1..REC. COUNT LOOP
          IF UPPER (REC(J)) LIKE '%' || UPPER (KEYWORD) || '%' THEN  -- キーワードチェック
             DBMS_OUTPUT.PUT_LINE(V_URL);
             EXIT;
          END IF;
      END LOOP;
   END LOOP;
END ;
/
キーワードに値を入力してください: パッケージ
旧   5:   KEYWORD  VARCHAR2(100) := '&キーワード' ;
新   5:   KEYWORD  VARCHAR2(100) := 'パッケージ' ;
 
PL/SQLプロシージャが正常に完了しました。

すこしわかりにくいので解説します。
まず、2行目で、BASE_URL VARCHAR2(300) := 'http://www.istudy.ne.jp/training/serial/plsql/AAA.html'; という宣言を行ってますが、これは、本メルマガの毎回のURLがこの文字列の'AAA'の部分を001~087のように回の番号にしたものにしているために、そのもとになるURLの文字列を変数に格納したものです。

そして、7行目から17行目のループ処理で、このAAAの部分を001,002,003・・・というように各回の番号にしながらURLを取得し、そのURLのHTMLドキュメントを10行目でRECという名前のコレクション変数に格納します。
11行目から16行目のループ処理で取得した各ピースに指定したキーワードの文字列が含まれているかどうかを LIKE '%~%' の条件でチェックします。その条件に該当すれば、13行目で画面にURLを表示し、そのピースを調べるループを打ち切ります(14行目の EXIT)。

このような処理により指定したキーワードを含む、本メルマガのバックナンバーはどれであるか簡単に調べることができます。

5行目でKEYWORD変数を置換変数&を使って定義しているので、20行目で値をキーボードから入力します。
上記の例では「パッケージ」と入力しました。

その結果、「パッケージ」という文字を含む本メルマガはこれだけである、ということで、該当するURLがずらっと表示されているわけです。
このように自由にキーワードを指定してその文字を含むバックナンバーを検索できます。

この処理はマシンスペックによっては少し長時間になることもあると思いますので、必要に応じて7行目でバックナンバーの回の範囲を限定して対象範囲を狭めればよいと思います。

いかがですか? UTL_HTTPパッケージで様々なことに応用できそうですね。ぜひ、いろいろと試してみてください。

今回はここまでにします。次回もご期待ください。

先頭へ戻る