Si vous n'êtes pas intéressé par le code et que vous souhaitez simplement ajouter un calendrier ici. Si vous disposez d'un compte Google, vous pouvez l'ajouter immédiatement.
Dans cet article, nous visons à obtenir des informations auprès de HP et à générer automatiquement le calendrier suivant.
Cette volonté
Hinatazaka 46 est l'un des groupes de pente, et est un groupe dont la devise est "Happy Aura". Bien sûr, il y a beaucoup de gens qui sont attirés par leur "** visuel ", " luminosité " et " attitude à travailler dur sur n'importe quoi **", et je suis l'un d'eux.
Le moyen le plus fiable de suivre leurs activités est de consulter la page «Calendrier» sur HP. Je le vois souvent.
cependant,
Aussi, en présentant le calendrier de ce site, il est possible de couvrir des événements majeurs, mais des événements détaillés (corrigé). Il semblait qu'il n'était pas couvert pour (activités irrégulières qui n'étaient pas faites).
Alors, afin d'éliminer ces insatisfactions, j'ai pensé à réaliser ** "Refléter leur emploi du temps dans mon Google Agenda" **.
Vous devez obtenir l'API Google. Pour la procédure, veuillez vous référer à cet article pour une compréhension facile.
De plus, si vous souhaitez effectuer une exécution régulière, il est préférable d'utiliser cron ou Heroku. Personnellement, j'aime Heroku, qui n'a pas besoin de fonctionner sur mon ordinateur local, alors je l'utilise. En ce qui concerne Heroku, j'ai expliqué comment l'utiliser dans Mon blog hatena avant, veuillez donc vous y référer si vous le souhaitez.
Les informations à acquérir sont les quatre suivantes.
--Catégorie
Puisqu'il peut y avoir plusieurs événements d'apparition le même jour,
Les informations sont acquises dans le flux.
def search_event_each_date(year, month):
url = (
f"https://www.hinatazaka46.com/s/official/media/list?ima=0000&dy={year}{month}"
)
result = requests.get(url)
soup = BeautifulSoup(result.content, features="lxml")
events_each_date = soup.find_all("div", {"class": "p-schedule__list-group"})
time.sleep(3) # NOTE:Éliminez la charge sur le serveur
return events_each_date
def search_event_info(event_each_date):
event_date_text = remove_blank(event_each_date.contents[1].text)[
:-1
] # NOTE:Obtenez des informations autres que le jour
events_time = event_each_date.find_all("div", {"class": "c-schedule__time--list"})
events_name = event_each_date.find_all("p", {"class": "c-schedule__text"})
events_category = event_each_date.find_all("div", {"class": "p-schedule__head"},)
events_link = event_each_date.find_all("li", {"class": "p-schedule__item"})
return event_date_text, events_time, events_name, events_category, events_link
def search_detail_info(event_name, event_category, event_time, event_link):
event_name_text = remove_blank(event_name.text)
event_category_text = remove_blank(event_category.contents[1].text)
event_time_text = remove_blank(event_time.text)
event_link = event_link.find("a")["href"]
active_members = search_active_member(event_link)
return event_name_text, event_category_text, event_time_text, active_members
def search_active_member(link):
try:
url = f"https://www.hinatazaka46.com{link}"
result = requests.get(url)
soup = BeautifulSoup(result.content, features="lxml")
active_members = soup.find("div", {"class": "c-article__tag"}).text
time.sleep(3) # NOTE:Éliminez la charge du serveur
except AttributeError:
active_members = ""
return active_members
def remove_blank(text):
text = text.replace("\n", "")
text = text.replace(" ", "")
return text
** [Ajout] ** Dans la version du 14/10/2020, il n'était pas possible d'acquérir correctement autre chose que des événements liés aux médias. Par conséquent, modifiez-le comme suit. (Dans le code ci-dessus, c'est déjà reflété.)
** (avant correction) **
events_category = event_each_date.find_all(
"div", {"class": "c-schedule__category category_media"}
)
event_category_text = remove_blank(event_category.text)
(Modifié)
events_category = event_each_date.find_all("div", {"class": "p-schedule__head"},)
event_category_text = remove_blank(event_category.contents[1].text)
Désormais, les événements tels que "Anniversaire" et "EN DIRECT" peuvent être correctement reflétés dans le calendrier.
Surtout en ce qui concerne le temps, selon la notation ――C'est le lendemain, comme "24: 20 ~ 25: 00"
def over24Hdatetime(year, month, day, times):
"""
Convertir le temps sur 24H en datetime
"""
hour, minute = times.split(":")[:-1]
# to minute
minutes = int(hour) * 60 + int(minute)
dt = datetime.datetime(year=int(year), month=int(month), day=int(day))
dt += datetime.timedelta(minutes=minutes)
return dt.strftime("%Y-%m-%dT%H:%M:%S")
def prepare_info_for_calendar(
event_name_text, event_category_text, event_time_text, active_members
):
event_title = f"({event_category_text}){event_name_text}"
if event_time_text == "":
event_start = f"{year}-{month}-{event_date_text}"
event_end = f"{year}-{month}-{event_date_text}"
is_date = True
else:
start, end = search_start_and_end_time(event_time_text)
event_start = over24Hdatetime(year, month, event_date_text, start)
event_end = over24Hdatetime(year, month, event_date_text, end)
is_date = False
return event_title, event_start, event_end, is_date
La procédure générale est la suivante.
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
def build_calendar_api():
SCOPES = ["https://www.googleapis.com/auth/calendar"]
creds = None
if os.path.exists("token.pickle"):
with open("token.pickle", "rb") as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file("credentials.json", SCOPES)
creds = flow.run_local_server(port=0)
with open("token.pickle", "wb") as token:
pickle.dump(creds, token)
service = build("calendar", "v3", credentials=creds)
return service
Avant d'ajouter, vérifiez en vous basant sur "Event Name-Time" pour déterminer "s'il s'agit d'un événement précédemment ajouté". Obtenez la liste pour cela avec la fonction search_events.
def search_events(service, calendar_id, start):
end_datetime = datetime.datetime.strptime(start, "%Y-%m-%d") + relativedelta(
months=1
)
end = end_datetime.strftime("%Y-%m-%d")
events_result = (
service.events()
.list(
calendarId=calendar_id,
timeMin=start + "T00:00:00+09:00", # NOTE:+09:Il est important de le mettre à 00. (Convertir UTC en JST)
timeMax=end + "T23:59:00+09:00", # NOTE;Période de recherche jusqu'au mois prochain.
)
.execute()
)
events = events_result.get("items", [])
if not events:
return []
else:
events_starttime = change_event_starttime_to_jst(events)
return [
event["summary"] + "-" + event_starttime
for event, event_starttime in zip(events, events_starttime)
]
def change_event_starttime_to_jst(events):
events_starttime = []
for event in events:
if "date" in event["start"].keys():
events_starttime.append(event["start"]["date"])
else:
str_event_uct_time = event["start"]["dateTime"]
event_jst_time = datetime.datetime.strptime(
str_event_uct_time, "%Y-%m-%dT%H:%M:%S+09:00"
)
str_event_jst_time = event_jst_time.strftime("%Y-%m-%dT%H:%M:%S")
events_starttime.append(str_event_jst_time)
return events_starttime
def add_date_schedule(
event_name, event_category, event_time, event_link, previous_add_event_lists
):
(
event_name_text,
event_category_text,
event_time_text,
active_members,
) = search_detail_info(event_name, event_category, event_time, event_link)
#Préparation des informations à refléter dans le calendrier
(event_title, event_start, event_end, is_date,) = prepare_info_for_calendar(
event_name_text, event_category_text, event_time_text, active_members,
)
if (
f"{event_title}-{event_start}" in previous_add_event_lists
): # NOTE:Passer si le même rendez-vous existe déjà
pass
else:
add_info_to_calendar(
calendarId, event_title, event_start, event_end, active_members, is_date,
)
def add_info_to_calendar(calendarId, summary, start, end, active_members, is_date):
if is_date:
event = {
"summary": summary,
"description": active_members,
"start": {"date": start, "timeZone": "Japan",},
"end": {"date": end, "timeZone": "Japan",},
}
else:
event = {
"summary": summary,
"description": active_members,
"start": {"dateTime": start, "timeZone": "Japan",},
"end": {"dateTime": end, "timeZone": "Japan",},
}
event = service.events().insert(calendarId=calendarId, body=event,).execute()
Cette fois, j'essaie de refléter le calendrier de ce mois à 3 mois à l'avance dans Google Agenda. Seul calendarId doit définir l'identifiant de mon calendrier.
import time
import pickle
import os.path
import requests
from bs4 import BeautifulSoup
import datetime
from dateutil.relativedelta import relativedelta
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
def build_calendar_api():
SCOPES = ["https://www.googleapis.com/auth/calendar"]
creds = None
if os.path.exists("token.pickle"):
with open("token.pickle", "rb") as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file("credentials.json", SCOPES)
creds = flow.run_local_server(port=0)
with open("token.pickle", "wb") as token:
pickle.dump(creds, token)
service = build("calendar", "v3", credentials=creds)
return service
def remove_blank(text):
text = text.replace("\n", "")
text = text.replace(" ", "")
return text
def search_event_each_date(year, month):
url = (
f"https://www.hinatazaka46.com/s/official/media/list?ima=0000&dy={year}{month}"
)
result = requests.get(url)
soup = BeautifulSoup(result.content, features="lxml")
events_each_date = soup.find_all("div", {"class": "p-schedule__list-group"})
time.sleep(3) # NOTE:Éliminez la charge sur le serveur
return events_each_date
def search_start_and_end_time(event_time_text):
has_end = event_time_text[-1] != "~"
if has_end:
start, end = event_time_text.split("~")
else:
start = event_time_text.split("~")[0]
end = start
start += ":00"
end += ":00"
return start, end
def search_event_info(event_each_date):
event_date_text = remove_blank(event_each_date.contents[1].text)[
:-1
] # NOTE:Obtenez des informations autres que le jour
events_time = event_each_date.find_all("div", {"class": "c-schedule__time--list"})
events_name = event_each_date.find_all("p", {"class": "c-schedule__text"})
events_category = event_each_date.find_all("div", {"class": "p-schedule__head"},)
events_link = event_each_date.find_all("li", {"class": "p-schedule__item"})
return event_date_text, events_time, events_name, events_category, events_link
def search_detail_info(event_name, event_category, event_time, event_link):
event_name_text = remove_blank(event_name.text)
event_category_text = remove_blank(event_category.contents[1].text)
event_time_text = remove_blank(event_time.text)
event_link = event_link.find("a")["href"]
active_members = search_active_member(event_link)
return event_name_text, event_category_text, event_time_text, active_members
def search_active_member(link):
try:
url = f"https://www.hinatazaka46.com{link}"
result = requests.get(url)
soup = BeautifulSoup(result.content, features="lxml")
active_members = soup.find("div", {"class": "c-article__tag"}).text
time.sleep(3) # NOTE:Élimine la charge du serveur
except AttributeError:
active_members = ""
return active_members
def over24Hdatetime(year, month, day, times):
"""
Convertir le temps sur 24H en datetime
"""
hour, minute = times.split(":")[:-1]
# to minute
minutes = int(hour) * 60 + int(minute)
dt = datetime.datetime(year=int(year), month=int(month), day=int(day))
dt += datetime.timedelta(minutes=minutes)
return dt.strftime("%Y-%m-%dT%H:%M:%S")
def prepare_info_for_calendar(
event_name_text, event_category_text, event_time_text, active_members
):
event_title = f"({event_category_text}){event_name_text}"
if event_time_text == "":
event_start = f"{year}-{month}-{event_date_text}"
event_end = f"{year}-{month}-{event_date_text}"
is_date = True
else:
start, end = search_start_and_end_time(event_time_text)
event_start = over24Hdatetime(year, month, event_date_text, start)
event_end = over24Hdatetime(year, month, event_date_text, end)
is_date = False
return event_title, event_start, event_end, is_date
def change_event_starttime_to_jst(events):
events_starttime = []
for event in events:
if "date" in event["start"].keys():
events_starttime.append(event["start"]["date"])
else:
str_event_uct_time = event["start"]["dateTime"]
event_jst_time = datetime.datetime.strptime(
str_event_uct_time, "%Y-%m-%dT%H:%M:%S+09:00"
)
str_event_jst_time = event_jst_time.strftime("%Y-%m-%dT%H:%M:%S")
events_starttime.append(str_event_jst_time)
return events_starttime
def search_events(service, calendar_id, start):
end_datetime = datetime.datetime.strptime(start, "%Y-%m-%d") + relativedelta(
months=1
)
end = end_datetime.strftime("%Y-%m-%d")
events_result = (
service.events()
.list(
calendarId=calendar_id,
timeMin=start + "T00:00:00+09:00", # NOTE:+09:Il est important de le mettre à 00. (Convertir UTC en JST)
timeMax=end + "T23:59:00+09:00", # NOTE;Période de recherche jusqu'au mois prochain.
)
.execute()
)
events = events_result.get("items", [])
if not events:
return []
else:
events_starttime = change_event_starttime_to_jst(events)
return [
event["summary"] + "-" + event_starttime
for event, event_starttime in zip(events, events_starttime)
]
def add_date_schedule(
event_name, event_category, event_time, event_link, previous_add_event_lists
):
(
event_name_text,
event_category_text,
event_time_text,
active_members,
) = search_detail_info(event_name, event_category, event_time, event_link)
#Préparation des informations à refléter dans le calendrier
(event_title, event_start, event_end, is_date,) = prepare_info_for_calendar(
event_name_text, event_category_text, event_time_text, active_members,
)
if (
f"{event_title}-{event_start}" in previous_add_event_lists
): # NOTE:Passer si le même rendez-vous existe déjà
pass
else:
add_info_to_calendar(
calendarId, event_title, event_start, event_end, active_members, is_date,
)
def add_info_to_calendar(calendarId, summary, start, end, active_members, is_date):
if is_date:
event = {
"summary": summary,
"description": active_members,
"start": {"date": start, "timeZone": "Japan",},
"end": {"date": end, "timeZone": "Japan",},
}
else:
event = {
"summary": summary,
"description": active_members,
"start": {"dateTime": start, "timeZone": "Japan",},
"end": {"dateTime": end, "timeZone": "Japan",},
}
event = service.events().insert(calendarId=calendarId, body=event,).execute()
if __name__ == "__main__":
# -------------------------step1:divers paramètres-------------------------
#Système API
calendarId = (
"〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜" # NOTE:Mon identifiant de calendrier
)
service = build_calendar_api()
#Gamme de recherche
num_search_month = 3 # NOTE;Reflété dans le calendrier jusqu'à l'horaire 3 mois à l'avance
current_search_date = datetime.datetime.now()
year = current_search_date.year
month = current_search_date.month
# -------------------------step2.Obtenez des informations pour chaque date-------------------------
for _ in range(num_search_month):
events_each_date = search_event_each_date(year, month)
for event_each_date in events_each_date:
# step3:Obtenez les horaires pour un jour spécifique à la fois
(
event_date_text,
events_time,
events_name,
events_category,
events_link,
) = search_event_info(event_each_date)
event_date_text = "{:0=2}".format(
int(event_date_text)
) # NOTE;Remplissez avec 0 pour qu'il devienne 2 chiffres (ex.0-> 01)
start = f"{year}-{month}-{event_date_text}"
previous_add_event_lists = search_events(service, calendarId, start)
# step4:Ajouter des informations au calendrier
for event_name, event_category, event_time, event_link in zip(
events_name, events_category, events_time, events_link
):
add_date_schedule(
event_name,
event_category,
event_time,
event_link,
previous_add_event_lists,
)
# step5:Au mois suivant
current_search_date = current_search_date + relativedelta(months=1)
year = current_search_date.year
month = current_search_date.month
Dans cet article, j'ai présenté comment refléter le calendrier de Hinatazaka 46 dans Google Agenda. Cette volonté
Cette fois, nous nous sommes concentrés sur Hinatazaka 46, mais si vous modifiez "(1) Récupération des informations nécessaires auprès de HP", vous pouvez réutiliser (2) et refléter le calendrier de toute personne dans Google Agenda.
━━━━━━━━━━
Si vous ne connaissez pas Hinatazaka 46, pourquoi ne vous intéressez-vous pas à cela? Personnellement, "Rendez-vous à Hinatazaka", qui est diffusé sur TV Tokyo tous les dimanches à partir de 25h05. ** est recommandé. Vous serez étonné et attiré par la grande variété de capacités que vous ne pouvez pas considérer comme une idole. De plus, je pense qu'il est bon de savoir à partir de la chanson sur Hyugazaka 46 OFFICIAL YouTube CHANNEL.
En passant, ma récente recommandation est M. Yoshika Matsuda, qui a un très beau sourire. Ce qui est bon?
Comment extraire des événements arbitraires dans Google Agenda avec Python
Ajout d'un événement à Google Agenda avec Python
[Python] Obtenir / ajouter des rendez-vous Google Agenda à l'aide de l'API Google Agenda
━━━━━━━━━━ Page d'accueil de Hyugazaka46