Cet article est le premier jour du calendrier de l'Avent 2019 de l'Université de la ville de Tokyo. https://adventar.org/calendars/4282
salut! Je m'appelle Ojie (@ 920oj) et j'étudie les systèmes d'information dans une université appelée Tokyo City University. Cette fois, j'ai construit un calendrier de l'Avent de la taille d'une ville, alors je J'écrirai "L'histoire de la création d'un bot LINE qui vous informe d'un petit-déjeuner de 100 yens à l'université avec Python"!
Notre école dispose d'un système très rentable où vous pouvez prendre votre petit-déjeuner pour 100 yens. De plus, comme je vis seul à Tokyo dans une zone rurale, c'est parfait pour manquer d'argent.
C'est 100 yens
Ce menu est affiché sur le site Web de la cafétéria tous les matins, mais ce site Web est un auteur-compositeur et vous devez passer par l'application ou le site portail de l'école pour y accéder.
Par conséquent, j'ai décidé de gratter automatiquement le site Web de la cafétéria chaque matin et de créer une notification LINE qui informera LINE du petit-déjeuner de 100 yens de la journée.
Python v3.7.1 pip 19.1.1 Windows 10 v1903
Cafétéria des étudiants du campus de Yokohama de l'université de la ville de Tokyo Bot de notification de petit-déjeuner de 100 yens https://github.com/920oj/TCU-YC-Breakfast-Notify-Bot
Ainsi, vous serez averti tous les jours à 7h30 du matin (uniquement si vous prenez un petit-déjeuner à 100 yens)!
Tout d'abord, accédez au site Web de l'alimentation scolaire avec Beautiful Soup. Puisque vous devez vous connecter pour parcourir le site Web de l'alimentation scolaire, nous avons établi une directive pour lancer un POST une fois pour vous authentifier, puis pétrir à l'aide de l'identifiant de session.
Cependant, si vous regardez de plus près, l'authentification n'existe pas et il semble que vous écrivez simplement l'ID et le mot de passe en texte brut dans le cookie pour vous authentifier. (C'est OK?)
(À l'origine, une fois authentifié (POST), l'ID de session est lié au fait que l'authentification a réussi et que les demandes suivantes sont acceptées, mais pour une raison quelconque, cela fonctionne sans POST. C'est bien parce que c'est bon) (Ce n'est pas bon à l'origine)
Pour le moment, lorsque vous allez sur la page de connexion, il semble qu'une "clé de session" et un "identifiant de session" soient donnés, donc il commence par l'obtenir.
def get_sessionid():
#Processus initial d'acquisition des cookies
r = requests.get('https://livexnet.jp/local/default.asp')
first_access_cookie = str(r.headers['Set-Cookie'])
# "ASPSESSIONID+Toute capitale anglaise à 8 chiffres"(24 caractères alphabétiques)Avoir
asp_session = str(first_access_cookie[first_access_cookie.find("ASPSESSIONID"):first_access_cookie.find("; secure")])
asp_session_key = str(asp_session[0:asp_session.find("=")])
asp_session_id = str(asp_session[asp_session.find("="):].replace('=',''))
return asp_session_key, asp_session_id
Le framework est comme ASP.NET. En ce qui concerne ASPSESSIONID, il semble qu'une majuscule à 8 chiffres soit ajoutée à la fin, alors obtenez-la également. Les valeurs de retour de cette fonction sont asp_session_key et asp_session_id, et deux types sont renvoyés.
def get_breakfast_info(key,id):
#Préparer les cookies (les informations peuvent changer à l'avenir)
site_cookies = {
key: id,
'KCD': '02320',
'company_id': SITE_ID,
'company_pw': SITE_PASS,
'wrd': 'jp',
'dip': '0',
'ink': 'a',
'bcd': '02320',
'val': 'daily'
}
#Accéder au menu / à la page du tableau nutritionnel
url = 'https://reporting.livexnet.jp/eiyouka/menu.asp?val=daily&bcd=02320&ink=a&col=&str=' + today_data
r = requests.get(url, cookies=site_cookies)
r.encoding = r.apparent_encoding
#Analyse HTML
all_html = r.text.replace('<br>','')
souped_html = BeautifulSoup(all_html, 'lxml')
try:
breakfast = souped_html.find('p', class_="img_comment6").string
return breakfast
except:
return False
Utilisez les outils de développement de Chrome pour voir quels cookies sont définis.
Après vérification, préparez un cookie en fonction de celui-ci et chargez-le dans beautifulsoup, alors préparez un dictionnaire.
La clé est la clé de session obtenue précédemment et l'ID est l'ID de session. (Ce n'est pas le nom de la variable. Rendons-le plus descriptif)
Comme mentionné précédemment, il semble que l'ID d'authentification et le mot de passe soient lus en texte brut avec SITE_ID et SITE_PASS (?), Alors spécifiez-le tel quel.
(N'est-il pas inutile d'obtenir cet identifiant de session ...? S'il vous plaît laissez-moi savoir si vous avez des détails.)
Tout ce que vous avez à faire est de le charger dans lxml, qui analyse le HTML, et d'en extraire l'élément de classe "img_comment6"!
def post_line(result):
post_data = 'aujourd'hui(' + today_data + ')100 yens petit-déjeuner' + result + 'est.'
line_api_headers = {"Authorization" : "Bearer "+ LINE_TOKEN}
line_payload = {"message" : post_data}
r = requests.post(LINE_API_URL ,headers = line_api_headers ,params=line_payload)
return r.status_code
Tout ce que vous avez à faire est de passer à LINE Notify. Avec LINE Notify, vous pouvez mettre les informations d'authentification et le contenu du message dans l'en-tête et lancer POST au point de terminaison de l'API pour envoyer les informations à la conversation prédéfinie.
def main():
print('Programme d'affichage du menu du petit-déjeuner à 100 yens de l'Université de la ville de Tokyo')
print('aujourd'hui' + today_data + 'est.')
session = get_sessionid()
session_key = session[0]
session_id = session[1]
print('Obtention des informations d'identification initiales.' + session_key + 'Est' + session_id + 'est. Attendez 3 secondes ...')
sleep(3)
result = get_breakfast_info(session_key,session_id)
if not result:
print('Aucune information n'a pu être obtenue. 100 yens Le petit-déjeuner peut ne pas être disponible.')
sys.exit()
print('Le petit-déjeuner de 100 yens d'aujourd'hui est' + result + 'est. Envoyez une notification à LINE.')
post_status = post_line(result)
if post_status == 200:
print('La notification LINE a réussi. Quittez le programme.')
else:
print('La notification LINE a échoué. La réponse est' + str(post_status) + 'est. Quittez le programme.')
if __name__ == "__main__":
main()
Après cela, j'écrirai le processus principal de la même manière que l'assemblage de la fonction créée précédemment.
Enfin, écrivez ʻif name == "main": `pour éviter que le processus ne soit exécuté arbitrairement si ce programme est importé quelque part. Je n'ai jamais entendu parler d'un mécanisme qui appelle la fonction main () lorsque les noms des fichiers en cours d'exécution correspondent.
Je l'héberge sur mon Lightsail (VPS) emprunté et je l'exécute régulièrement avec cron. Dès que je le lance, je vais prendre le petit-déjeuner de la journée, donc je lance cron tous les matins à 7h30 pour réaliser une exécution régulière.
Pour dire la vérité, ce code a été créé en avril, donc quand je le regarde maintenant, il y a des endroits où les noms de variables ne sont pas corrects et l'implémentation est ambiguë. J'aimerais réécrire le code quand j'aurai un peu plus de temps libre.
Demain est un article de M. K (@ ke_odakyu9000
)! Ravi de vous rencontrer!
https://adventar.org/calendars/4282