JavaScriptで別ページのHTMLテキストをデータとして取得する機能

勘違いしながらドはまりしながら作り上げていく『JavaScript奮闘記』。事始めのJavaScript常識をまとめたページや現在作ろうとしてるクイズの仕様説明はこちら。

ポク太郎です。

本ページの話題は「JavaScriptで別ページ内のHTML情報を取得する。」『JavaScript3択クイズを作ろう』中の一機能。

ソース丸ごと閲覧者のデバイスにダウンロードするJavaScriptなので、閲覧者に答えがバレないようクイズの問題と答えを別ページに準備し、それをJavaScriptで読みに行く仕様とするために。


JavaScriptで作るクイズの仕様と呼び名の定義

準備するもの
1クイズを設置するページAの他にクイズの問題と答えを書いた別ページBを用意。
別ページBは通常、ページAをリファラーとするアクセス以外をブロックする閲覧制限。
2別ページB内の情報を読み取る機能。ページAJavaScriptに設置。

以下に別ページBのHTMLとページA内のJavaScriptを作っていきます。

別ページBのHTML

ブログのタイムラインに出現しないよう“固定ページ”に作成した別ページBのURLは、

poku.blog/js-test

ドメインが異なる別のサイト上でもOK。上記は見本なので閲覧制限は付けてありません。

アクセスする場合は先頭にhttps://を付けて下さい。style=”visibility:hidden;”としてあるので中身は見えませんが。

以下がHTML内容。

<html>
<head>
<meta name="robots" content="noindex,noarchive,nofollow">
</head>

<body>

<!-- ここに貼る -->
<div style="visibility:hidden;">
<div class="qdt">9000,足し算,r,3+5=?,8○,9,10,正解は「8」です。</div>
<div class="qdt">9001,足し算,r,4+5=?,8,9○,10,正解は「9」です。</div>
<div class="qdt">9002,足し算,r,3+9=?,12○,15,10,正解は「12」です。</div>
<div class="qdt">9003,足し算,r,2+8=?,8,9,10○,正解は「10」です。</div>
<div class="qdt">9004,引き算,r,2-5=?,-3○,-5,7,正解は「-3」です。</div>
<div class="qdt">9005,引き算,r,11-4=?,7○,9,10,正解は「7」です。</div>
<div class="qdt">9006,引き算,r,9-2=?,7○,6,11,正解は「7」です。</div>
<div class="qdt">9007,引き算,r,8-5=?,3○,2,13,正解は「3」です。</div>
<div class="qdt">9008,掛け算,r,2x5=?,10○,12,7,正解は「10」です。</div>
<div class="qdt">9009,掛け算,r,11x4=?,44○,42,7,正解は「44」です。</div>
<div class="qdt">9010,掛け算,r,4x4=?,16○,20,8,正解は「16」です。</div>
<div class="qdt">9011,掛け算,r,3x4=?,12○,10,7,正解は「12」です。</div>
<div class="qdt">9012,割り算,r,10/5=?,2○,3,4,正解は「2」です。</div>
<div class="qdt">9013,割り算,r,9/3=?,3○,4,5,正解は「3」です。</div>
<div class="qdt">9014,割り算,r,3/2=?,1.5○,2,1,正解は「1.5」です。</div>
<div class="qdt">9015,割り算,r,4/2=?,2○,1,4,正解は「2」です。</div>
<div class="qdt">9016,慣用句,r,○○を漢字で埋めなさい。豚に○○。,真珠○,念仏,小判,正解は「真珠」です。</div>
<div class="qdt">9017,慣用句,r,○○を漢字で埋めなさい。人生万事塞翁が○,馬○,豚,猿,正解は「馬」です。</div>
<div class="qdt">9018,慣用句,r,○○を漢字で埋めなさい。猿吉は○でも踏んどれ。,麦○,米,肉,正解は「麦」です。</div>
<div class="qdt">9019,慣用句,r,○○を漢字で埋めなさい。パンツトラナイデネ!○○トコナイデネ!,二度○,再度,既,正解は「二度」です。</div>
</div>
</body></html>

div class=”qdt”とある20行がクイズのデータ。

データのフォーマットを、

クイズNo,カテゴリ,シャッフルフラグ,問題文,選択肢1,選択肢2,選択肢3,正解の解説文

としました。シャッフルフラグとは選択肢の順番を並び替えて出題するかどうか、また選択肢中の正解には文末に○を付けておく仕様とします。

クイズページAに実装されるJavaScriptdiv class=”qdt”を頼りにこれらHTMLテキストをデータとして読み込みます。

別ページの内容を読み取るJavaScript関数

こちらが実際にクイズページAに実装するJavaScriptJavaScriptが走った後、別ページB内のテキストを変数に納めるまでの機能です。

document.getElementById("debug").innerHTML = '';
var obj = new XMLHttpRequest();
obj.open('GET','https://poku.blog/js-test',true);//true:非同期通信
obj.onreadystatechange = function(){

	if (obj.readyState === 4 && obj.status === 200){
		var str = obj.responseText; //読み込んだHTMLを変数に代入
//----処理
		var qdt = str.match(/<div class="qdt">.+?<\/div>/g);

			document.getElementById("debug").style.display = '';
		//id="debug"タグにテキストを記述する。
		for (var i=0;i<qdt.length;i++){
			document.getElementById("debug").innerHTML += qdt[i];
		}
//----処理
	}

	};
	obj.send(null); //リクエストの送信

XMLHttpRequest()に関する説明
外部参照用の箱obj外部参照用の箱として変数objを準備し、new XMLHttpRequest()を代入。
実際に別ページBへアクセス。obj.open(‘GET’,’https://poku.blog/js-test‘,true);と、別ページBのURLを指定。
obj.onreadystatechange = function()状態変化が認められた時に走るfunction()関数内に条件指示。上記例のif文では、obj.readyStateが“転送完了”かつレスポンスコードが代入されるobj.statusが“200”であることを条件にしています。
変数strに全データobj.responseTextに読み込んだHTMLが代入されてるので変数strに代入。
正規表現で該当部位を変数qdtに代入変数strの内、別ページBの仕様としたdiv class=”qdt”を含む部分のみを変数qdtに代入。その配列全部を次のfor文で全表示しています。

判定や値を利用するXMLHttpRequest()関連パラメータ
1obj.open(‘GET’,’URL‘,true);実際に外部ページを読みに行けと命令する部分。オプションパラメータは非同期通信の指定。例では非同期を指定するtrue
2obj.onreadystatechangeXMLHttpRequest()に何らかの状態変化が起きたフラグ。
3obj.readyStateXMLHttpRequest()の接続状態を表す値が入るプロパティ。“4”は転送完了を表す。XMLHttpRequest.readyStateの結果と表す状態
4obj.statusXMLHttpRequest()接続のエラーコードが入るプロパティ。“200”…正常終了、“404”…存在せずなど。HTTP レスポンスステータスコード
5obj.responseTextXMLHttpRequest()接続先の全HTMLテキストが代入される変数。

ここから

ここまで表示領域。

別ページには閲覧制限

別ページBはクイズの問題と答え・解説が書いてあるページなので、閲覧制限をしておかないと意味がありません。

つまり、クイズのJavaScriptが設置してあるページA以外からのアクセスをブロックする必要があります。

方法はいくつかありますが、完璧なブロックを行うには.htaccessファイルを使える環境である必要があります。

閲覧制限の実現方法と条件
1.htaccessファイルでリファラー指定。通常無料ブログは.htaccessファイルを置けないので、レンタルサーバなどのみで使える方法。ただし100%ブロック可能。
2JavaScriptでリファラーをチェックし条件判定。無料ブログでも使える方法。ただし、JavaScriptオフにしてアクセスされると閲覧できてしまう。CSSで非表示にすることはできるがソースは見れてしまう状態。

その他、別ページBは検索エンジンに登録されてはいけないのでNOINDEX属性必須。やり方はHTMLの<head></head>タグ内に、

<meta name=”robots” content=”noindex,noarchive,nofollow”>

と記述。

実装例1 .htaccessによる別ページBの閲覧制限

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
SetEnvIf Referer "クイズページAのURL" ref=qpage
SetEnvIf REQUEST_URI "別ページBのURL" req=qkotae
RewriteCond %{ENV:req} qkotae
RewriteCond %{ENV:ref} !qpage
RewriteRule .* https://www.google.com/ [R=301,END]
</IfModule>

上記の意味は、REQUEST_URIが別ページBである場合、そのリファラーがクイズページAでなかったらgoogleへ転送しろ、というもの。

上記の場合、”別ページBのURL“部分は”/js-test”と書き、”クイズページAのURL“部分は設置するページのURL”/pc/code/js-quiz.html”と記述。URLのドメイン以下の部分を先頭に/付で記述。

実装例2 JavaScriptによる別ページBの閲覧制限

var ref = document.referrer;
	if( ref == 'クイズページAのURL' ){
	}
	else
	{
	window.top.location.href = "//www.google.com/";
	}

完璧なブロックはできないが、無料ブログでも使えるJavaScriptを使った方法。

document.referrerプロパティを使ってリファラーを調べ、それがクイズページAのURLでない場合、googleへ転送します。

別ページBから情報を読み取ってしまえば、後は配列変数などに格納し好きなように値として扱えます。

本ページでは別ページの内容をJavaScriptで読み取るまでを実施してみました。

コメント

タイトルとURLをコピーしました