スクレイピング
GoogleAppsScript
chatwork

Google Apps Scriptでの業界ニュース通知を社内で運用した話

Apps Script Advent Calendar 2017に空いている日があったので参加します。

以前にブログを書きましたが、自社のIRなどのニュース更新の通知プログラムをGoogle Apps Scriptで作ったところ、割と評判が良く運用できています。

image.png

簡単に要点を説明すると、以下のようなプログラムです。

  1. HTMLを取得する
  2. 正規表現でニュースのタイトルとURLを取り出す
  3. 前回投稿したURLまでをチャットに投稿する
  4. 今回投稿したURLをSpread Sheetに残す

今回は、大小様々な問題と、「できるだけ楽に対応する」という方針で暫定的に対処してきた結果をまとめておきます。

User-Agentを指定しないと通知できないサイトの通知

UrlFetchAppではUser-Agentヘッダーを指定するオプションが無いため、User-Agentを指定しないとエラーページを返すようなサイトはクロールできません。

これは良い方法が見つからず、他のページから同じ情報をクロールする方法で対応しました。同じ問題が多ければ、AWS Lambda等、もっと自由度の高い環境に移行したほうが楽でしょう。

HTMLのDOM要素が変わる

当然ながら、サイトのデザインが変わるとエラーが発生するようになります。

そのため度々コードの変更が発生するのですが、以下の工夫で最小限の手間で済むようにしました。

  1. 「一覧要素をパースする正規表現」と「その中のURLとページタイトルを取得する正規表現」を指定するよう、元々汎用的に使えるコードを作る
  2. エラー時にエラー内容をマイチャットに投稿することで気づきやすくする

詳しくは『自社のIRをGoogle Apps ScriptでChatWorkに通知する』を見てください。

クローリング先とのサイトの通信に失敗する

クロール先のサイトが落ちている場合があり、これは度々発生します。

ニュースの通知が目的だと割り切って、次の実行で成功すればニュースがきちんと通知されるように作りました。

様々なレイヤーのエラーが通知されるのでネットワーク通信周りの勉強にもなると思います。

最新のニュースが削除されるケースがある

「一つ前に投稿されたニュースURLが出てくるまで通知する」ように作ってしまったので、最新ニュースが削除されたときにページ全体分のURLが投稿されてしまいます。

これは、「投稿する件数が5件以上ならマイチャットに投稿する」という対応で乗り切りました。自分には通知が来てしまうのですが、他のメンバーには迷惑をかけません:slight_smile:

「正規表現の操作が実行時間の上限を超えた」エラーへの対応

運用していた間、急に以下のエラーが発生するようになりました。

InternalError: 正規表現の操作が実行時間の上限を超えました。

Atomフィードをパースしていたサイトがあったのですが、記事のHTMLの一部で正規表現のパースに時間がかかっていたようです。

実は一部のサイトでHTMLからの情報抽出でXMLServiceでパースできない場合があり、汎用性のために正規表現を利用していました。

XMLServiceを使う方法は、以下のサイトを参考にすると良いと思います。

この際は、スクレイピングするページを変えることで対応しました。「より高速な正規表現で実装した」とかならかっこいいですが、ちょっとそこまで手が回りませんでした。

チャットワークAPIの自動投稿に未読がつかなくなる

そのため、自分が自動投稿したニュース記事に自分で気づかない状態になってしまいました。

自動投稿後に「未読をつけるAPI」を追加で叩くように変更しました。

最後に

Google Apps Scriptでは便利なスクリプトをサクッと書けるのが魅力で、業務の空き時間に便利なプログラムを作ってしまうことも可能です。

そのため機能が制限されており、どうしても知恵や工夫が必要な面があります。がんばっていきましょう。