sodcalculator

10 Tech How-To

Web Scraping with Beautiful Soup: A Step-by-Step Guide

Guide 10-15847 · Updated · Step by step

This guide shows you how to extract data from websites using Python and Beautiful Soup, a library that parses HTML and makes it easy to navigate and search the page structure. You’ll learn how to fetch a page, locate specific elements, and save the data you need—skills useful for gathering product details, news headlines, or any public information. No prior experience with web scraping is required, but you should have basic Python knowledge and a code editor installed.

What You’ll Need

  • Python 3.7 or newer installed on your computer
  • pip (Python’s package installer, usually included with Python)
  • A code editor or IDE (like VS Code, PyCharm, or even a simple text editor)
  • Internet connection to install packages and fetch web pages

Step-by-Step

  1. Install the required libraries. Open your terminal or command prompt and run:
    pip install requests beautifulsoup4
    This installs requests (to download web pages) and beautifulsoup4 (to parse HTML).
  2. Create a new Python script. In your editor, create a file named scraper.py. This will hold all your code.
  3. Import the libraries. At the top of your script, add:
    import requests
    from bs4 import BeautifulSoup
  4. Fetch the webpage. Use requests.get() to download the page content. For example:
    url = 'https://example.com'
    response = requests.get(url)

    Always check that the request succeeded by verifying response.status_code == 200. If not, handle the error (see Troubleshooting).
  5. Parse the HTML. Pass the response text to BeautifulSoup:
    soup = BeautifulSoup(response.text, 'html.parser')
    The html.parser is built into Python, so no extra install is needed.
  6. Find elements. Use methods like find() (returns the first match) or find_all() (returns a list of all matches). For example, to get all headings:
    headings = soup.find_all('h2')
    To find by class or id, use the class_ and id parameters:
    title = soup.find('h1', id='main-title')
    items = soup.find_all('div', class_='product')
  7. Extract text and attributes. Use .text or .get_text() to get the visible text inside an element. To get an attribute like href or src, use element['href'] or element.get('href').
  8. Loop through multiple elements. If you’re scraping a list, iterate over the results:
    for item in items:
        name = item.find('h2').text
        price = item.find('span', class_='price').text
        print(name, price)
  9. Handle missing data gracefully. Not every element may exist. Use if checks or the get_text() method with a default. For example:
    title = item.find('h2')
    if title:
        print(title.text)
    else:
        print('No title')
  10. Save the data. Write the extracted data to a CSV file using Python’s csv module, or to a JSON file with json.dump(). This makes your scraping useful for later analysis.
  11. Respect the website. Always check the site’s robots.txt (e.g., https://example.com/robots.txt) to see if scraping is allowed. Also, add a delay between requests using time.sleep(1) to avoid overloading the server.

Common Mistakes

  • Using the wrong parser. The default html.parser is fine for most pages, but if you encounter weird parsing issues, try lxml (install with pip install lxml) or html5lib.
  • Not checking the response status. A page might return a 404 or 403 error, and your script will fail. Always check response.status_code before parsing.
  • Assuming elements exist. Websites change, and an element you expect might be missing. Use conditional checks to avoid AttributeError.
  • Scraping JavaScript-rendered content. Beautiful Soup only sees the initial HTML. If the content is loaded dynamically, you’ll need Selenium or Playwright (see Troubleshooting).
  • Ignoring the site’s terms. Some sites explicitly forbid scraping in their terms of service. Always review them and respect rate limits.

Tips

  • Use your browser’s developer tools. Right-click on the element you want and select “Inspect” to see its HTML structure. This helps you write precise selectors.
  • Start with a small test. Before scraping hundreds of pages, test your script on a single page to ensure it works.
  • Use CSS selectors. The select() method lets you use CSS-like selectors, e.g., soup.select('div.product > h2'). This can be more concise.
  • Cache your requests. If you’re developing, save the HTML to a file and parse that instead of hitting the server repeatedly.
  • Handle pagination. If the site has multiple pages, look for a “Next” button and loop through it, updating the URL or using the link’s href.

Troubleshooting

  • Request returns 403 Forbidden. The site may be blocking default user agents. Set a custom header:
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}
    response = requests.get(url, headers=headers)
  • Content is empty or missing. The data may be loaded via JavaScript. Use a headless browser like Selenium:
    pip install selenium
    Then use webdriver to load the page and get the rendered HTML.
  • Encoding issues. If you see garbled characters, specify the encoding: response.encoding = 'utf-8' before parsing.
  • Script crashes due to network errors. Wrap your request in a try-except block and retry after a delay.
  • Elements not found. Double-check the class name or id—they are case-sensitive. Use print(soup.prettify()) to see the actual HTML structure.

Frequently Asked Questions

Is web scraping legal?

It depends on the website’s terms of service and local laws. Public data is generally scrapeable, but always check robots.txt and the site’s terms. Avoid scraping personal data or copyrighted content without permission.

Can I scrape sites that require login?

Yes, but it’s more complex. You’ll need to handle sessions and cookies, often using requests.Session() to maintain login state. However, many sites prohibit automated login scraping, so proceed with caution.

How do I scrape data from tables?

Use soup.find('table') to get the table, then iterate over tr (rows) and td or th (cells). Extract text from each cell and store in a list of lists.

What’s the difference between find() and find_all()?

find() returns the first matching element or None if no match. find_all() returns a list of all matches (empty list if none). Use find_all() when you expect multiple elements.

How do I avoid being blocked?

Respect the site’s rate limits by adding delays between requests, rotate user agents, and avoid aggressive scraping patterns. Consider using a proxy if you’re scraping at scale, but always follow ethical practices.

Can I scrape dynamic content with Beautiful Soup alone?

No. Beautiful Soup parses static HTML only. For JavaScript-rendered content, use Selenium, Playwright, or Puppeteer to render the page first, then feed the resulting HTML to Beautiful Soup.

Related

General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.

More in this bed

The whole Tech How-To bed →