Web Scraping & Browser Automation
Web Scraping is the automated extraction of data from websites. While web APIs provide structured JSON endpoints, over 90% of the world's public internet data exists as raw HTML web pages.
Why is Web Scraping Useful?
- Competitive Price Monitoring: Tracking e-commerce product prices and inventory across Amazon, Flipkart, and eBay.
- Financial & Stock Analysis: Extracting quarterly earnings reports, market news, and sentiment indicators.
- Lead Generation & Research: Aggregating job listings, real estate properties, and academic research papers.
The HTML DOM Tree & CSS Selectors:
A web page is structured as a hierarchical DOM (Document Object Model) Tree. BeautifulSoup4 parses raw HTML text into a searchable Python object tree.
# Web Scraping & HTML DOM Parsing Simulation:
from html.parser import HTMLParser
raw_html_mock = """
Mechanical Keyboard
โน2,499.00
In Stock
4K Monitor 27-inch
โน28,999.00
Out of Stock
"""
class SimpleDOMScraper(HTMLParser):
"""Parses HTML mock text into structured product dictionaries."""
def __init__(self):
super().__init__()
self.products = []
self.current_tag = None
self.current_item = {}
def handle_starttag(self, tag, attrs):
self.current_tag = tag
attr_dict = dict(attrs)
if attr_dict.get("class") == "product-card":
self.current_item = {"id": attr_dict.get("data-id")}
def handle_data(self, data):
text = data.strip()
if text:
if self.current_tag == "h2":
self.current_item["title"] = text
elif self.current_tag == "span" and "โน" in text:
self.current_item["price"] = text
elif self.current_tag == "span" and ("Stock" in text):
self.current_item["status"] = text
if "title" in self.current_item:
self.products.append(self.current_item.copy())
# Execute Scraper:
scraper = SimpleDOMScraper()
scraper.feed(raw_html_mock)
print("--- ๐ Scraped Product Catalog Output ---")
for p in scraper.products:
print(f"โข ID #{p['id']}: {p['title']:22} | Price: {p['price']:>10} | Availability: {p['status']}")
requests.get(url, headers={'User-Agent': 'Mozilla/5.0...'}): Fetches the raw HTML string over HTTPS, providing a realistic browser user-agent header.soup.select('div.product-card'): Uses standard CSS selector syntax (dot notation for classes, hash for IDs) to find all matching card containers.item.get_text(strip=True): Extracts human-readable text while stripping out all surrounding whitespace and HTML tags.
Static scrapers (like requests + BeautifulSoup) can only read the initial static HTML sent by the server. If a website is built with React, Vue, or Angular (where content loads dynamically via client-side JavaScript API calls or infinite scrolling), static scrapers see only an empty <div id="root"></div>!
The Solution: Headless Browser Automation (Selenium / Playwright):
Browser automation tools launch a real, automated Chrome/Firefox browser engine in the background (Headless Mode without a visible UI window), execute all client-side JavaScript, click buttons, fill login forms, and wait for elements to appear.
# Playwright & Selenium Headless Automation Pattern Reference:
"""
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 1. Configure Headless Chrome Browser:
chrome_options = Options()
chrome_options.add_argument("--headless=new") # Run in background without window
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--no-sandbox")
# 2. Launch WebDriver:
driver = webdriver.Chrome(options=chrome_options)
try:
# 3. Navigate to dynamic web page:
driver.get("https://example.com/login")
# 4. Explicit Wait: Wait up to 10 seconds for dynamic element to render:
username_input = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.NAME, "username"))
)
# 5. Type credentials and click login:
username_input.send_keys("balaji_dev")
driver.find_element(By.NAME, "password").send_keys("SecretPass2026")
driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
# 6. Capture full rendered page source or take screenshot:
driver.save_screenshot("dashboard_verified.png")
print("โ
Successfully logged in and captured screenshot!")
finally:
driver.quit() # Always close browser process to free RAM!
"""
print("Browser Automation Blueprint Configured.")
Never use hardcoded time.sleep(5) in automation scripts (it slows down execution). Always use Explicit Waits (WebDriverWait) which poll the DOM every 500ms and resume execution the exact millisecond the element appears.
Firing hundreds of requests per second will trigger Cloudflare/Akamai rate limiters and result in an instant 429 Too Many Requests status or permanent IP address ban. Always insert random delays (time.sleep(random.uniform(1.0, 3.0))) and check the site's robots.txt file.
Write a regex or string extraction function parse_links(html_text) that extracts all href URLs from tags.
import re
sample_html = '''
'''
links = re.findall(r'href="([^"]+)"', sample_html)
print("Extracted Hyperlinks:")
for link in links:
print("โข", link)
Q What is robots.txt in web scraping?
robots.txt is a text file located at the root of a domain (e.g. example.com/robots.txt) specifying which directories crawlers and scrapers are permitted (Allow) or forbidden (Disallow) to scrape.
Q How does Playwright compare to Selenium in 2026?
Playwright (by Microsoft) is significantly faster, supports modern async/await syntax out of the box, handles automatic waiting natively, and can intercept network requests and mock API responses with ease.
Q How do I bypass Cloudflare bot detection in web scraping?
Use realistic browser headers (including User-Agent, Accept-Language, Sec-Ch-Ua), manage request delays, solve captchas using human-in-the-loop services, or use undetected-chromedriver / stealth plugins.