<

Google Apps Script で FetchAllとRedirctURL の組み合わせは悪い

Google Apps Script (以下、GAS)で、困ったことがあったので備忘録として残しておこうと思います。

やろうとしたこと

特定ハッシュタグにおける、ツイートに書いてあるリンクを集めようとしていました。 そのリンクは、特定のドメインのみでフィルタリングしたいとも思っていました。 これらを RESTful API として提供したかったので、手軽に作れる GAS で作ろうと考えていました。

取り組んでみたこと

Twitter に書くリンクは、全て短縮 URL になります。 そのため、短縮 URL にアクセスし、リダイレクト先の URL を取りに行く必要がありました。 GAS では、リクエストメソッドである fetch があります。その fetch のfollowRedirectsというオプションを false にし、responseHeader の location を取ることで、解決(リダイレクト先の URL 取得が)できます。

https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#advanced-parameters

また、1 リクエストだけをする fetch では、直列処理になってしまうため、大変遅いです。 複数リクエストが同時にできる featchAll を使うことで、並列処理ができ、パフォーマンスが良いです。 要するに次のようなコードで解決しようと考えていました。

FetchAllとRedirectURL
FetchAllとRedirectURL
let urlList: Array<string> = ["https://t.co/XXXX", "https://t.co/YYYY"];
const locationList: Array<string> = [];
while (true) {
  const requestList: Array<URLFetchRequest> = urlList.map((url: string) => {
    return {
      url: url,
      method: "get",
      followRedirects: false,
      muteHttpExceptions: true,
    };
  });
  const responseList: Array<HTTPResponse> = UrlFetchApp.fetchAll(requestList);
  urlList = [];
  responseList.forEach((response: HTTPResponse) => {
    const allHeaders: any = response.getAllHeaders();
    const location: string = allHeaders["Location"];
    if (location) {
      locationList.push(location);
      urlList.push(location);
    }
  });
  if (urlList.length === 0) {
    break;
  }
}
return locationList;
追記 (20200228)

https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets

Twitter の API レスポンスに urls がありました。説明はありませんでしたが、Tweet に貼られたリンク(短縮 URL と、オリジナル URL)の情報が入るそうです。

"urls": [
          {
            "url": "https://t.co/Rbc9TF2s5X",
            "expanded_url": "https://twitter.com/i/web/status/1125490788736032770",
            "display_url": "twitter.com/i/web/status/1…",
            "indices": [
              117,
              140
            ]
          }
 ]

困ったこと

この手段だと、Location を 1 つ 1 つ辿っていくことになります。 そのため、リダイレクトを自動的に追う( followRedirects: true )よりも、処理コストが大きいです。まあ、そこは目を瞑ります。

次です。

https://www.monotalk.xyz/blog/google-app-script-%E3%81%AE-urlfetchapp-%E3%81%AE-%E4%BE%8B%E5%A4%96%E3%83%8F%E3%83%B3%E3%83%89%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/

fetch や fetchAll は、muteHttpExceptions: true としたとしても、ExceptionError が発生してしまいます。 そうすると、例えば 1000 件の URL を fetchAll した場合、どれが成功で、どれが失敗で、どれが未実施か がわからないというところです。

FetchAllとRedirectURL (Error)
FetchAllとRedirectURL (Error)

Promise.allSettled が使えれば、解決できるのかなと思いますが、現状 Promise は使えません。

私が思う解決策としては、

  • fetchAll ではなく、fetch を使う
  • fetchAll でリクエストする件数をいくつかの塊に分ける。(一気にではなく、分ける)

最後に

そもそもなのですが、今回やろうとしたことって GAS の良さがないですよね。 GAS は、GSuites 連携を簡単にできるという良さがあります。

しかし、今回はちょっとしたクローラーを作りたいだけでした。もちろん、GAS でも作れると思いますが、いくつかを妥協しないといけなくなります。

もし、そこが妥協できないのであれば、別の手段を検討する必要があります。

教訓

  • 表面的
    • fetchAll するときは、リダイレクト先 URL を取得しない
  • 根本的
    • 目的に適したツールを選択する

ちなみに、このツールは、並列処理をシンプルにコーティングできる golang で書き直そうと考えています。

Tags

ZoomのMeetingを自動生成するGASライブラリ zoom-meeting-creator を作った

2020-06-06

みなさん、Zoom使っていますか? ZoomのMeetingを自動生成するGASライブラリを公開しましたので、そのきっかけと使い方について紹介しようと思います。...

Google Apps Script でも テスト がしたい! (Clasp + Typescript + Jest)

2020-02-01

Google Apps Script(以下,GAS)でライブラリを公開しました。ライブラリを開発する際、テストのフィードバックサイクルを短くするため、`Clasp + Typescript + Jest` という技術スタックを選択しました。その開発体験について共有しようと思います。特段変わったことはしていません。...

TikTokスクレイプ基盤をGCP上で構築してハマったこと

2021-08-28

TikTokへスクレイプするバッチをGCP上で構築しました。GCP構築のシステム設計話と、その構築時に、ハマったことを共有します。...

ブラウザの仕組みを学ぶ

2021-05-24

Webフロントエンジニアたるもの、ブラウザの仕組みに興味を持つのは自然の摂理です。本記事では、私がブラウザの仕組みを学んでいく過程を備忘録として残します。...

リモートワークになってから『気軽にすぐ聞く』ことが難しくなった

2021-03-10

リモートワークが普及しつつある今、オンラインでの仕事に慣れているエンジニアも多いのではないでしょうか。私も、そのエンジニアの一人であり、約1年はリモートワークしています。そんな中、久々に会社へ出社すると、気軽に話しかける楽さ を実感しました。この体験について、深堀りしたいと思います。...

20代後半エンジニアである私がこれから学ぶべきこと

2020-10-29

私は、現在26歳のWebエンジニアです。これまでの技術に対する学び方と、これからの技術に対する学び方について、少し考えたいと思っています。...

Micro Frontends を調べたすべて

2020-10-07

Micro Frontendsに関わる記事を100件以上読みました(参考記事に記載しています)。そこから得たMicro Frontendsについてこの投稿に記録します。また、調査メモについて、次のリポジトリに残しています。...

ZoomのMeetingを自動生成するGASライブラリ zoom-meeting-creator を作った

2020-06-06

みなさん、Zoom使っていますか? ZoomのMeetingを自動生成するGASライブラリを公開しましたので、そのきっかけと使い方について紹介しようと思います。...

アカウント画像一括更新ツールを作ったので、紹介と学びについて

2020-06-04

GoogleやGithubなど、様々なサービスのプロフィール情報(画像, etc)を一括更新するツール、puppeteer-account-manager を開発しました。開発の目的や、開発から得た知見を紹介します。...

Micro Frontends を学んだすべて

2020-05-04

Micro FrontendsというWebフロントエンドアーキテクチャがあります。このアーキテクチャを知るために、書籍を読み、簡単なサンプルWebアプリを開発しました。そこから学んだことをすべて議事録として残したいと思います。...

TwitterにあるLinkを収集するツール Cotlin で、世界中のプレゼンテーション資料を知ろう

2020-03-15

Twitterに投稿されているLinkを収集するツール Cotlin を作りました。Collect links in tweet から、Cotlinという名前にしました。Androidのアレに似ています。...

GMailをGCalendarに登録するサービス rMinc を作ってみた

2020-02-17

ターゲットユーザー * GMailとGCalendarを使っている人 メールを開くって面倒じゃないですか? 例えば、次のようなメールを受信していたとします。* アマゾンで商品を購入した際、お届け予定日が記載されたメール * 映画館(TOHOシネマ)でネット予約した際、上映日が記載されたメール * ホテルをネット予約した際、宿泊日が記載されたメール...

1コマ漫画検索サービスTiqav2 (Algolia + Cloudinary + Google Cloud Vision API) 作ってみた

2020-02-08

画像で会話って楽しい 皆さん、チャットツールでコミュニケーションするとき、絵文字や画像って使ってますか?僕はよく使ってます。人とコミュニケーションするのに、文字だけだと堅苦しいイメージですよね。例えば、『OKです、それで先に進めて下さい。』というフレーズだけだと、相手がどのような感情なのか読み取りにくいです。...

フィリピンに行ってきたら、日本は良いなって思うようになった

2019-10-27

2019年10月11日~2019年10月15日の5日間、フィリピンに行ってきました。日本人男性(前職の先輩:Kikuchi)とフィリピン人女性が結婚するため、その結婚式旅行に同伴させて頂きました。Kikuchiさんとは、私が新人の頃に大変お世話になった方なので、お祝いの気持ちが込み上げてきました。:)...

技術書典7で初執筆した経験をすべて公開

2019-09-06

技術書典7で初執筆しました。記事の目的 * 執筆でどういったことをしたのかの備忘録 * 執筆を考えている人の助けになりたい実際に販売する本は↓のものです。...