記事の詳細
JavaScriptで同一ドメイン内のHTMLで構成されたページの開始タグと終了タグで囲った部分を全て取得する方法
趣味が睡眠になりつつあります、網干です。
予定が何も入っていない休日に睡眠時間を16時間もとっていました。
具体的には 0-8時 10-13時 16時-19時 22時-24時 と睡眠をとっていました。
食事の前後しか起きないグータラ生活でしたが、翌日に首と肩で謎の痛みが発症しました…。
過度な睡眠は良くないですね、適度な睡眠が大事です。
さて、以前に「JavaScriptで同一ドメイン内のHTMLで構成されたページの特定のタグを全て取得する方法」という記事を書かせていただいたのですが、divやspanなどの閉じタグがあるような範囲の取得に対応していませんでした。
※前回の記事は下記になります。
なので、今回は開始タグから終了タグまでを取得するプログラムを紹介させていただきます。
今回のブログの見出しはコチラです!
JavaScriptで同一ドメイン内のページの特定タグの開始タグから終了タグまでを取得する
以前にもご紹介しましたが、このプログラムは同一ドメイン内のページにしか対応していないことに注意してください。
例えば、これから紹介するプログラムを”http://example.com”のドメインのページに設置した場合は”http://example.com/page1.html”のHTMLコードを取得することは可能です。
しかし、プログラムを”http://example.com”のドメインのページに設置して”http://www.yahoo.co.jp/”のHTMLコードを取得することはできません。
これは、今回のプログラムで使用するXMLHttpRequestの仕様で外部ドメインのコード取得が不可能になっているため、取得ができません。
では早速、下記にコードの一式を記載します。
【 html 】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>HTMLの特定タグの範囲取得プログラム</title> <script type="text/javascript" src="./test.js" charset="UTF-8"></script> </head> <body> <select id="url"> <option value=""></option> <option value="http://techmemosrv.minibird.jp/">myHP</option> </select> <input type="text" id="keyword" value=""> <select id="tagkeyword"> <option value="article">article</option> </select> <input type="button" value="取得開始" onclick="request();"> <textarea id="page_text" style="width: 100%; height: 200px;"></textarea> </body> </html> |
【 javascript(test.js) 】
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
/*********************************************************************/ /* ファイル概要:自身のドメインのページのhtmlコードを取得して */ /* 特定のタグで囲われた部分だけを抜き出すプログラム */ /*********************************************************************/ /*********************************************************************/ /* 初期設定 */ /*********************************************************************/ // 変数初期化 httpRequest = false; // XMLHttpRequestオブジェクト // IE6.0以外の「XMLHttpRequest」オブジェクトをサポートしているブラウザ? if(window.XMLHttpRequest) { // 「XMLHttpRequest」オブジェクトをサポートしている場合は下記 httpRequest = new XMLHttpRequest(); httpRequest.overrideMimeType('text/xml'); } else if(window.ActiveXObject) { // IEの場合は下記 try { httpRequest = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { httpRequest = new ActiveXObject('Microsoft.XMLHTTP'); } } /*********************************************************************/ /* 関数名:特定のタグ範囲取得関数 */ /* 概要 :範囲制限あり。特定の文字列で始まるタグの範囲のみを取得 */ /* 引数 :strHtmlSrc = HTMLソースコード */ /* :strKeyWord = 取得開始キーワード */ /* :strTagKeyWord = 取得開始キーワードのタグ */ /* 戻り値:特定のタグ範囲の文字列の配列 */ /*********************************************************************/ function getTargetStringArray( strHtmlSrc, strKeyWord, strTagKeyWord ) { // 定数宣言 const SERCH_END_VAL = -1; // 検索終了条件値(indexOfで見つからなかった場合に返る値で判定) const GET_TARGET_AREA_END = 0; // 取得範囲の終了条件値 const GET_AREA_MAXCOUNT = 4; // 取得最大数 const KEY_TAG_START_WORD = '<'; // タグ開始キーワード const KEY_TAG_END_WORD = '/'; // タグ終了キーワード // 変数宣言 var getSearchIndex = 0; // 検索中のインデックス位置 var saveStartIndex = 0; // 取得対象エリア開始位置のインデックス保存 var saveEndIndex = 0; // 取得対象エリア終了位置のインデックス保存 var cntStart = 0; // 取得対象のタグが開始した数 var cntEnd = 0; // 取得対象のタグが終了した数 var flgSearching = true; // 取得対象エリア検索中フラグ var flgGetting = false; // 取得対象エリア取得中フラグ var arrayGetTargetArea = new Array(); // 取得対象のエリア格納配列 var stringGetArea = ''; // 取得対象のエリアの文字列 var cntGetTargetArea = 0; // 取得対象の取得数 // 入力が足りない? if( ( strKeyWord == "" ) || ( strTagKeyWord == "" ) || ( strHtmlSrc == "" ) ){ return arrayGetTargetArea; } // 文字チェック while( flgSearching == true ) { // 文字列の検索 getSearchIndex = strHtmlSrc.indexOf( strKeyWord, getSearchIndex ); // 文字列が見つからなかった?or最大取得数になった? if( ( getSearchIndex == SERCH_END_VAL ) || ( cntGetTargetArea == GET_AREA_MAXCOUNT ) ) { // 取得終了 flgSearching = false; continue; } // 取得開始インデックスを保持 saveStartIndex = getSearchIndex; // 検索開始位置を移動 getSearchIndex += strKeyWord.length; // 検索タグの開始数をカウント cntStart++; // 取得中フラグON flgGetting = true; // 対象エリアの取得 while( flgGetting == true ) { // 取得開始インデックス以降で同じタグを検索 getSearchIndex = strHtmlSrc.indexOf( strTagKeyWord, getSearchIndex ); // タグが見つからなかった?(※異常処理) if( getSearchIndex == SERCH_END_VAL ) { flgGetting = false; continue; } // タグの前の文字が'<'? if( strHtmlSrc.charAt(getSearchIndex - 1) == KEY_TAG_START_WORD ) { // タグの開始数をカウント cntStart++; } else if( strHtmlSrc.charAt(getSearchIndex - 1) == KEY_TAG_END_WORD ) { // タグの終了数をカウント cntEnd++; } else { // 条件に該当しない(※異常処理) flgGetting = false; continue; } // 対象エリアの取得が完了した? if( ( cntStart - cntEnd ) == GET_TARGET_AREA_END ){ // 取得終了インデックス取得(タグ末尾の'>'のインデックス位置を取得) saveEndIndex = getSearchIndex + strTagKeyWord.length; // 取得対象エリアを取り出す(終了位置の文字を含めるため+1加算) stringGetArea = strHtmlSrc.substring( saveStartIndex, saveEndIndex + 1 ); // 取得対象エリアを保持 arrayGetTargetArea[cntGetTargetArea] = stringGetArea; cntGetTargetArea++; // 取得終了 flgGetting = false; // 検索位置を閉じタグの後に変更 getSearchIndex = saveEndIndex++; } else { // 検索位置を閉じタグの後に変更 getSearchIndex += strTagKeyWord.length; } } } // 配列を返す return arrayGetTargetArea; } /*********************************************************************/ /* 関数名:HTMLコード埋め込み関数 */ /* 概要 :指定したページのHTMLコードを取得してpage_textに書き出す */ /* 引数 :なし */ /* 戻り値:なし */ /*********************************************************************/ function request() { // url、開始キーワード、開始キーワードのタグ取得 page = document.getElementById("url").value; // url strKeyWord = document.getElementById("keyword").value; // 開始キーワード strTagKeyWord = document.getElementById("tagkeyword").value; // 開始キーワードのタグ // 入力が足りない? if( ( page == "" ) || ( strKeyWord == "" ) || ( strTagKeyWord == "" ) ){ return arrayGetTargetArea; } // リクエスト中止 httpRequest.abort(); // リクエスト初期化 httpRequest.open('GET', page, true); // テキストエリア初期化 document.getElementById('page_text').value = ""; // readyStateの値変更を監視 httpRequest.onreadystatechange = function() { // データ受信完了? if(httpRequest.readyState == 4) { // リクエスト成功? if(httpRequest.status == 200) { // HTMLソースコードを文字列で取得 var getHtmlSrc = httpRequest.responseText; // 抽出した文字列の配列を取得 var getArray = getTargetStringArray( getHtmlSrc, strKeyWord, strTagKeyWord ); // 取得した文字列を全て書き出す for (var i = 0; i < getArray.length; i++) { document.getElementById('page_text').value = document.getElementById('page_text').value + getArray[i] + "\n"; } } } } // リクエスト発行 httpRequest.send(null); } |
基本的には全てコメントに記載した通りの内容になっています。
上記のプログラムを使う場合は、optionタグで指定しているURLを自身のドメインに設置しているページのURLに変更してください。
開始キーワードを指定して指定範囲のコードを取得する
上記プログラムの使い方は…
- 取得するページを指定する(今回は自身のHPのトップページ)
- 取得を開始するキーワードを指定する(今回は”article”タグの始めから終わりまでを取得)
- キーワードのタグを指定する(今回取得するタグ”article”を選択する)
条件を指定する際に2.の条件は非常に重要で、可能な限り確実に取れるコードの開始ワードを指定してください。
例えば、私のHPのトップページのソースコードを見ると下記のような構造になっています。
今回は投稿記事のソースコードのみを取得するのですが、画像を見るとarticleタグで囲っている部分が投稿記事であることがわかります。
なので、articleのタグで取得をすれば良い と考えてしまうのは少し怖いです。
というのも、もしかしたら別の場所でもarticleタグを使用している可能性があるからです。
従って、想定しないarticleタグの範囲を取得しないように、もっと文字列を特定して‘<article id=”post-‘というワードから始まる文字列で検索を行います。
このようにキーワードは可能な限り他のタグと区別ができるように指定する必要があります。
最後に、キーワードのタグを選択して「取得開始」ボタンを押します。
すると、下記のように指定範囲のコードを抜き出してテキストボックスに表示します。
※検索開始のキーワードには‘<article id=”post-‘を入力することに注意してください
今回のプログラムの実装手順
今回のプログラムを自身のサイトで試したい場合は、下記の手順でファイルの作成/修正を行ってください。
- 新規のテキストファイルを二つ用意して【 html 】と【 javascript(test.js) 】の内容をコピペする
- 【 html 】のファイルは”test.html”の名称で保存、【 javascript(test.js) 】のファイルは”test.js”の名前で保存する
- 保存したファイルは同じフォルダに格納する
- “test.html”の”http://techmemosrv.minibird.jp/”の部分を自身のページのURLに変更する
- “test.html”の”article”の部分を取得したいタグの名称に変更する
- “test.html”をブラウザで開いてURL、開始キーワード、開始タグを設定して取得開始ボタンを押す
上記の手順で同じようなプログラムが動きます。
動作確認環境
このプログラムは下記のブラウザで正常に機能していることを確認しています。
- Google Chrome 53.0.2785.143 m (64-bit)
- Firefox 49.0.2
- Safari 5.1.7
- Microsoft Edge 38.14393.0.0
- Internet Explorer11 11.321.14393.0
最後に
いかがでしたか?
なかなか使いどころが難しいプログラムではありますが、ドメイン内に複数のサイトを持っていたりするとなかなか使えるプログラムだと思います。
どこかのタイミングで外部ドメインのソースコードを取得するプログラムも作ってみたいですね。
ではまた!
コメント
この記事へのトラックバックはありません。
この記事へのコメントはありません。