unpocoプログラミング

ゲームライフを快適にするためにプログラミングを勉強します。間違ってたら教えてください。

【GAS】GASでCloud Functionsを定期実行

2019/07/31時点ではCloud Schedulerジョブは無料で3つまでしか動かせないようなので別の手段を探した。
GASで出来そうだったのでテストでSlackへの通知までやってみた。

Cloud Functions

トリガーを「HTTP」にする

URLをメモっておく。

https://i.imgur.com/yuSzSfu.png

コード

Slack側に送るJSONを作って返す。

#!/usr/bin/python
# -*- coding: utf-8 -*-
import json


def hello_world(request):
    data = {
        "text": "はろーわーるど",
    }

    json_data = json.dumps(data)
    return json_data

Google Apps Script

トリガーの設定

実行したいタイミングに応じて設定する。

プロパティ設定

コードに直接書くのはやめたほうがいいものを設定しておく。

https://i.imgur.com/ff0pR6p.png

https://i.imgur.com/JlWOgrg.png

コード

function myFunction() {
  var properties = PropertiesService.getScriptProperties();
  var gcf_url = properties.getProperty("GCF_URL");
  var webhook_url = properties.getProperty("WEBHOOK_URL");
  
  var json = getJson(gcf_url);
  sendToSlack(webhook_url, json);
}

function getJson(url) {
  var res = UrlFetchApp.fetch(url);
  var content_text = res.getContentText();
  
  return content_text;
}

function sendToSlack(webhook_url, json) {
  var params = {
    "method": "post",
    "payload": json
  };
  
  UrlFetchApp.fetch(webhook_url, params);
}

実行結果

ちゃんと送られました。
https://i.imgur.com/kVO5MLb.png

参考

developers.google.com

developers.google.com

おわりに

割と簡単にできた。
この間作った糞箱セール情報もこのかたちに変更しようと思う。

おわり。

【Python】Cloud Functionsで環境変数を使う

これまでも前回もWEBHOOK_URLみたいなものをコードに直接書いていたが、よろしくないので環境変数を使う方法を調べた。

前回の記事

参考までに。 unpoco.hatenadiary.jp

環境変数の設定方法

コンソールから普通に設定するだけ。かんたん。

https://i.imgur.com/HHjVEcV.png

環境変数にアクセスするには

こんな感じ。かんたん。

def get_env_var(var_name):
    return os.environ.get(var_name, None)

url = get_env_var("URL")

参考

cloud.google.com

おわり

【Python】Cloud Functionsでselenium使ってスクレイピングしてslackにメッセージ送信

いまさらながら個人的にSlackを使うことにしたので何かしらのツールを作ることにした。

つくったもの

これ。公式のセール情報を定期的にSlackに投げるやつ。 https://i.imgur.com/rDiryis.png

構成

それっぽい構成図も作ってみた。
Schedulerで定期的に関数を走らせるだけ。

https://i.imgur.com/o32jJEo.png

問題

ソフトの一覧がjavascriptで作られていたのでseleniumを使う必要があった。
seleniumを使うときは動かすマシンにブラウザとそれ用のdriverを入れる必要があるが、Cloud Functionsでそんなことが出来るのか??

Googleに聞く

1つだけそれらしき情報を見つける。
このおかげで出来ました。本当にありがとうございます。
感謝の気持ちを伝えたかったがコメント欄が無かったため泣く泣く諦める。

blowup-bbs.com

手順

SlackのIncoming Webhooks設定

名前決めたり、通知先のチャンネル決めたりする。
Webhook URLをメモっておく。

gcf-packs関連の作業

githubから持ってくる

Cloneなりダウンロードなりする。 github.com

headless-chromium.zipを展開

selenium_chrome/source/headless-chromium.zip」

main.pyを書き換える

selenium_chrome/source/main.py」
実行する関数はsale_pubsub

import json
import os
import random
import time

import requests
from selenium import webdriver
from fake_useragent import UserAgent

WEBHOOK_URL = "メモったWebhook URL"
URL = "https://www.xbox.com/ja-jp/games/xbox-one?cat=onsale"


def get_games_info():
    games_info = []

    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--disable-gpu')
    chrome_options.add_argument('--window-size=1280x1696')
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--hide-scrollbars')
    chrome_options.add_argument('--enable-logging')
    chrome_options.add_argument('--log-level=0')
    chrome_options.add_argument('--v=99')
    chrome_options.add_argument('--single-process')
    chrome_options.add_argument('--ignore-certificate-errors')
    chrome_options.add_argument('user-agent='+UserAgent().random)

    chrome_options.binary_location = os.getcwd() + "/headless-chromium"
    driver = webdriver.Chrome(
        os.getcwd() + "/chromedriver", options=chrome_options)

    driver.get(URL)
    time.sleep(10)

    games = driver.find_elements_by_class_name("m-product-placement-item")
    for game in games:
        title = game.find_element_by_tag_name("h3").text
        price = game.find_element_by_class_name("textpricenew").text
        games_info.append("{} {}".format(title, price))

    driver.quit()

    return games_info


def make_json(games_info, count):
    payload = {}

    main_text = "以下のゲームなどがセール中!"
    payload["text"] = "<{}|{}>".format(URL, main_text)
    payload["attachments"] = []

    if len(games_info) <= count:
        games = games_info
    else:
        games = random.sample(games_info, count)

    for game in games:
        item = {
            "color": "#01DF01",
            "text": game
        }
        payload["attachments"].append(item)
    return json.dumps(payload)


def sale_pubsub(event, context):
    print("開始")
    games_info = get_games_info()
    json_data = make_json(games_info, 5)
    res = requests.post(WEBHOOK_URL, json_data)
    print("status_code : {}".format(res.status_code))
    print("終了")

GCP側の作業

Pub/Subトピックを作成

今回は「sale」とした。

Cloud Schedulerの設定

毎日01:00に動くようにした。
ターゲットを「Pub/Sub」、トピックを「sale」にする。
ペイロードは使わないのでなんでもいい。 https://i.imgur.com/RmR86Hf.png

デプロイ

$ cd gcf-packs/selenium_chrome/source
gcloud auth login
gcloud functions deploy [main.pyの実行したい関数] --runtime python37 --trigger-resource [Pub/Subトピック] --trigger-event google.pubsub.topic.publish --region asia-northeast1 --memory 512MB

[main.pyの実行したい関数]と[Pub/Subトピック]は状況に合わせて書き換える。

今回の場合は

  • [main.pyの実行したい関数]:sale_pubsub
  • [Pub/Subトピック]:sale

動作確認

Cloud Schedulerの「今すぐ実行」ボタンを押すだけ。
あとはSlackにメッセージが飛んでくるのを待つ。

参考

Cloud Functions+Python+selenium(Part.3) | Blow Up By Black Swan

SlackのIncoming Webhooksを使い倒す - Qiita

cloud.google.com

おわりに

やったぜ!
これをもとに色々作ってSlackを充実させたいですね。

おわり

【GAS】Google Apps Scriptの始め方2019

使えたほうが何かと便利そうなので始め方をまとめておく。

自分のGoogleドライブにアクセス

新規 > その他 > アプリを追加

https://i.imgur.com/tnxfLrh.png

アプリを追加

Google Apps Script」で検索して「接続」ボタンを押す

https://i.imgur.com/YGxFcpL.png

「OK」

https://i.imgur.com/yhi4XwN.png

追加されていることを確認

https://i.imgur.com/GMlIWfG.png

適当なコード書いて実行

ログに「Hello World!」と出力してるだけ。

https://i.imgur.com/VSqIsDL.png

ログを見てみる

https://i.imgur.com/wqR9flW.png

動いてる

https://i.imgur.com/d1OHHW3.png

トリガーを追加

https://i.imgur.com/DoIIv9h.png

1分間隔で実行するように設定

https://i.imgur.com/QZanDPJ.png

動いてる

https://i.imgur.com/Syc6cLm.png

おわりに

メール送れたり、スプレッドシートいじれたり、翻訳使えたり、Web APIとして公開できたり色々できるみたいなので使えそうなときは使っていこうと思う。

おわり