[PYTHON] Je souhaite répondre automatiquement au formulaire Google à 17 heures tous les matins

Bonjour à tous. C'est l'été. Les activités du club ont enfin repris, et je suis ravi, mais avant-hier soir, mon conseiller m'a contacté comme ça.

-Veuillez mesurer la température avant 5h20 tous les matins et signaler le résultat à partir de Google Form.
-Les membres qui ne se sont pas présentés ne seront pas autorisés à participer à la formation du matin

En premier lieu, j'étais malade lorsque l'entraînement du matin a commencé à 6h30, donc je n'ai pas été surpris quand on m'a demandé de me contacter à 5h20, mais un problème s'est posé ici. Parce que je me lève généralement à 5 heures du matin et que je vais à la gare en vélo en mordant le pain, je n'ai donc pas le temps de mesurer la température. C'est une histoire que je devrais me lever un peu plus tôt, mais je ne veux pas me lever à 4 heures parce que je suis trop serré pour me lever. Cependant, si je me réveille à 5 heures et que je mesure la température, je serai en retard pour l'entraînement du matin lui-même.

Donc, vers 5 heures du matin, j'aimerais créer un programme qui vous enverra une température corporelle dont vous n'avez pas à vous soucier en la saisissant sous la forme spécifiée.

Soumettre le formulaire avec Selenium

Si vous utilisez un vrai formulaire, mon identité sera perdue, donc cette fois formulaire avec le même contenu que le vrai que j'ai créé pour le test / 1FAIpQLScGgZ8dsBkcSVutvW3JgDLqy3pIEKk12ucjiA8mNQrKopILog / viewform) Je voudrais l'implémenter.

Préparer une URL avec l'entrée de la valeur initiale

Google Form peut ouvrir l'URL avec la valeur de chaque question saisie en ajoutant des paramètres. L'URL pour ouvrir un formulaire est normalement https://docs.google.com/forms/d/e/1FAIpQLScGgZ8dsBkcSVutvW3JgDLqy3pIEKk12ucjiA8mNQrKopILog/viewform?usp=sf_link Comme ça, le paramètre "usp = sf_link" est attaché après le formulaire de vue. Ce paramètre indique qu'il s'agit d'un formulaire de réponse pur sans pré-remplissage, donc changez d'abord ceci en "usp = pp_url" pour nous faire savoir qu'il y a un pré-remplissage. Entrez ensuite la réponse à chaque question dans les paramètres. Il y a un numéro qui identifie chaque question sur le formulaire, alors recherchez la question div sur l'écran de validation de Chrome et recherchez un numéro comme celui ci-dessous dans le deuxième niveau. スクリーンショット 2020-08-07 16.56.07.jpg Lorsque vous trouvez le numéro, ajoutez le paramètre sous la forme "" entrée. Numéro = contenu de la réponse "". Cette fois, le nom et la température corporelle sont entrés dans le texte, donc l'URL sera la suivante. https://docs.google.com/forms/d/e/1FAIpQLScGgZ8dsBkcSVutvW3JgDLqy3pIEKk12ucjiA8mNQrKopILog/viewform?usp=pp_url&entry.1534939278=荒川智則&entry.511939456=36.5 Cependant, si cela reste tel quel, il indiquera 36,5 degrés chaque jour, et je m'en méfie, donc je donnerai une bonne impression avec des nombres aléatoires.

# 36.1~36.Générer aléatoirement des valeurs entre 7 et convertir des chaînes
body_temp = str(36 + random.randint(1,7)/10)
#Ajouter à la fin de l'URL
url = 'https://docs.google.com/forms/d/e/1FAIpQLScGgZ8dsBkcSVutvW3JgDLqy3pIEKk12ucjiA8mNQrKopILog/viewform?usp=pp_url&entry.1534939278=Tomonori Arakawa&entry.511939456='+body_temp

Soumission automatique avec Selenium

Une fois l'URL terminée, tout ce que vous avez à faire est d'ouvrir l'URL dans Selenium et de cliquer sur le bouton Soumettre.

#Installez le pilote Selenium et Chrome avec pip
from selenium import webdriver
import chromedriver_binary
import time
import random

body_temp = str(36 + random.randint(1,7)/10)
url = 'https://docs.google.com/forms/d/e/1FAIpQLScGgZ8dsBkcSVutvW3JgDLqy3pIEKk12ucjiA8mNQrKopILog/viewform?usp=pp_url&entry.1534939278=Tomonori Arakawa&entry.511939456='+body_temp

#Cliquez sur la fonction
def click(xpath):
    driver.find_element_by_xpath(xpath).click()

#Fonction d'entrée de mot de passe
def insert_pw(xpath, str):
    driver.find_element_by_xpath(xpath).send_keys(str)

driver = webdriver.Chrome()
driver.implicitly_wait(1)
driver.get(url)

moving_login_button = '/html/body/div[2]/div/div[2]/div[3]/div[2]'
time.sleep(1)

#Connectez-vous si vous devez vous connecter avec votre compte Google
if(driver.find_elements_by_xpath(moving_login_button) != []):
  click(moving_login_button)
  login_id = "{E-mail du compte Google}"
  login_id_xpath = '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div/div[1]/div/div[1]/input'
  login_id_button = '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[2]/div/div[1]/div/div'
  insert_pw(login_id_xpath, login_id)
  click(login_id_button)
  time.sleep(1)
  login_pw = "{Mot de passe du compte Google}"
  login_pw_xpath = '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input'
  login_pw_button = '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[2]/div/div[1]/div/div'
  insert_pw(login_pw_xpath, login_pw)
  time.sleep(1)
  click(login_pw_button)

time.sleep(1)
submit_button = '//*[@id="mG61Hd"]/div[2]/div/div[3]/div[1]/div/div'
click(submit_button)

print("Done!")

driver.close
#Il mange de la mémoire alors finissons-le correctement
driver.quit
スクリーンショット 2020-08-07 17.23.49.png

J'ai pu l'envoyer fermement.

Faites-en un événement régulier

Après avoir écrit le code, tout ce que j'ai à faire est d'en faire un événement régulier, mais j'ai un peu trébuché ici, alors je vais vous expliquer comment le faire. La méthode initialement prévue consiste à en faire une application avec Automator, à la mettre dans le calendrier et à l'exécuter tous les jours ([Reference](https://qiita.com/baraobara/items/73d753c678e5c0e72f46#4-mac%E3%81%AE%] E3% 83% 87% E3% 83% 95% E3% 82% A9% E3% 83% AB% E3% 83% 88% E3% 81% AEautomator% E3% 82% 92% E7% 94% A8% E3% 81% 84% E3% 81% A6mac% E5% 86% 85% E3% 82% A2% E3% 83% 97% E3% 83% AA% E3% 82% 92% E4% BD% 9C% E3% 82% 8B)). Si tel est le cas, vous pouvez le supprimer du calendrier les jours où vous n'avez pas besoin de le signaler, et cela devrait être parfait. J'ai pensé, mais cela ne fonctionne pas lorsque le PC est arrêté. La méthode pour le configurer dans crontab et en faire un événement régulier est également de la merde pour la même raison. Après tout, j'ai décidé d'utiliser AWS Lambda, qui peut exécuter des événements quel que soit l'état du PC, même si je ne peux pas modifier l'événement de manière flexible. (Pour savoir comment utiliser Lambda, ce site a été utile)

Augmentez le sélénium, le pilote Chrome, le chrome sans tête sur la couche Lambda

Pour utiliser la bibliothèque avec Lambda, vous devez compresser chaque dossier et le télécharger dans la couche. Cette fois, nous utiliserons Chromedriver, qui est un pilote Web pour Selenium et Chrome, et du chrome sans tête pour gratter sans ouvrir Chrome, nous allons donc les compresser et les mettre en couches.

  1. Selenium
mkdir selenium
cd selenium
mkdir python
cd python
pip install selenium -t .
cd ../
zip -r selenium.zip ./python

Téléchargez le fichier zip créé sur le calque tel quel.

2. Pilote Chrome et chrome sans tête

curl https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-55/stable-headless-chromium-amazonlinux-2017-03.zip > headless-chromium.zip
curl https://chromedriver.storage.googleapis.com/2.43/chromedriver_linux64.zip > chromedriver.zip

Décompressez les deux fichiers zip résultants et rassemblez-les dans un dossier chrome sans tête. Ensuite, zippez le chrome sans tête et téléchargez-le sur le calque.

3. Appliquer le calque à la fonction

Appuyez sur "Calques" sous la fonction et ajoutez deux calques à partir du bouton "Ajouter un calque" ci-dessous スクリーンショット 2020-08-07 18.36.45.png

※Mise en garde※

--Chromedriver ne fonctionnait pas lorsque j'ai défini le runtime de la fonction Lambda sur Python3.8 (cause inconnue), je recommande donc de définir le runtime sur Python3.6 ou 3.7.

Un petit changement de code pour Lambda

Je n'ai jamais utilisé d'outils AWS autre que Cloud9 auparavant, j'ai donc réussi à faire fonctionner le code avec Lambda en imitant l'apparence de divers sites. Merci à mes ancêtres.

import json
from selenium import webdriver
import time
import random

def lambda_handler(event, context):
    body_temp = str(36 + random.randint(1,7)/10)
    url = 'https://docs.google.com/forms/d/e/1FAIpQLScGgZ8dsBkcSVutvW3JgDLqy3pIEKk12ucjiA8mNQrKopILog/viewform?usp=pp_url&entry.1534939278=Tomonori Arakawa&entry.511939456='+body_temp
    options = webdriver.ChromeOptions()
    options.binary_location = '/opt/headless-chrome/headless-chromium'
    #Sans ces 4 options, Chrome ne démarrera pas et une erreur se produira.
    options.add_argument('--headless') #Lancer Chrome sans serveur
    options.add_argument('--no-sandbox') #Lancer Chrome en dehors du bac à sable
    options.add_argument('--single-process') #languette/Passer à un processus unique au lieu de plusieurs processus par site
    options.add_argument('--disable-dev-shm-usage') #Changer l'emplacement de sortie du fichier mémoire
    driver = webdriver.Chrome('/opt/headless-chrome/chromedriver',options = options)
    driver.implicitly_wait(1)
    driver.get(url)
    
    def click(xpath):
        driver.find_element_by_xpath(xpath).click()

    def insert_pw(xpath, str):
        driver.find_element_by_xpath(xpath).send_keys(str)
    
    moving_login_button = '/html/body/div[2]/div/div[2]/div[3]/div[2]'
    time.sleep(2)
    if(driver.find_elements_by_xpath(moving_login_button) != []):
        click(moving_login_button)
        #Variable d'environnement MY_Veuillez définir l'adresse e-mail du compte Google dans GMAIL
        login_id = MY_GMAIL
        login_id_xpath = '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div/div[1]/div/div[1]/input'
        login_id_button = '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[2]/div/div[1]/div/div'
        insert_pw(login_id_xpath, login_id)
        click(login_id_button)
        time.sleep(1)
        #Variable d'environnement MY_Définissez le mot de passe du compte Google dans PASSWORD
        login_pw = MY_PASSWORD
        login_pw_xpath = '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input'
        login_pw_button = '/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[2]/div/div[1]/div/div'
        insert_pw(login_pw_xpath, login_pw)
        time.sleep(1)
        click(login_pw_button)
    time.sleep(1)
    submit_button = '//*[@id="mG61Hd"]/div[2]/div/div[3]/div[1]/div/div'
    click(submit_button)
    driver.close
    driver.quit
    return {
        'statusCode': 200,
        'body': json.dumps('Form submission success!!')
    }

point important

Définir des déclencheurs dans CloudWatch Events

  1. Cliquez sur la fonction Layers, cliquez sur Add Trigger et sélectionnez Event Bridge (CloudWatch Events) dans la liste déroulante.
  2. Pour la règle, entrez un nom de règle arbitraire dans "Créer une nouvelle règle". Définissez le type de règle sur le type de planification, et cette fois il est 5 heures du matin tous les jours, entrez donc corn (0 20? * * *) '' (Notez que Lambda est déclenché par UTC, donc défini il y a 9 heures) .. Activez le déclencheur et cliquez sur Ajouter. (Voir ici pour savoir comment écrire cron)
スクリーンショット 2020-08-07 18.56.44.png

tester

Enfin, testons si cela fonctionne bien. Cliquez sur "Test" sur l'écran de la fonction Lambda. スクリーンショット 2020-08-07 18.51.28.png Ça me va.

en conclusion

Je saute la mesure de la température le matin, mais soyez assuré que je la mesure correctement avant de me coucher.

Les références

https://masakimisawa.com/selenium_headless-chrome_python_on_lambda/ https://github.com/heroku/heroku-buildpack-google-chrome/issues/56 https://qiita.com/mishimay/items/afd7f247f101fbe25f30

Recommended Posts

Je souhaite répondre automatiquement au formulaire Google à 17 heures tous les matins
Je souhaite envoyer automatiquement un e-mail de création d'entreprise
Je souhaite publier le produit au moindre coût
Je veux faire Wake On LAN de manière entièrement automatique
[Django] Je souhaite me connecter automatiquement après une nouvelle inscription
Je souhaite importer des notes Google Keep dans Bear (application mémo)
Je veux trouver automatiquement des pièces de haute qualité à partir des vidéos que j'ai tournées
Je veux comprendre à peu près systemd
Je veux gratter des images et les former
Je veux faire ○○ avec les Pandas
Je veux copier l'annotation de yolo
Je veux déboguer avec Python
Je veux être maudit par une jolie fille à chaque fois que je sudo! !!
[Google Colab] Je souhaite afficher plusieurs images côte à côte dans une vignette