Build Your Own Website Watcher with Python: Track Price Changes and News via Telegram

Python tutorial - IT technology blog
Python tutorial - IT technology blog

Why You Should Build Your Own Website Monitoring Tool

I once missed a 3-million VND discount on an iPhone just because I was in a 15-minute meeting and couldn’t refresh the page. That’s when I realized that manually monitoring prices or news is exhausting and discouraging.

Tools like Distill.io or Visualping are great, but free versions usually limit you to under 30 checks per month. To check every 5 minutes, you might pay $15 – $25 monthly. With Python, you can build your own clone, customize ad filtering, and send Telegram messages completely for free.

Many people still use BeautifulSoup for scraping. However, for modern websites using React or Vue, BeautifulSoup often returns a blank HTML shell. That’s why I chose Playwright. This library simulates a real browser, waiting for JavaScript to render before fetching data, making it capable of handling the toughest websites today.

Environment Setup

First, ensure you have Python 3.8+ installed. We’ll need Playwright for web browsing and the requests library to connect with the Telegram API.

# Create a virtual environment to avoid library conflicts
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate

# Install Playwright and requests
pip install playwright requests

# Download Chromium for Playwright (approx. 100-150MB)
playwright install chromium

For Telegram, chat with @BotFather, type /newbot to get your API Token. Don’t forget to send a message to the bot, then visit https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates to find your chat_id.

Detailed Implementation

Our script follows the pattern: Access -> Extract -> Compare -> Notify.

1. Fetching Data with Playwright

Instead of fetching the entire HTML, target a specific Selector (like a price class or title ID). This prevents the script from triggering false alerts due to timestamps or changing ad banners.

import asyncio
from playwright.async_api import async_playwright

async def get_website_content(url, selector):
    async with async_playwright() as p:
        # Run in headless mode (no browser window displayed)
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page()
        
        # Simulate User-Agent to avoid anti-bot detection
        await page.set_extra_http_headers({"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0"})
        
        try:
            await page.goto(url, wait_until="networkidle", timeout=60000)
            await page.wait_for_selector(selector)
            content = await page.inner_text(selector)
            return content.strip()
        except Exception as e:
            print(f"Access error: {e}")
            return None
        finally:
            await browser.close()

2. Checking for Content Changes

The simplest way to detect updates is to save the previous result in a .txt file. If the new content differs from the old, we update the file and trigger a notification.

import os

def has_changed(new_content, filename="last_state.txt"):
    if not os.path.exists(filename):
        with open(filename, "w", encoding="utf-8") as f:
            f.write(new_content)
        return False
    
    with open(filename, "r", encoding="utf-8") as f:
        old_content = f.read()
    
    if new_content != old_content:
        with open(filename, "w", encoding="utf-8") as f:
            f.write(new_content)
        return True
    return False

3. Sending Messages via Telegram

With just a few lines of code using the requests library, you can push notifications directly to your phone.

import requests

def notify_telegram(message, token, chat_id):
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    data = {"chat_id": chat_id, "text": message, "parse_mode": "HTML"}
    return requests.post(url, data=data)

Putting It All Together

Here is the main function to run the entire process. Just replace the URL and Selector with real values to get started.

async def main():
    CONFIG = {
        "url": "https://tiki.vn/dien-thoai-iphone-15-pro-max-p251643444.html",
        "selector": ".price-and-icon",
        "token": "YOUR_TOKEN",
        "chat_id": "YOUR_ID"
    }

    print("Checking website...")
    current_data = await get_website_content(CONFIG["url"], CONFIG["selector"])

    if current_data and has_changed(current_data):
        msg = f"🚀 <b>New Update!</b>\nValue: {current_data}\nLink: {CONFIG['url']}"
        notify_telegram(msg, CONFIG["token"], CONFIG["chat_id"])
        print("Notification sent!")
    else:
        print("No changes found.")

if __name__ == "__main__":
    asyncio.run(main())

Real-world Operating Experience

To keep your script running smoothly without getting your IP banned, keep these 3 points in mind:

  • Check Frequency: Never check every 1-2 seconds. Major sites like Shopee or Amazon will block your IP instantly. A 15-30 minute cycle is usually ideal.
  • Automation: Use crontab if you have a VPS. Otherwise, leverage GitHub Actions to run your script 24/7 for free without needing your personal computer on.
  • Handling Dynamic Classes: Some sites change classes after every build. In these cases, use xpath or stable attributes like data-testid for more accurate element targeting.

Building your own monitoring bot doesn’t just help you snag great deals. It’s also a fantastic way to practice understanding browser workflows and real-world data handling. Good luck!

Share: