Skip to content
  • requests & BeautifulSoup · Data Science

requests & BeautifulSoup

LearnViaNotes @learnvianotes· 2 min read

Web scraping = download a page's HTML (requests), then pick out the data you need (BeautifulSoup). It's how you build datasets that don't come as a CSV.

  1. Request

    requests.get(url, headers=…) downloads the page.

  2. Parse

    BeautifulSoup(html, "html.parser") turns HTML text into a searchable tree.

  3. Extract

    find / find_all / select locate elements; .text and .get("href") read them.

  4. Store

    Collect rows in a list, then save with pandas (to_csv).

1. Download the page

Python
import requests

headers = {"User-Agent": "Mozilla/5.0 (compatible; LearnViaNotesBot/1.0)"}
r = requests.get("https://quotes.toscrape.com/page/1/", headers=headers, timeout=10)
print(r.status_code)          # 200 means OK; 404 not found, 403 forbidden, 429 too many requests
html = r.text                 # decoded text (r.content is the raw bytes)

2. Parse and extract

Python
html = """
<div class="quote">
  <span class="text">“The world as we have created it is a process of our thinking.”</span>
  <small class="author">Albert Einstein</small> <a href="/author/Albert-Einstein">(about)</a>
  <a class="tag" href="/tag/change/">change</a> <a class="tag" href="/tag/thinking/">thinking</a>
</div>
<div class="quote">
  <span class="text">“It is our choices that show what we truly are.”</span>
  <small class="author">J.K. Rowling</small> <a href="/author/J-K-Rowling">(about)</a>
  <a class="tag" href="/tag/choices/">choices</a>
</div>
"""

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")

first = soup.find("div", class_="quote")                      # first match (or None)
print(first.find("small", class_="author").text)              # Albert Einstein

for q in soup.find_all("div", class_="quote"):                # every match
    text = q.find("span", class_="text").text.strip("“”")
    tags = [t.text for t in q.find_all("a", class_="tag")]
    print(text[:22], "|", ", ".join(tags))
Output
Albert Einstein
The world as we have c | change, thinking
It is our choices that | choices
CallReturns
soup.find(tag, class_=…)The first matching element, or None
soup.find_all(tag, attrs={…})A list of all matches
soup.select("div.quote span.text")Matches for a CSS selector
el.text / el.get_text(strip=True)The element's text
el.get("href") / el["href"]An attribute (get returns None if missing)
Python
html = """
<div class="quote">
  <span class="text">“The world as we have created it is a process of our thinking.”</span>
  <small class="author">Albert Einstein</small> <a href="/author/Albert-Einstein">(about)</a>
  <a class="tag" href="/tag/change/">change</a> <a class="tag" href="/tag/thinking/">thinking</a>
</div>
<div class="quote">
  <span class="text">“It is our choices that show what we truly are.”</span>
  <small class="author">J.K. Rowling</small> <a href="/author/J-K-Rowling">(about)</a>
  <a class="tag" href="/tag/choices/">choices</a>
</div>
"""

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
print([a.get("href") for a in soup.select("div.quote > a:not(.tag)")])   # ['/author/Albert-Einstein', '/author/J-K-Rowling']
print(len(soup.select("a.tag")))                                          # 3

Parsers

ParserInstallNotes
html.parserBuilt inGood default
lxmlpip install lxmlFastest
html5libpip install html5libMost forgiving with broken HTML, slowest

Scrape responsibly

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report