ゼロからはじめるプログラミング講座の第四十七回です。今回は解説に戻ってAjaxというものを使います。Ajaxを使いリンク先のページから画像のファイルパスを取ってくるというプログラムを作ってみましょう。
Ajaxを知ろう。
Ajaxとは
サーバーと通信を行いブラウザとサーバーでデータをやり取りするプログラムのこと。
今まではブラウザに読み込んだデータのみをコードで操作していました。Ajaxを使うことでリンク先(サーバー)のデータも取り込んでコードで操作することができます。
サーバーと通信をするということは、通信先のサーバーに負荷をかけるということを覚えておいてください。故意に負荷をかけると違法行為になることもあるのでやめましょう。
これから紹介するAjaxでは”GET”データ(htmlコード)を取ってくるだけなので、自分でリンクをクリックしたり更新(F5)をする行為と変わりがありません。
今まで紹介した中でlocation.reload()なども使い方次第ではサーバーに負荷をかける攻撃のようなことも出来てしまいます。
故意でなくとも違法になるような行為はしたくない!
大丈夫です。故意がなければサーバーを攻撃するなんてことは起こりません。
1秒間に何百とリクエスト(通信を要求)を送るようなことがなければ大丈夫です。
仮にそのようなリクエストを送ったとしてもサーバー側がブロックします。攻撃される危険があるのでサーバー側が防御策を持つのは当然ですよね。そのブロックも回避するようなことをすれば、それは明らかに攻撃の意思があると見なされて違法行為になるでしょう
それも簡単なことではないので、私の記事で勉強したぐらいでは出来ないはずです。
- 一度に送るリクエストは30個まで。
- 24時間リクエストを送り続ける場合は最低2~5秒以上は間隔を空ける。
これを越えなければ違法になるような攻撃にはなりません。リクエストは1個でリンクを1回クリックしたのと同じことです。リンク30個をタブ30個で同時に開いたとしても問題無いよ!という感じです。
24時間リクエストを送り続けてデータを収集する行為をスクレイピングと言います。
このスクレイピングは非常に有益な情報を生みます。興味のある人は「スクレイピング」や「ウェブスクレイピング」などで検索しましょう。
Ajaxを使おう。
まずは以下のファイルをダウンロードして、フォルダを作りファイルを配置してください。
ルートフォルダ
- index.html
- style.css
- test.js
- linksフォルダ
- sample1.html
- sample2.html
- sample3.html
- sample1フォルダ
- sample2フォルダ
- sample3フォルダ
となっています。index.htmlを開いてリンク先などをチェックしてください。
コードはtest.jsを作りその中に書いていきます。
const link = document.querySelectorAll("a")
for(let item of link){
const url = item.getAttribute("href")
const parent = item.parentNode
getImage(url,parent)
}
function getImage(url,ele){
}
あらかじめこのようにコードが書かれているので、関数getImage(url,ele)の中身を作っていきます。目的の処理結果は、
- リンク先にある画像を全て取得してindex.htmlに表示する。
これを実現するにはAjaxを利用してリンク先のページのhtmlコードを取得する必要があります。まずはAjaxを使えるようになりましょう。
Ajaxを使うにはまずXMLHttpRequestというオブジェクトを作ります。
const req = new XMLHttpRequest();
時間を取得するために作ったnew Date()と同じですね。このXMLHttpRequestの持っているメソッドを使っていろいろ処理を行っていきます。
基本的な使い方を確認します。コードと画像は同じものです。
const req = new XMLHttpRequest();
req.onreadystatechange = function(){
if(req.readyState == 4){ // 通信の完了時
if(req.status == 200){ // 通信の成功時
const html = req.responseText
}
}else{
// 通信中
}
}
req.open("GET", url, true);
req.send(null);
11行目:req.open(“GET”, url, true) open(第一引数,第二引数,第三引数)
openはサーバーに送るリクエストの内容を作るメソッドです。
第一引数:”GET”か”POST”です。”POST”の方が高機能ですが今回の場合は必要がないので”GET”で行います。”POST”は何か投稿したりサーバーにデータを蓄積させることに特化しています。”GET”には簡単に扱える利点があります。
第二引数:リクエストを送るURLを指定しましょう。
第三引数:非同期処理を行うかどうか、デフォルト(無記入)でtrue。
非同期処理にしましょう。Ajaxは非同期通信をするためのプログラムです。同期処理にしてしまうとサーバーとの通信が完了するまでページが固まります。
12行目:req.send(null) 実際にサーバーにリクエストを送る処理。”GET”の場合は引数にはnullを渡します。”POST”の場合は引数にいろいろと入れます。
2-10行目:req.onreadystatechange = function(){}
onreadystatechangeはイベントです。サーバーからの通信状態を常に監視してくれます。通信に変化が合った場合に中の関数の処理が行われます。
3行目:if(req.readyState == 4){} 現在の通信状態を教えてくれます。readyStateが4のときはデータの通信が完了した合図です。
4行目:if(req.status == 200){} サーバーから返ってきたデータがリクエストの内容に合っているかを教えてくれます。200は正常にデータを受け取れた合図です。他に
401 Unauthorized
403 Forbidden
404 Not Found
500 Internal Server Error
などがあります。見たことあるやつですね。
5行目:req.responseText 通信で得たページのhtmlコードが入っています。このコードを取得するのがAjaxの目的です。
以上が基本的なAjaxの使い方です。今はまだ覚えるのは難しいかもしれませんが処理の内容を理解できるようになっていれば大丈夫です。
Ajaxで得たデータを操作して今回の目的である処理を作りましょう。
>リンク先にある画像を全て取得してindex.htmlに表示する。
まずプログラムの構成を考えます。
- リンクのURLを取得する。
- Ajaxでリンク先のhtmlコードを取得する。
- htmlコードを編集して現在のページに加える。
1.リンクのURLを取得する。これは既にtest.jsに書いてあります。
const link = document.querySelectorAll("a")
for(let item of link){
const url = item.getAttribute("href")
const parent = item.parentNode
getImage(url,parent)
}
<a>タグと兄弟要素として追加する為に.parentNodeで親要素を取得しておきます。
URLと親要素をgetImage関数に送ります。
2.3.Ajaxでリンク先のhtmlコードを取得。htmlコードを編集して現在のページに加える。
function getImage(url,ele){
const req = new XMLHttpRequest();
// 通信時の処理を先に書く
req.onreadystatechange = function(){
const result = document.getElementById('result');
if(req.readyState == 4){ // 通信の完了時
if(req.status == 200){ // 通信の成功時
const html = req.responseText // urlのページから取得したhtmlコードが入っている
// console.log(html) // ←確認するとよい
let img = html.match(/<img.*>/g)
let out = "" // imgタグをまとめておく変数
for(let item of img){
item = item.replace('src="','src="links/')
out += item
}
ele.innerHTML = ele.innerHTML + out
}
}else{
result.innerHTML = "通信中..."
}
}
// サーバーに送る命令
req.open("GET", url, true);
req.send(null);
}
10行目:let img = html.match(/<img.*>/g) String.match(“文字列”) 正規表現が使える。
matchは新しく出てきたメソッドです。正規表現を使って文字列を取り出したりします。指定した文字列が存在しない場合はnullが返ってくるので、文字列の存在確認にも使えます。今回はhtmlコードの中から<img>タグを取り出します。
正規表現の「.*」は何でもいい文字が何文字でもいいという意味でした。
「g」が付いているのでマッチした文字全てを配列形式で返します。
14行目:item.replace(‘src=”‘,’src=”links/’)
まとめた<img>タグが入っている配列imgをfor-ofループで回して、パスを少し変更します
パスの頭に「links/」を付けています。
17行目:ele.innerHTML = ele.innerHTML + out
引数で受け取った<a>タグの親要素のinnerHTMLに、Ajaxで得た<img>タグを後ろに付け足して書き直します。これで現在のページにリンク先にある画像を取ってくることができました。
20行目:通信が正常に行われていない状態のときの処理で、通信中と表示されるようになっています。通信中の処理が行われたことを確認できます。
お疲れ様でした。Ajaxは基本のコード量が多いですがネットサーフィンの効率を驚異的に上げてくれます。次回はデータをパソコンに保存するlocalstorageについて解説します。
次も頑張って記事を作るのでチャレンジしてください!
/⌒ ⌒\
/ 癶 癶 \
/::::::⌒(__人__)⌒::::: \ コメント待ってるよー
| |r┬-| |
\ `ー'´ /