تمرین و پروژه‌های پایتون

ساخت ربات با پایتون؛ ربات تلگرام، اتوماسیون کارها و کار با API

ساخت ربات با پایتون برای تلگرام، اتوماسیون و API

🗓 آخرین به‌روزرسانی:

«ربات» در برنامه‌نویسی یعنی برنامه‌ای که بدون دخالت مستقیم شما کاری را انجام می‌دهد: به پیام‌ها جواب می‌دهد، فایل‌ها را مرتب می‌کند، از یک سرویس داده می‌گیرد یا هر روز ساعت هشت صبح گزارشی می‌فرستد. پایتون به خاطر سادگی و کتابخانه‌های فراوان، یکی از بهترین زبان‌ها برای ساخت این ربات‌هاست. در این آموزش سه نوع ربات را می‌سازیم: ربات اتوماسیون فایل‌ها، ربات کار با API و ربات تلگرام؛ و در پایان یاد می‌گیریم چطور آن‌ها را خودکار و امن اجرا کنیم.

نمونه‌کدها با پایتون 3.13.5، requests 2.34.2 و python-telegram-bot 22.8 اجرا یا آزموده شده‌اند. خروجی هر بخش، خروجی واقعی همان اجراست.

پیش‌نیازها

python -m pip install requests python-telegram-bot

بخش ۱: ربات اتوماسیون؛ کارهای تکراری را به پایتون بسپارید

ساده‌ترین ربات‌ها اصلاً به اینترنت نیاز ندارند. فرض کنید هر هفته ده‌ها فایل گزارش با نام‌های نامرتب دریافت می‌کنید و باید آن‌ها را بر اساس تاریخ تغییر نام دهید و یک فهرست خلاصه بسازید. کد زیر چند فایل نمونه می‌سازد، آن‌ها را با الگوی یکسان تغییر نام می‌دهد و خلاصه را چاپ می‌کند. ماژول pathlib کار با مسیرها را روی همه سیستم‌عامل‌ها یکسان می‌کند:

from pathlib import Path
from datetime import date

inbox = Path("reports")
inbox.mkdir(exist_ok=True)
for name in ["Report final.TXT", "report (2).txt", "REPORT-new.txt"]:
    (inbox / name).write_text("sales: 100\n")

today = date(2026, 10, 15).isoformat()
for i, f in enumerate(sorted(inbox.glob("*.[tT][xX][tT]")), start=1):
    new = inbox / f"report_{today}_{i:02}.txt"
    f.rename(new)
    print(f"{f.name:20} -> {new.name}")
print("files now:", len(list(inbox.iterdir())))

خروجی:

REPORT-new.txt       -> report_2026-10-15_01.txt
Report final.TXT     -> report_2026-10-15_02.txt
report (2).txt       -> report_2026-10-15_03.txt
files now: 3

همین الگو برای مرتب کردن پوشه دانلود، پشتیبان‌گیری از فایل‌های مهم و تبدیل گروهی فایل‌ها هم کار می‌کند. پروژه کامل‌تر این ایده را در مرتب‌سازی خودکار فایل‌ها با پایتون نوشته‌ایم. همیشه پیش از اجرای اسکریپتی که فایل جابه‌جا یا حذف می‌کند، آن را روی یک پوشه آزمایشی امتحان کنید.

ساخت گزارش خودکار از داده

بخش دوم بسیاری از ربات‌های اتوماسیون، خلاصه کردن داده و ساختن گزارش است. کد زیر از یک فهرست سفارش، مجموع فروش هر محصول را حساب می‌کند و گزارش را در یک فایل CSV می‌نویسد؛ فایلی که با اکسل هم باز می‌شود:

import csv
from collections import defaultdict

orders = [("book", 2, 150), ("pen", 10, 12), ("book", 1, 150), ("bag", 1, 480)]
totals = defaultdict(int)
for item, qty, price in orders:
    totals[item] += qty * price

with open("summary.csv", "w", newline="") as f:
    w = csv.writer(f)
    w.writerow(["item", "total"])
    for item, total in sorted(totals.items(), key=lambda x: -x[1]):
        w.writerow([item, total])

print(open("summary.csv").read())

خروجی:

item,total
bag,480
book,450
pen,120

بخش ۲: ربات کار با API

API رابطی است که یک سرویس برای برنامه‌ها فراهم می‌کند تا داده بگیرند یا کاری انجام دهند. بیشتر APIهای امروزی با درخواست HTTP کار می‌کنند و پاسخ را در قالب JSON برمی‌گردانند. کتابخانه requests فرستادن این درخواست‌ها را ساده می‌کند. در مثال زیر از API عمومی GitHub اطلاعات مخزن رسمی پایتون را می‌گیریم. چون عددها زنده‌اند، اگر کد را اجرا کنید مقدار متفاوتی می‌بینید:

import requests

url = "https://api.github.com/repos/python/cpython"
try:
    r = requests.get(url, timeout=10, headers={"Accept": "application/vnd.github+json"})
    r.raise_for_status()
    data = r.json()
    print("repo:", data["full_name"])
    print("default branch:", data["default_branch"])
    print("language:", data["language"])
    print("stars > 50k:", data["stargazers_count"] > 50_000)
except requests.RequestException as e:
    print("request failed:", e)

خروجی:

repo: python/cpython
default branch: main
language: Python
stars > 50k: True

نکته‌های مهم کار با API

  • همیشه timeout بگذارید. بدون آن، اگر سرور جواب ندهد برنامه شما تا ابد منتظر می‌ماند.
  • کد وضعیت را بررسی کنید. raise_for_status() برای خطاهای 4xx و 5xx استثنا ایجاد می‌کند.
  • به محدودیت نرخ (Rate Limit) احترام بگذارید. بیشتر APIها تعداد درخواست در ساعت را محدود می‌کنند؛ بین درخواست‌ها فاصله بگذارید و نتیجه را ذخیره کنید.
  • کلید API را در کد ننویسید. از متغیر محیطی یا فایل تنظیمات خارج از مخزن کد استفاده کنید.

پاسخ JSON در پایتون به دیکشنری و لیست تبدیل می‌شود؛ برای کار با آن آموزش کار با JSON در پایتون را ببینید. اگر هنگام خواندن کلیدی که وجود ندارد خطا گرفتید، رفع KeyError و استفاده از data.get("key") را ببینید.

تلاش دوباره هوشمند

شبکه همیشه پایدار نیست. ربات خوب وقتی درخواستی شکست خورد، چند بار با فاصله‌ای که هر بار بیشتر می‌شود دوباره تلاش می‌کند. تابع زیر این منطق را پیاده می‌کند؛ برای آزمودن، یک تابع ساختگی به آن داده‌ایم که دو بار اول شکست می‌خورد:

import time

def with_retry(fn, tries=4, base=0.1):
    for attempt in range(1, tries + 1):
        try:
            return fn()
        except ConnectionError as e:
            wait = base * 2 ** (attempt - 1)
            print(f"attempt {attempt} failed ({e}); waiting {wait:.1f}s")
            time.sleep(wait)
    raise RuntimeError("all retries failed")

calls = {"n": 0}
def flaky():
    calls["n"] += 1
    if calls["n"] < 3:
        raise ConnectionError("timeout")
    return "ok"

print("result:", with_retry(flaky))

خروجی:

attempt 1 failed (timeout); waiting 0.1s
attempt 2 failed (timeout); waiting 0.2s
result: ok

بخش ۳: ربات تلگرام با پایتون

گرفتن توکن از BotFather

  1. در تلگرام حساب رسمی @BotFather را باز کنید و دستور /newbot را بفرستید.
  2. نام نمایشی و نام کاربری ربات را (که باید به bot ختم شود) وارد کنید.
  3. BotFather یک توکن می‌دهد. این توکن مثل رمز عبور است؛ آن را در هیچ کد عمومی، اسکرین‌شات یا گروهی منتشر نکنید.

کد ربات

این ربات به سلام جواب می‌دهد و اگر عدد بفرستید، مربع آن را برمی‌گرداند. منطق پاسخ را عمداً در تابع جداگانه reply_for نوشته‌ایم تا بدون اتصال به تلگرام قابل‌آزمایش باشد. فایل را با نام bot.py ذخیره کنید:

import os
from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, ContextTypes, filters


def reply_for(text: str) -> str:
    """Pure logic: easy to test without Telegram."""
    t = text.strip().lower()
    if t in ("hi", "hello", "salam"):
        return "Hello! Send me a number and I will square it."
    if t.lstrip("-").isdigit():
        n = int(t)
        return f"{n} squared is {n * n}"
    return "I only understand greetings and whole numbers."


async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("Welcome! Type hi or a number.")


async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text(reply_for(update.message.text))


def main():
    token = os.environ["BOT_TOKEN"]  # never hard-code the token
    app = Application.builder().token(token).build()
    app.add_handler(CommandHandler("start", start))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))
    app.run_polling()


if __name__ == "__main__":
    main()

برای اجرا، توکن را در متغیر محیطی قرار دهید و فایل را اجرا کنید:

# Linux / macOS
export BOT_TOKEN="123456:ABC..."
python bot.py

# Windows PowerShell
$env:BOT_TOKEN="123456:ABC..."
python bot.py

آزمودن منطق ربات بدون تلگرام

پیش از اتصال به تلگرام، منطق را تست کنید. این کد فایل ربات را وارد می‌کند (بدون اجرای main) و تابع پاسخ را با چند ورودی امتحان می‌کند:

import bot

for msg in ["hi", "12", "-3", "what?"]:
    print(f"{msg!r:8} -> {bot.reply_for(msg)}")

خروجی:

'hi'     -> Hello! Send me a number and I will square it.
'12'     -> 12 squared is 144
'-3'     -> -3 squared is 9
'what?'  -> I only understand greetings and whole numbers.

run_polling مدام از تلگرام می‌پرسد پیام جدیدی آمده یا نه؛ ساده است و برای شروع عالی. در پروژه‌های بزرگ‌تر از روش Webhook استفاده می‌شود که در آن تلگرام پیام‌ها را به آدرس سرور شما می‌فرستد. اگر سرور یا شبکه شما به سرورهای تلگرام دسترسی پایدار ندارد، ربات را روی سروری اجرا کنید که این دسترسی را دارد.

معماری یک ربات خوب

ربات‌های کوچک معمولاً در یک فایل شروع می‌شوند و کم‌کم بزرگ و درهم می‌شوند. از همان ابتدا سه بخش را از هم جدا نگه دارید تا کد قابل‌نگهداری بماند. بخش اول «منطق» است: تابع‌هایی که ورودی می‌گیرند و خروجی برمی‌گردانند و هیچ اطلاعی از تلگرام یا فایل ندارند، مثل reply_for در مثال بالا. بخش دوم «اتصال» است: کدی که با تلگرام، API یا سیستم فایل صحبت می‌کند. بخش سوم «تنظیمات» است: توکن، آدرس‌ها، زمان‌بندی و مسیرها که از متغیر محیطی یا فایل تنظیمات خوانده می‌شوند.

مزیت این تفکیک این است که منطق را می‌توانید بدون اینترنت و در چند میلی‌ثانیه تست کنید، اگر روزی خواستید از تلگرام به پیام‌رسان دیگری مهاجرت کنید فقط بخش اتصال عوض می‌شود، و انتقال ربات به سرور جدید فقط تغییر تنظیمات است. وقتی ربات بزرگ‌تر شد، هر بخش را در فایل جداگانه بگذارید؛ آموزش ماژول و پکیج این کار را توضیح می‌دهد.

یک نکته عملی دیگر: پیش از نوشتن هر ربات، کار را یک بار دستی و قدم‌به‌قدم انجام دهید و مراحل را یادداشت کنید. هر مرحله تقریباً به یک تابع در کد تبدیل می‌شود. اگر نتوانید مراحل را روشن بنویسید، احتمالاً هنوز مسئله را کامل نفهمیده‌اید و بهتر است قبل از کدنویسی آن را دقیق‌تر کنید.

برای یک مثال کامل از کار با API، آموزش برنامه هواشناسی با پایتون را ببینید که داده دمای فعلی و پیش‌بینی چندروزه را از یک API رایگان می‌گیرد و خطاهای شبکه را هم مدیریت می‌کند.

ایده‌های ربات برای تمرین

  • ربات یادآور که فهرست کارهای روزانه را از یک فایل بخواند و صبح‌ها برایتان بفرستد؛ ایده اولیه را از پروژه لیست کارها بگیرید.
  • ربات قیمت که هر ساعت از یک API عمومی نرخ ارز یا آب‌وهوا بگیرد و اگر از حد مشخصی عبور کرد خبر بدهد.
  • ربات پشتیبان‌گیری که هر شب پوشه پروژه‌ها را فشرده کند و نسخه‌های قدیمی‌تر از سی روز را پاک کند.
  • ربات آزمون تلگرامی که سؤال بپرسد و امتیاز بدهد؛ منطقش شبیه بازی کوییز است.
  • ربات گزارش فروش که هر هفته فایل CSV سفارش‌ها را خلاصه و نمودار آن را ذخیره کند.

اجرای خودکار و زمان‌بندی‌شده

ربات اتوماسیون وقتی واقعاً مفید است که خودش در زمان مشخص اجرا شود. سه روش رایج:

  • لینوکس و سرور: با crontab -e خطی مثل 0 8 * * * /path/env/bin/python /path/report.py اضافه کنید تا هر روز ساعت ۸ اجرا شود.
  • ویندوز: از Task Scheduler یک وظیفه بسازید که مفسر داخل محیط مجازی را با مسیر اسکریپت اجرا کند.
  • داخل خود پایتون: برای کارهای ساده، یک حلقه با time.sleep کافی است، اما اگر برنامه بسته شود زمان‌بندی هم از بین می‌رود.

اگر ربات شما خطا داد و کسی پای سیستم نبود، چطور بفهمید؟ همیشه خروجی و خطاها را در فایل لاگ بنویسید. ماژول داخلی logging این کار را با زمان دقیق هر پیام انجام می‌دهد:

import logging

logging.basicConfig(filename="bot.log", level=logging.INFO,
                    format="%(levelname)s %(message)s")
logging.info("report generated: 3 items")
logging.warning("api slow: 4.2s")
print(open("bot.log").read())

خروجی:

INFO report generated: 3 items
WARNING api slow: 4.2s

نکات امنیتی و اخلاقی

  • توکن‌ها و رمزها را در متغیر محیطی یا فایل .env نگه دارید و آن فایل را در .gitignore بگذارید.
  • اگر توکن ربات لو رفت، فوراً از BotFather با دستور /revoke آن را باطل کنید.
  • پیش از استخراج داده از سایت‌ها، قوانین استفاده و فایل robots.txt آن سایت را بررسی کنید و با درخواست‌های پشت‌سرهم به سرور فشار نیاورید.
  • ربات نباید برای ارسال پیام انبوه ناخواسته (اسپم) یا جمع‌آوری اطلاعات شخصی بدون اجازه استفاده شود.

📌 همچنین بخوانید: تمرین پایتون با جواب، ساخت بازی با پایتون و Pygame و تشخیص عدد اول و زوج یا فرد در پایتون

سوالات متداول

برای ساخت ربات تلگرام با پایتون چه کتابخانه‌ای مناسب است؟

کتابخانه python-telegram-bot محبوب و مستند است و از نسخه‌های جدید به‌صورت async کار می‌کند. گزینه‌های دیگری مثل aiogram هم وجود دارد.

آیا برای اجرای ربات به سرور نیاز دارم؟

برای آزمایش، کامپیوتر خودتان کافی است. برای اینکه ربات همیشه روشن باشد، آن را روی یک سرور مجازی یا سرویس میزبانی اجرا کنید.

API چیست و چطور با پایتون از آن استفاده کنم؟

API رابطی است که سرویس‌ها برای تبادل داده با برنامه‌ها فراهم می‌کنند. با کتابخانه requests درخواست بفرستید و پاسخ JSON را با r.json به دیکشنری تبدیل کنید.

توکن ربات را کجا نگه دارم؟

در متغیر محیطی یا فایل .env که در مخزن کد قرار نمی‌گیرد. هرگز توکن را مستقیم در کد یا مخزن عمومی ننویسید.

آموزش‌های مرتبط

آموزش‌های تازه، کد آماده و رفع خطاهر هفته در کانال Dev Source؛ رایگان.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *