ساخت ربات تلگرام با پایتون و BigQuery گوگل برای خودکارسازی کارها — به زبان ساده
برخی از ما با وظایف تکراری سر و کار داریم و کار خاصی را باید هر هفته و یا هر روز انجام دهیم یا گزارشی هست که باید به صورت روزانه یا هفتگی به انجام برسد. برای نمونه باید یک کوئری داده بزنیم یا برخی کارهای بصریسازی انجام داده و به مافوق خود گزارش دهیم. اما چه میشود اگر این کارها را به جای این که دستی انجام دهیم، خودکار سازی کنیم و از شر این کارهای تکراری خستهکننده راحت شویم؟
بدین ترتیب میتوانیم از این زمان آزاد شده برای انجام کارهای بهتر استفاده کنیم. در این راهنما قصد داریم یک ربات تلگرام بسازیم که به خودکارسازی بخش عمدهای از کارهای خستهکننده یعنی گزارشدهی میپردازد. و همه این مزیتها را با نوشتن کمتر از 50 خط کد به دست خواهیم آورد!
اگر نخستین باری است که میخواهید یک ربات تلگرام بسازید، پیشنهاد میکنیم ابتدا از آموزش زیر استفاده کنید:
در ادامه مراحل ساخت یک ربات تلگرام با پایتون برای منظوری که در بالا شرح داده شد را به صورت گام به گام شرح میدهیم.
نصب کتابخانهها
ما قصد داریم از google-cloud-bigquery (+) برای کوئری زدن به دادههای موجود در BigQuery گوگل استفاده کنیم. همچنین کتابخانههای matplotlib ،numpy و pandas به ما کمک میکنند که دادههای خود را به صورت بصری ارائه کنیم. کتابخانه python-telegram-bot (+) تصاویر بصریسازی شده را در گفتگوهای تلگرام ارسال میکند.
pip3 install google-cloud-bigquery matplotlib numpy pandas python-telegram-bot
فعالسازی API BigQuery گوگل
برای استفاده از خدمات BigQuery گوگل ابتدا API آن را فعال کنیم. به این منظور به کنسول توسعهدهندگان گوگل (+) بروید و یک پروژه جدید بسازید. البته میتوانید در صورت تمایل از پروژههای موجود نیز استفاده کنید.
در بخش داشبورد پروژه روی گزینه ENABLE APIS AND SERVICES کلیک کنید و به دنبال API BigQuery بگردید.
روی گزینه Enable کلیک کنید تا API مورد نظر فعال شود.
ایجاد کلید حساب سرویس
اگر میخواهید از سرویسهای کلود گوگل مانند BigQuery گوگل استفاده کنید، باید از کلید حساب سرویس بهره بگیرید. در واقع این کلید همانند رمز عبور اتصال ما به سرویسهای گوگل عمل میکند. به کنسول توسعهدهندگان گوگل بروید و روی برگه Credentials کلیک کنید. گزینه Create Credentials را انتخاب کرده و روی Service Account Key کلیک کنید. گزینه New Service Account را انتخاب کرده و در فیلد Service Account Name یک نام وارد کنید. در لیست بازشدنی Role گزینه Project > Owner را انتخاب کرده و گزینه Create را بزنید.
این یک فایل json. است که به صورت خودکار دانلود خواهد شد. نام آن را creds.json بگذارید. در ترمینال مقدار گزینه GOOGLE_APPLICATION_CREDENTIALS را به صورت مسیر فایل creds.json تعیین کنید.
export GOOGLE_APPLICATION_CREDENTIALS='[PATH_TO_CREDS.JSON]'
اینک همه چیز آماده است و نوبت آن رسیده که برنامه خود را بنویسیم.
نوشتن برنامه
ما قصد داریم برنامهای بنویسیم که دادهها را از BigQuery کوئری بکند (البته فرض ما این است که دادهها در آنجا ذخیره شدهاند). سپس دادهها را بصریسازی کرده و در قالب یک تصویر ذخیره میکنیم. در ادامه این تصویر از طریق یک گفتگوی تلگرامی ارسال میشود.
ما در این راهنما از مجموعه داده bigquery-public-data.stackoverflow استفاده کردهایم و قصد داریم دادههای کل پستهای روزانه گزارش خود را بصریسازی کنیم. گردش کار برنامه کاملاً آسان است:
Query the table -> Visualize the data -> Save the visualization -> Send the image
برای تعریف هر گام یک تابع تعریف میکنیم.
کوئری به BigQuery
ابتدا کتابخانه را ایمپورت کنید:
from google.cloud import bigquery
تابعی به نام query_to_bigquery ایجاد کنید که یک query به عنوان پارامتر میگیرد.
1def query_to_bigquery(query):
2 client = bigquery.Client()
3 query_job = client.query(query)
4 result = query_job.result()
5 dataframe = result.to_dataframe()
6 return dataframe
این تابع دادهها را به صورت یک dataframe بازگشت میدهد.
بصریسازی دادهها
قصد داریم از کتابخانه matplotlib برای بصریسازی دادهها استفاده کنیم.
import matplotlib.pyplot as plt
ما پنج پارامتر میگیریم که به صورت زیر هستند:
- x به عنوان دادههای محور x
- x_label به عنوان نام برچسب محور x
- y به عنوان دادههای محور y
- y_label به عنوان نام محور y
- و title که عنوان نمودار بصریسازی ما است.
1def visualize_bar_chart(x, x_label, y, y_label, title):
2 plt.title(title)
3 plt.xlabel(x_label)
4 plt.ylabel(y_label)
5 index = np.arange(len(x))
6 plt.xticks(index, x, fontsize=5, rotation=30)
7 plt.bar(index, y)
8 return plt
ذخیره تصویر
از دو تابع فوق برای ایجاد بصریسازی استفاده میکنیم و سپس تصویر را ذخیره میکنیم. همانطور که قبلاً اشاره کردیم، میخواهیم دادههای پستهای مجموع روزانه را ارسال کنیم. ابتدا کوئری خود را مینویسیم.
1query = """
2 SELECT DATE(creation_date) date, COUNT(*) total_posts
3 FROM `bigquery-public-data.stackoverflow.post_history`
4 GROUP BY 1
5 HAVING date > DATE_SUB('2018-12-02', INTERVAL 14 DAY)
6 ORDER BY 1
7 """
در کوئری فوق دقت کنید که کد زیر به معنی این است که میخواهیم دادههای 14 روز را از تاریخ 02-12-2018 گردآوری کنیم:
HAVING date > DATE_SUB('2018-12-02'، INTERVAL 14 DAY)
دلیل استفاده از این تاریخ آن است که 02-12-2018 آخرین تاریخی است که در مجموعه داده ما به نام bigquery-public-data.stackoverflow.post_history ذخیره شده است. بدیهی است که در موارد مختلف میتوانید از ()CURRENT_DATE استفاده کنید تا جدیدترین دادهها را دریافت کنید. تابع query_to_bigquery را فراخوانی کنید تا دادهها به دست آیند:
dataframe = query_to_bigquery(query)
ستون date را به عنوان دادههای محور x در نظر میگیریم و ستون total_posts نیز محور y را تشکیل میدهد.
x = dataframe['date'].tolist() y = dataframe['total_posts'].tolist()
دادهها با استفاده از تابع visualize_bar_chart بصریسازی میشوند و سپس به صورت یک تصویر ذخیره میشوند.
1plt = visualize_bar_chart(x=x, x_label='Date', y=y, y_label='Total Posts', title='Daily Posts')
2plt.savefig('viz.png')
این کد را درون تابعی به نام get_and_save_image ذخیره میکنیم:
1def get_and_save_image():
2 query = """
3 SELECT DATE(creation_date) date, COUNT(*) total_posts
4 FROM `bigquery-public-data.stackoverflow.post_history`
5 GROUP BY 1
6 HAVING date > DATE_SUB('2018-12-02', INTERVAL 14 DAY)
7 ORDER BY 1
8 """
9 dataframe = query_to_bigquery(query)
10 x = dataframe['date'].tolist()
11 y = dataframe['total_posts'].tolist()
12 plt = visualize_bar_chart(x=x, x_label='Date', y=y, y_label='Total Posts', title='Daily Posts')
13 plt.savefig('viz.png')
ارسال تصویر
برای این که بتوانیم تصویر را به فرد صحیحی ارسال کنیم، باید chat_id وی را بدانیم، زیرا این یکی از پارامترهای الزامی است. بدین منظور به ربات userinfobot (+) مراجعه کرده و عبارت /start را وارد کنید. این ربات اطلاعات کاربر مورد نظر را به همراه chat_id وی که یک عدد در فیلد id است بازگشت میدهد.
تابعی به نام send_image بسازید. این تابع، اقدام به فراخوانی تابع get_and_save_image میکند تا بصریسازی را دریافت و ذخیره کند و سپس آن را به کاربری که chat-id اش در متغیر chat_id اعلان شده ارسال میکند.
1def send_image(bot, update):
2 get_and_save_image()
3 chat_id = 'CHAT_ID_RECEIVER'
4 bot.send_photo(chat_id=chat_id, photo=open('viz.png','rb'))
برنامه اصلی
در نهایت تابع دیگری میسازیم که main نام دارد و برنامه خود را به وسیله آن اجرا میکنیم. دقت کنید که باید مقدار YOUR_TOKEN را با توکن ربات خود عوض کنید.
همچنین به خاطر داشته باشید که این برنامه تصویر را به صورت خودکار بر مبنای تاریخ و ساعتی که تعریف کردهاید ارسال میکند. برای نمونه در این راهنما ما تاریخ ارسال را به صورت «هر روز ساعت 9:00 قبل از ظهر» تعیین کردهایم.
1def main():
2 updater = Updater('YOUR_TOKEN')
3 updater.job_queue.run_daily(send_image, time=datetime.datetime.strptime('9:00AM', '%I:%M%p').time(), days=(0,1,2,3,4,5,6))
4 updater.start_polling()
5 updater.idle()
6if __name__ == '__main__':
7 main()
در انتها کد شما باید مانند زیر باشد:
1from google.cloud import bigquery
2from telegram.ext import Updater
3
4import matplotlib.pyplot as plt
5import numpy as np
6import datetime
7
8def query_to_bigquery(query):
9 client = bigquery.Client()
10 query_job = client.query(query)
11 result = query_job.result()
12 dataframe = result.to_dataframe()
13 return dataframe
14
15def visualize_bar_chart(x, x_label, y, y_label, title):
16 plt.title(title)
17 plt.xlabel(x_label)
18 plt.ylabel(y_label)
19 index = np.arange(len(x))
20 plt.xticks(index, x, fontsize=5, rotation=30)
21 plt.bar(index, y)
22 return plt
23
24def get_and_save_image():
25 query = """
26 SELECT DATE(creation_date) date, COUNT(*) total_posts
27 FROM `bigquery-public-data.stackoverflow.post_history`
28 GROUP BY 1
29 HAVING date > DATE_SUB('2018-12-02', INTERVAL 14 DAY)
30 ORDER BY 1
31 """
32 dataframe = query_to_bigquery(query)
33 x = dataframe['date'].tolist()
34 y = dataframe['total_posts'].tolist()
35 plt = visualize_bar_chart(x=x, x_label='Date', y=y, y_label='Total Posts', title='Daily Posts')
36 plt.savefig('viz.png')
37
38def send_image(bot, update):
39 get_and_save_image()
40 chat_id = 'CHAT_ID_RECEIVER'
41 bot.send_photo(chat_id=chat_id, photo=open('viz.png', 'rb'))
42
43def main():
44 updater = Updater('YOUR_TOKEN')
45 updater.job_queue.run_daily(send_image, time=datetime.datetime.strptime('9:00AM', '%I:%M%p').time(), days=(0,1,2,3,4,5,6))
46 updater.start_polling()
47 updater.idle()
48
49if __name__ == '__main__':
50 main()
فایل را ذخیره کرده و نام آن را به صورت main.py تعیین کنید. برنامه را با وارد کردن دستور زیر در ترمینال اجرا کنید:
python3 main.py
اینک ما یک ربات تولیدکننده گزارش داریم که آن را با 50 خط کدنویسی ساختهایم و این بسیار شگفتانگیز است. در تصویر زیر نمونهای از بصریسازی که از سوی این ربات ارسال شده را میبینید. اینک میتوانید راحت بنشینید و با آرامش منتظر رباتی بمانید که گزارشها را به صورت روزمره ارسال میکند.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای ساخت ربات تلگرام (Telegram)
- مجموعه آموزشهای برنامهنویسی
- آموزش ساخت ربات تلگرام با پایتون (Python)
- ساخت رباتهای تلگرام – مقالات پروژه محور وبلاگ فرادرس
- ساخت ربات تلگرام با قابلیت ترجمه متن در سه مرحله — به زبان ساده
==