【2022年】PhantomJsCloudを用いた動的サイトのスクレイピングのやり方

こんにちはたくまろです。
最近、私欲に塗れた書籍紹介が多いので、たまには役に立ちそうなことを書いてみました。

今回はPhantomJsCloudを使った動的サイトのスクレイピングについて紹介したいと思います。

PhantomJsCloudは、ヘッドレスブラウザのクラウドサービスです。
簡単にいうと、JavaScriptで書かれている情報をHTMLのソース上に反映させてることができるサービスです。

今回は、ネットジャパンの金とプラチナ、シルバーの買取相場表をスクレイピングしてみたいと思います。

プロフィール

専門分野:数理統計学、機械学習
統計学やデータサイエンスを中心にブログで発信中!
スクレイピングを使ったシステム開発が得意!
相談・質問も待ってます!Twitter >>>@takumaroblog

ソースの確認

今回は赤枠で囲ったスクラップの金額をスクレイピングしてみたいと思います。

Ctrl+Shift+C(macだとoption+command+C)でソースの検証を開くことが出来ます。

すると、右側の金スクラップの表は<table class=”market_tbl”>…</table>に囲まれた部分に対応しています。
同様にPtスクラップと銀スクラップの価格も<table class=”market_tbl”>…</table>で囲まれています。

Parserライブラリを使ってHTMLにすると非常に長くなるため、あらかじめclassなどを指定すると、目的とする部分のソースを見つけやすくすることができます。

動的サイトのスクレイピングコード

実際にGASでスクレイピングのコードを書いてみます。

Parserの準備

ライブラリの追加で、スクリプトID入力欄に「1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw」を入力し、検索します。Parserライブラリがヒットするので、バージョンを最新のものを選択し、追加します。

PhantomJsCloudのAPIキーの発行

PhantomJsCloudのSign upをして、ログイン後のダッシュボード画面にPhantomJsCloudのAPIキーが表示されます。

 

PhantomJsCloudを使ったサンプルコード

PhantomJsCloudでレンダリングされたHTMLコードを読み取る関数です。
大体、やり方はほぼ決まっているので、他のサイトでも同じような関数が使われていると思います。
2行目には先ほどのAPIキーを入力します。

function phantomJSCloudScraping(URL) {
  let key = "APIキーを入力";
  let option =
  {url:URL,
  renderType:"HTML",
  outputAsJson:true,
  };

  let payload = JSON.stringify(option); 
  payload = encodeURIComponent(payload);
  let apiUrl = "https://phantomjscloud.com/api/browser/v2/"+ key +"/?request=" + payload;
  let response = UrlFetchApp.fetch(apiUrl);
  let json = JSON.parse(response.getContentText());
  let source = json["content"]["data"];
  return source;
}

HTMLのトリミング

phantomJSCloudScrapingで読み取ったHTMLの中で必要な箇所を見つけてトリミングしていきたいと思います。
ここではParserを使って必要な部分を切り抜いていきます。

function myFunction() {
  //スプレットシートとシートの選択
  let spreadSheet = SpreadsheetApp.getActive()
  let sheet = spreadSheet.getSheets()[0]
  //HTMLの読み込み
  let html = phantomJSCloudScraping("https://www.net-japan.co.jp/");
  //金スクラップのデータをトリミング
  let gold =
    Parser.data(html)
    .from('<td>K24</td><td class="tR">')
    .to('</div>')
    .iterate();
  //種類ごとにリスト化
  gold = gold[0].split('</td></tr>')
  //余計な部分を削除
  gold.pop()
  //ログにgoldのリストを表示
  Logger.log(gold)
  let rate
  //種類ごとに体裁を整えてスプレットシートに入力する
  for(i in gold){
    if(i>0){
      rate = gold[i].split('"tR">') [1]
    }else{
      rate = gold[i]
    }
  sheet.getRange(1 + Number(i),2).setValue(rate)
  }
  //プラチナ・銀スクラップのデータをトリミング
  let pla_sv =
    Parser.data(html)
    .from('<td>Pt1000</td>')
    .to('</div>')
    .iterate();
  //種類ごとにリスト化
  pla_sv = pla_sv[0].split('</td></tr>')
  //余計な部分を削除
  pla_sv.pop()
  //ログにgoldのリストを表示
  Logger.log(pla_sv)
  //種類ごとに体裁を整えてスプレットシートに入力する
  for(i in pla_sv){
    rate = pla_sv[i].split('tR">') [1]
    sheet.getRange(10+Number(i)+1,2).setValue(rate)
  }
}

そして、実行するとこのようになると思います。

実行ログに金とプラチナ・銀のスクラップ価格をトリミングしたリストが現れていますね。
コードの中では与えられたデータをスプレッドシートへの書き込みをしています。
その後の流れなどは、以下のページで解説しています。

まとめ

PhantomJsCloudの動的スクレイピング、思ったよりも簡単だったのではないでしょうか?
このやり方を応用してスプレッドシートで金相場表を作っています。

【2022年最新】GASを用いた動的サイトのスクレイピングで金相場表作ってみた

6 COMMENTS

ヤス

初めまして、ヤスと申します。
初心者にも分かりやすい丁寧な記事を執筆いただきありがとうございます。
GASを用いた動的サイトのスクレイピングについて解説しているブログをいくつか回っていたのですが、この記事が一番分かりやすく感じました。

———————————————————————————————————
以下、本記事を参考に私が作成しているスクリプについての質問です。
(記事についての質問ではないので、回答できない場合は無視してください。)

GASを触ったことはなかったのですが、記事内の「HTMLのトリミング」に記載のスクリプトを雛形とし、私がスクレイピングしたいサイト内のデータを当てはめてみました。
しかし結果は指定したページのほぼすべてのHTMLコードを出力するだけで、私が取得したいデータが表示されませんでした。
今回、私が取得したいデータは下記です。
サイトURL:
https://objkt.com/profile/dogami/created?sortBy=askAsc&type=
取得したい箇所:
「DOGA BONE」や「Dogami #XXXX」などの商品名

function myFunction() {
//スプレットシートとシートの選択
let spreadSheet = SpreadsheetApp.getActive()
let sheet = spreadSheet.getSheets()[0]
//HTMLの読み込み
let html = phantomJSCloudScraping(“https://objkt.com/profile/dogami/created?sortBy=askAsc&type=”);
//Dogami商品名のデータをトリミング
let dogami =
Parser.data(html)
.from(‘Doga Bones 8,000 x’)
.to(”)
.iterate();
  //種類ごとにリスト化
dogami = dogami[0].split(‘DOGAMÍ‘)
//ログにdogamiのリストを表示
  Logger.log(dogami)
let rate
}

Dogami商品名のデータをトリミングからすでに不備があるようなのですが、どのようにトリミング箇所を指定していいのかが分かりません。
図々しいお願いになりますが、修正すべき箇所がありましたらご教授いただければ幸いです。

返信する
Takumaro

ヤスさん
ご質問ありがとうございます。

原因まではよくわかりませんが、
トリミングの部分を次のようにすると、上手くいきました。

let dogami =
Parser.data(html)
.from(‘class=”title text-ellipsis”>’)
.to(”)
.iterate();

返信する
ヤス

ご回答ありがとうございます!

fromの中をclassで指定できるんですね。
toの中の”のままだと私のGASではエラーが起きてしまったので、以下のように/devを指定することで取得したい商品名を表示させることが出来ました。

//Dogami商品名のデータをトリミング
let dogami =
Parser.data(html)
.from(‘class=”title text-ellipsis”>’)
.to(‘/div’)
.iterate();
//ログにdogamiのリストを表示
  Logger.log(dogami)

次はスプレッドシート上に表示させるスクリプトを書いていきます。
合わせてhtmlとGASについて基礎知識を少しづつ勉強していきたいと思います。

返信する
Takumaro

divタグの部分が消えていましたねすみません
解決できて良かったです。頑張ってください!!

返信する
メグ

はじめまして。
ネットジャパンのスクレイピング参考にさせていただきました。
ありがとうございます。

他社の金相場をスクレイピングしたく、
自分でやってみたのですがうまくいかず…

gold = gold[0].split(”)
gold.pop()
let rate
for(i in gold){
if(i>0){
rate = gold[i].split(‘”tR”>’) [1]
}else{
rate = gold[i]
}
sheet.getRange(1 + Number(i),2).setValue(rate)
}

↑の部分の(”)と(‘”tR”>’) を変えるところか、
.to(”)
のところかな…?と思うのですが、
どうしても表の一番上の1つの金額しか抽出できませんでした…


https://www.high-rate-buy.com/market/


https://apre-g.com/precious-metal/market/

①と②の金相場について、ご教示いただけないでしょうか?

お忙しい中、図々しく大変お手数かと思いますが、宜しくお願い致します。

返信する
Takumaro

メグさん、コメントありがとうございます。
そうですね、split()の中身をそれぞれのサイトに合わせて作る必要があります。
ctrl+Shift+Cで該当箇所のHTMLソースを見ることができるので、
これを使ってスクレイピングしたい場所を少しずつ絞っていく感じです。
①のサイトの一番上の買取価格表の金額を抽出してみたので、参考にしてみてください。

返信する

Takumaro へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です