ウェブのデータを簡単に取得する方法

business-notepc プログラミング

Googleスプレッドシートやエクセルで家計簿をつけている場合、クレジットカードの明細を転記する必要がありますよね。

転記する方法として、以下のような方法があります。

  • 明細を見て、家計簿に手入力する
  • ウェブサイトの明細をCSVでダウンロードして家計簿に貼り付ける
  • ウェブサイトの明細をコピーして貼り付ける

手入力で入力するのは大変ですよね。CSVをダウンロードして貼り付けれたらいいですが、CSVをダウンロードできない場合もあります。

今回は、ウェブサイトのデータをJavaScriptを使って取得する方法を紹介します。

Webのデータを取得するには

Webのデータを取得する方法として、スクレイピングやAPIがあります。今回の記事ではDOMを使ってデータを取得してみます。

スクレイピングとは

ウェブスクレイピングとは、ウェブサイトから情報を抽出するコンピュータソフトウェア技術のこと。

Wikipedia -ウェブスクレイピング

インターネットで調べものをするときには、Google ChromeやMicrosoft Edgeなどのブラウザを使って、ウェブサイトを閲覧します。

それに比べて、スクレイピングは、ウェブサイトで提供されている情報の中から必要なもののみを抜き出して、加工することができます。

スクレイピングのプログラムを書くことで、自動で大量のデータを取得することができますが、ウェイブサイトによれば規約違反になったりするので注意が必要です。

APIとは

アプリケーションプログラミングインタフェース(API、英: Application Programming Interface)とは、広義ではソフトウェアコンポーネント同士が互いに情報をやりとりするのに使用するインタフェースの仕様である。

Wikipedia – アプリケーションプログラミングインタフェース

簡単に言えば、あるアプリケーションが持っているデータを、外部から使えるように公開している仕様のことです。

Twitterのデータを取得しようとした場合、スクレイピングは禁止しているので公開しているAPIを利用する必要があります。

DOMとは

Document Object Model(DOM、日: ドキュメントオブジェクトモデル)は、マークアップがなされたリソース(Document)をリソース要素(Object)の木構造(Model)で表現し操作可能にする仕組み、またそのモデルである。

Wikipedia – Document Object Model

ウェブサイトの多くは、HTML(ハイパーテキストマークアップ言語)で記述されており、DOMで操作することができます。DOMを使うことによって、そのウェブサイトにプログラムでアクセスすることができます。

Google Chromeなどのブラウザは、JavaScriptでDOMにアクセスする仕組みを提供しています。ブラウザがあればDOMを使うことができます。

開発者ツールを開く

DOMを使うために、Google Chromeでデベロッパーツールを開きましょう。

右上の三点リーダをクリックし、「その他のツール」→「デベロッパーツール」をクリックするか、「Ctrl+Shift+i」または「F12」を押すことでデベロッパーツールが開きます。

open-developer-tool

今回はGoogle Chromeを使って解説しますが、Microsoft EdgeやFireFoxでも同様のツールがあります。

デベロッパーツールが開いたら「Console」をクリックして、「>」の横にJavaScriptを書くことでスクリプトを実行することができます。

developer-tool-console

以下のスクリプトをコンソールに書いて「Enter」をクリックしてください。「Hello,World!」と表示されます。

const message = "Hello,World!";
console.log(message);
console-hello-world

コンソールで「Enter」は実行になるので、改行は「Shift+Enter」です。コンソールに直接入力するのではなく、メモ帳などのテキストエディタで書いたものをコンソールに貼り付ける方法がいいかもしれません。

DOMを使ってウェブにアクセスする

楽天カードのWEB明細サービス「楽天e-NAVI」を使って解説していきます。最終的なスクリプトを見たい場合は、こちらをクリックしてください。

DOMを使ってウェブサイトの情報にアクセスするためには、欲しいデータの要素を調べる必要があります。

HTMLは、ハイパーテキスト・マークアップ・ランゲージと言われ「<div>コンテンツ</div>」のようなタグで囲むような形で表現されます。

<div>などのタグやclass名、id名などを使ってデータにアクセスします。

デベロッパーツールを使って調べてみましょう。上部にあるマウスのアイコンをクリックして、ウェブサイトの対象部分をクリックすればその要素が表示されます。

select-element-by-class

対象の要素を拡大したものが以下の画像です。

select-element-by-class

<div>タグで囲まれており、そのclass名は「stmt-payment-lists__tbl」ということがわかったので、以下のスクリプトをコンソールパネルに貼り付けて実行します。

const element = document.querySelectorAll(".stmt-payment-lists__tbl");
console.log(element);

実行すれば以下のように要素のリスト(NodeList)が取得できました。

get-nodelist

querySelectorAll()メソッド

HTMLは、以下のようなDOMツリーを持っています。documentを使うことで、ブラウザで読み込まれたウェブページのDOMツリーにアクセスすることができます。

using_the_w3c_dom_level_1_core-doctree
参照:mW3C DOM Level 1 Core – mdm web docs

documentの要素を取得するのが「querySelectorAll()」メソッドです。今回の要素はclass名を持っていたのでclass名で取得しましたが、id名を持っていればid名で取得することもできます。

  • class名で取得:document.querySelectorAll(“.className”)
  • id名で取得:document.querySelectorAll(“#idName”)

例えば、以下の要素はid名「js-payment-calendar-current」とclass名「stmt-head-calendar-picker__current」の両方を持っています。

select-element-panel

コンソールで以下のスクリプトを実行すれば同じ要素が取得できます。

const element1 = document.querySelectorAll("#js-payment-calendar-current");
console.log(element1);

const element2 = document.querySelectorAll(".stmt-head-calendar-picker__current");
console.log(element2);

ただし、class名は複数の要素に同じclass名が指定されることがありますが、id名はページ内で基本的に1つになるので、ウェブサイトによれば取得した要素が異なることがあります。

「document.querySelectorAll()」以外にも、要素を取得するには以下のようなメソッドがあります。

  • document.querySelector():指定したセレクターに一致する最小の要素を取得
  • document.getElementById():指定したidの要素を取得
  • document.getElementsByClassName():指定したクラス名の要素のリストを取得
  • document.getelementsByTagName():指定したタグ名を持つ要素のリストを取得

各要素を使いやすいように加工する

取得した要素(NodeList)を1つずつ確認してみましょう。「NodeList.forEach()」メソッドを使えば、1つずつの要素にアクセスできます。

各要素のテキストの内容を「innerText」で確認しています。

const nodeList = document.querySelectorAll(".stmt-payment-lists__tbl");
nodeList.forEach(node => { 
  console.log(node.innerText);
});
console-confirm-each-node

指定した文字で区切るsplit()

1行ごとに表示されましたが、このままでは使いにくいですね。どうやらタブで区切られてそうです。タブで区切ってみましょう。

「split()」メソッドを使えば、指定した文字で分割することができます。分割したものは配列で出力されます。タブは「\t」で表します。

const nodeList = document.querySelectorAll(".stmt-payment-lists__tbl");
nodeList.forEach(node => {
  const textArray = node.innerText.split("\t");
  console.log(textArray);
});
console-each-node-split

これでデータごとに分割できて使いやすくなりました。日付と金額だけを出力してみましょう。

const nodeList = document.querySelectorAll(".stmt-payment-lists__tbl");
nodeList.forEach(node => {
  const textArray = node.innerText.split("\t");
  console.log(`${textArray[0]} ${textArray[4]}`);
});
console-each-node-array

「console.log(`${textArray[0]} ${textArray[4]}`);」の「(` `)」は、テンプレートリテラルといい「`」の間を文字列として表します。変数を表示させるときは変数を「${}」で囲みます。

出力したものをコピーしてGoogleスプレッドシートに貼り付けてみます。

paste-spreadsheet

余分な文字が含まれているし、すべてA列に貼り付けられています。要素ごとに「console.log()」で出力させていることに問題がありそうです。何回も「console.log()」で出力せずに、1度だけ出力するようにすれば良さそうです。

また、スプレッドシートに貼り付けるテキストは、タブで列が変わり、改行で行が変わります。スプレッドシートに貼り付けるところまで意識して出力する文字列を作ります。

次のスクリプトを実行して出力結果をコピーして、スプレッドシートに貼り付けます。「\t」はタブ、「\n」は改行を表します。いい感じですね。

const nodeList = document.querySelectorAll(".stmt-payment-lists__tbl");

let outputText = "";

nodeList.forEach(node => {
  const textArray = node.innerText.split("\t");
  outputText += `${textArray[0]}\t${textArray[4]}\n`;
});

console.log(outputText);
finish-paste-spreadsheet

ブロックスコープ

思ったようなスクリプトは完成しました。しかし、書いたスクリプトの変数名がすでにウェブサイトで使用されていた場合、エラーになります。

楽天e-naviでは「yahoo_retargeting_label」という変数がすでに使われています。

const-name

コンソールパネルで同じ変数名を使えば、すでに使用されていますとエラーが出ます。

const-sama-name

「{}」で囲むことで、このブロック「{}」内で宣言された変数は、このブロック内でのみ参照可能となるので、このエラーを回避できます。

以下のようにスクリプトをブロックで囲って実行してみます。

blockscope

コンソールパネルの1行目では「{}」で囲っていなかったのでエラーになりましたが、ブロック「{}」でスクリプトを囲むことで、エラーにならずに実行ができるようになりました。

このようにブロックで囲むことで、ブロック内で宣言された変数はブロック内だけで有効になります。これをブロックスコープといいます。

最終スクリプト

以下のスクリプトで、ウェブサイトのデータの取得することができました。

{
  const nodeList = document.querySelectorAll(".stmt-payment-lists__tbl");

  let outputText = "";

  nodeList.forEach(node => {
    const textArray = node.innerText.split("\t");
    outputText += `${textArray[0]}\t${textArray[4]}\n`;
  });

  console.log(outputText);
}

まとめ

ウェブ上の情報のデータを取得するには、スクレイピング、API、DOMなどを使う方法があります。

「document.querySelectorAll()」でウェブサイトの要素を取得することができます。

「split()」を使えば、文字列を指定した文字で分割することができます。

DOMを使えばウェブサイトのデータを取得することができます。この技術を使っていろいろな作業を効率的にしましょう。

バッチを使って作業を効率化をすることもできます。

参考

DOMの紹介 – mdn web docs

JavaScript Primer – 関数とスコープ

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