質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

解決済

1回答

413閲覧

開発者ツールに表示されている内容と実際に取得できた内容が異なる

Kodanosuke

総合スコア42

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

0クリップ

投稿2023/05/21 02:31

編集2023/05/21 03:05

実現したいこと

下記サイトから下記内容を取得したいと考えています.ブラウザの開発者ツールから見た内容と,後述するコードにて取得した内容が異なってしまいます.どのようにして合わせたらいいかご教示いただけないでしょうか?よろしくお願いいたします.
https://weathernews.jp/s/pain/city.html?lat=38.0151938888889&lon=138.371501944444
取得内容

  • <div class="item trasparent">タグの最後のところに含まれる内容を取得したい
  • <p class="ti">の内容が開発者ツールと取得した内容で異なっている

発生している問題・エラーメッセージ

後述のコードで取得できし,tmpdの変数に格納される内容が下記のとおりです. <p class="da sun day-change">21<span class="week">(日)</span></p> <p class="ti">0</p> <p class="fc lv0"><img src="//smtgvs.weathernews.jp/s/pain/images/statusA/Lv0.svg"><span class="txt">安心</span></p> <p class="we"><img src="//mwsgvs.weathernews.jp/s/img/telop/600.png"></p> <p class="ap">987</p> 開発者ツールから確認できた内容は添付画像のとおりです.![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2023-05-21/bbf3022e-27f4-4496-a68b-c3abc83e8377.png)

該当のソースコード

Google

1 2const level = ["安心", "やや注意", "注意", "警戒"] 3var date = new Date(); // 現在時刻を取得 4var futureDate = new Date(date.getTime() + (36 * 60 * 60 * 1000)); // 36時間後の日付を計算 5 6var hour = futureDate.getHours(); // 時間を取得 7var nearestHour = Math.floor(hour / 3) * 3; // 最も近い3の倍数の時間を計算 8 9var targetDate = getClosestTime()//new Date(futureDate.getFullYear(), futureDate.getMonth(), futureDate.getDate(), nearestHour, 0, 0, 0); // 最も近い3の倍数の時間の日付を作成 10 11function main_dataStorage() { 12 //URL指定 13 var tgtSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('2:取得データ'); 14 15 const url = tgtSheet.getRange("A2").getValue() 16 //getResource関数を呼び出し 17 var APIKEY = tgtSheet.getRange("G2").getValue() 18 var response = getResource(url, APIKEY); 19 //parseResponse関数を呼び出し 20 var source = parseResponse(response); 21 22 //地域を取得 23 var area = Parser.data(source) 24 .from('class="tit-h1">') 25 .to('の天気痛予報') 26 .build(); 27 var prefec = Parser.data(source) 28 .from('index.html?') 29 .to('</a>') 30 .iterate(); 31 32 var strt = prefec[1].indexOf(">") + 1 33 var last = prefec[1].length 34 var head = prefec[1].substring(strt, last) 35 36 var area = head + area 37 tgtSheet.getRange("B1").setValue(area) 38 39 //スクレイピングの対象をすべて取得する 40 var items = Parser.data(source).from('<div class="item transparent">').to('</div>').iterate(); 41 var tmpd = items[items.length-1] 42 Logger.log(tmpd) 43 44 //時刻を取得する 45 var hh = parseInt(Parser.data(tmpd).from('"ti">').to("</p").build())+6 46 var today = Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd HH'); 47 // today.; 48 // today.setMinutes(0); 49 // today.setSeconds(0); 50 // today.setMilliseconds(0); 51 52 53 54} 55 56 57 58 59function getResource(target_url, APIKEY) { 60 //HTTPSレスポンスに設定するペイロードのオプション項目を設定する 61 var _options = { 62 url: target_url, 63 renderType: "html", 64 outputAsJson: true 65 }; 66 67 //オプション項目をJSONにしてペイロードとして定義し、エンコードする 68 var _payload = encodeURIComponent(JSON.stringify(_options)); 69 //PhantomJsCloudのAPIリクエストを行うためのURLを設定 70 var _request = 71 "https://phantomjscloud.com/api/browser/v2/" + 72 APIKEY + 73 "/?request=" + 74 _payload; 75 //設定したAPIリクエスト用URLにフェッチして、情報を取得 76 var _response = UrlFetchApp.fetch(_request).getContentText(); 77 78 return _response; 79} 80 81function parseResponse(response) { 82 //取得したjsonデータを配列データとして格納 83 var _json = JSON.parse(response); 84 //APIから取得したデータからJSから生成されたソースコードを取得 85 var _source = _json["content"]["data"]; 86 87 return _source; 88} 89 90function getCurrentDate() { 91 var date = new Date(); // 現在の日付を取得 92 var options = { year: 'numeric', month: '2-digit', day: '2-digit', weekday: 'short' }; 93 var formattedDate = date.toLocaleDateString('ja-JP', options); // フォーマットを指定して日付を文字列化 94 return formattedDate//.replace(/\//g, ""); // / を削除して返す 95} 96 97 98} 99 100 101

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

UrlFetchAppで得られるのは、指定URLにHTTPプロトコルでGETした結果のHTMLですが、
ウェブブラウザでそのURLを指定して表示されるのは、得たHTMLからJavaScriptが起動されてJavaScriptが加工した結果のHTMLなので、一般的には異なります。(JavaScriptで加工しないページだと一致する)

コード中にAPIという文字が見えるのですが、WebAPIだとプログラムでそのまま処理可能なデータの形でデータが返されるはずです。
WebAPIじゃなくて、ウェブブラウザーで人間向けに表示されるページから情報を取得するのであれば、ブラウザを使うなりしてJavaScriptの処理結果を反映する必要があります。

解決策としては、
案1:人間向けのページじゃなくて、プログラム処理向けのWebAPIを使う(提供されている場合)
案2:一般のプログラム実行環境であればSeleniumライブラリー等ウェブブラウザーを制御して処理する・・・GASのような環境の場合はどうするのかと、ググってみると、PhantomJsCloud という外部サービスを使ってJavaScript加工後のページを取得したという例が見つかりました。

投稿2023/05/21 04:20

編集2023/05/21 04:28
otn

総合スコア84538

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kodanosuke

2023/05/21 04:59

返信ありがとうございます。 ご指摘いただいているAPI のところは、回答の中に出てきていたphantomJScloud経由でスクレイピングしております。 そちらを経由しても今回のような問題が発生するため、解決策をご教示いただけないかと思っています。 言葉足らずで申し訳ありません。 もし何かご存知でしたら教えていただけないでしょうか。 よろしくお願いします。
otn

2023/05/21 08:43

失礼しました。文中に特に何も書いてなかったので、プログラムを部分的にしか見てませんでした。 phantomJScloudの制約ですかね。 あるいは、対象サイトがスクレイピングを嫌がって防止している可能性もありますが、規約で禁止してないことを確認済みであれば、関係ないでしょうね。 私なら、 ・phantomJScloudの制約事項(「こういうケースでは対応できない」など)を精査 ・手元PCでSeleniumを使ってどうなるか確認。それがうまくいく前庭で、ブラウザをヘッドレスモードでどうなるか確認 とかでしょうか。JavaScriptでブラウザの情報(UAや画面サイズなど)を取得して何かしている場合にうまく行かないとかあるのかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問