To kick off your journey into web scraping with Python, here are the detailed steps to get you started quickly and efficiently:
👉 Skip the hassle and get the ready to use 100% working script (Link in the comments section of the YouTube Video) (Latest test 31/05/2025)
First, install Python from python.org. Most systems already have it, but ensure you have a recent version 3.8+ is good.
Next, set up your environment. A virtual environment is crucial to manage project dependencies cleanly. Open your terminal or command prompt and run:
0.0 out of 5 stars (based on 0 reviews)
There are no reviews yet. Be the first one to write one. |
Amazon.com:
Check Amazon for Web scraping with Latest Discussions & Reviews: |
python -m venv venv_scraper
source venv_scraper/bin/activate # On Windows, use `venv_scraper\Scripts\activate`
Then, install key libraries: requests
for fetching web pages and BeautifulSoup4
for parsing HTML.
pip install requests beautifulsoup4
Now, identify your target website and its data. Before you scrape, always review the website’s robots.txt
file e.g., https://example.com/robots.txt
to understand their scraping policies. Respect their rules. if they explicitly disallow scraping, it’s best to find an alternative data source or contact them for an API. Ethical scraping is paramount.
Finally, write your script. A basic script involves:
- Sending a GET request to the URL using
requests.get'your_url'
. - Parsing the HTML content with
BeautifulSoupresponse.content, 'html.parser'
. - Locating the data using CSS selectors or HTML tags e.g.,
soup.find_all'div', class_='product-name'
. - Extracting the text or attributes from the elements.
- Saving the data to a structured format like CSV or JSON.
Understanding the Fundamentals of Web Scraping
Web scraping, at its core, is the automated extraction of data from websites.
Think of it as a digital librarian systematically going through books web pages and pulling out specific facts or figures.
In an age where data is increasingly valuable, web scraping provides a powerful, albeit often misunderstood, method for collecting information that isn’t readily available via APIs.
While it can be a fantastic tool for research, market analysis, and even personal projects, it’s crucial to approach it with a clear understanding of its implications and best practices.
What is Web Scraping?
Web scraping is the process of extracting information from websites using automated software. Turnstile and challenge in 2024
Instead of manually copying and pasting, a “scraper” program can browse a webpage, identify the data points you’re interested in, and then collect them in a structured format.
This can range from product prices on an e-commerce site to articles from news portals or even public contact information.
The key is automation, allowing for the collection of large datasets efficiently.
Why Python for Web Scraping?
Python has emerged as the go-to language for web scraping, and for good reasons.
Its simplicity and readability make it accessible for beginners, while its extensive ecosystem of powerful libraries caters to complex scraping tasks. Identify cdata cloudflare
- Rich Ecosystem: Libraries like
requests
,BeautifulSoup
,Scrapy
, andSelenium
provide robust tools for every stage of the scraping process, from making HTTP requests to parsing HTML and handling dynamic content. - Community Support: A massive and active community means abundant resources, tutorials, and quick solutions to common problems.
- Versatility: Python isn’t just for scraping. the data you collect can then be cleaned, analyzed, and visualized using other Python libraries, creating a seamless end-to-end data pipeline.
- Ease of Use: Compared to other languages, Python’s syntax is often more intuitive, reducing the learning curve.
Ethical Considerations and Legality of Web Scraping
This is where we slow down and think.
While web scraping is a powerful tool, it’s not a free pass to take whatever you want.
As a professional, understanding the ethical and legal boundaries is non-negotiable.
- Respect
robots.txt
: This file e.g.,https://example.com/robots.txt
is a website’s way of telling scrapers what areas they can and cannot access. Always check it first. Ignoring it is like walking past a “Do Not Enter” sign. - Terms of Service ToS: Many websites explicitly state their policies on automated data collection in their ToS. Violating these can lead to legal action, account suspension, or IP bans. Always read them.
- Data Privacy: Never scrape personal or sensitive data without explicit consent. This is a critical point, especially with regulations like GDPR.
- Server Load: Send requests at a reasonable rate. Bombarding a server can slow it down or even crash it, which is effectively a denial-of-service attack. Use delays
time.sleep
between requests. - Copyright and Intellectual Property: The data you scrape might be copyrighted. Using it commercially without permission can lead to serious legal repercussions.
- Public vs. Private Data: Just because data is publicly visible doesn’t mean it’s free for all uses. Think about the intent and potential harm.
Consider the example of news articles.
While you might scrape headlines for personal research, republishing entire articles without permission is a copyright infringement. Im not a bot
For ethical data collection, consider using official APIs whenever available.
They are built for programmatic access and respect the website’s data ownership.
If an API isn’t available and scraping is your only option, prioritize anonymized public data and always ensure your actions don’t harm the website or its users. This isn’t just about avoiding legal trouble. it’s about conducting yourself with integrity.
Setting Up Your Python Environment for Scraping
Before you start writing code, setting up a clean and efficient Python environment is like preparing your workshop before a big project.
A well-organized environment ensures your dependencies don’t clash and your projects remain isolated. Redeem bonus code capsolver
Installing Python
If you don’t have Python already, the first step is to get it.
- Download from Python.org: Visit https://www.python.org/downloads/ and download the latest stable release of Python 3. As of late 2023, Python 3.9+ is widely recommended.
- Installation Process:
- Windows: During installation, crucially, make sure to check the box that says “Add Python to PATH.” This saves you a lot of headache later.
- macOS/Linux: Python 3 often comes pre-installed. You can verify this by opening your terminal and typing
python3 --version
. If it’s not there, use your system’s package manager e.g.,brew install python3
for macOS with Homebrew, orsudo apt-get install python3
for Debian/Ubuntu.
Virtual Environments: Your Best Friend
Imagine you’re working on two scraping projects.
Project A needs requests
version 2.25.0, but Project B requires an older requests
version 2.20.0. Without virtual environments, installing one might break the other.
Virtual environments solve this by creating isolated Python installations for each project.
-
Why use them? Httpclient csharp
- Dependency Management: Prevent dependency conflicts between projects.
- Cleanliness: Keep project dependencies separate from your global Python installation.
- Reproducibility: Easily share your project with others. they can recreate your exact environment.
-
How to create and activate:
-
Navigate to your project directory in the terminal:
cd my_scraper_project
-
Create a virtual environment:
python3 -m venv venv
You can namevenv
anything you like, butvenv
is common. -
Activate it:
* macOS/Linux:source venv/bin/activate
* Windows Command Prompt:venv\Scripts\activate.bat
* Windows PowerShell:venv\Scripts\Activate.ps1
- You’ll see
venv
or a similar indicator in your terminal prompt, signifying that the virtual environment is active.
-
-
Deactivating: When you’re done with a project, just type
deactivate
. Capsolver captcha 해결 서비스
Essential Python Libraries for Scraping
Once your virtual environment is active, it’s time to install the workhorses of web scraping.
requests
for HTTP Requests
The requests
library is your gateway to the internet.
It simplifies making HTTP requests, allowing your Python script to act like a web browser and fetch web pages.
- Installation:
pip install requests
- Key features:
- GET, POST, PUT, DELETE requests.
- Handling redirects, sessions, and cookies.
- Custom headers, proxies, and authentication.
- Example Usage:
import requests response = requests.get'https://www.example.com' printresponse.status_code # Should print 200 for success printresponse.text # Prints the first 200 characters of the HTML
BeautifulSoup4
for HTML Parsing
BeautifulSoup4
often referred to just as BeautifulSoup is a fantastic library for pulling data out of HTML and XML files.
It sits on top of an HTML parser like lxml
or html5lib
and provides Pythonic ways to navigate, search, and modify the parse tree. Mastering web scraping defeating anti bot systems and scraping behind login walls
-
Installation:
pip install beautifulsoup4
Note:BeautifulSoup4
is the package name, notBeautifulSoup
.- Parse malformed HTML gracefully.
- Navigate the parse tree using tags, attributes, and text.
- Powerful search methods
find
,find_all
,select
.
from bs4 import BeautifulSoup
html_doc = “””
The Dormouse’s story The Dormouse’s story
“””
soup = BeautifulSouphtml_doc, ‘html.parser’
printsoup.prettify # Formats the HTML nicely
printsoup.title.string # Extracts title text
printsoup.find_all’a’ # Finds all tags
While soup = BeautifulSoupresponse.content, ‘lxml’ With these tools in place, your scraping environment is ready to tackle a wide range of web data extraction tasks.
Remember to keep your virtual environments clean and manage dependencies methodically. Recent changes on webmoney payment processing
Now that your environment is set up, let’s dive into the core mechanics: fetching a web page and extracting data from its HTML.
This is where The first step in any web scraping endeavor is to download the web page’s content.
The Most commonly, you’ll use a This is what your browser does when you type a URL.
lxml
for Speed Optional but RecommendedBeautifulSoup
can use Python’s built-in html.parser
, lxml
is a much faster and more robust parser, especially for large or complex HTML documents.
pip install lxml
BeautifulSoup
object, simply specify lxml
as the parser:
… fetch HTML with requests
Basic Web Scraping: Fetching and Parsing
requests
and BeautifulSoup
truly shine.
Making HTTP Requests with
requests
requests
library makes this incredibly straightforward.
Sending a GET Request
GET
request to retrieve data from a server. Kameleo 4 0 experience the next level of masking with multikernel
-
Simple Fetch:
url = ‘http://quotes.toscrape.com/‘ # A great site for scraping practice!
response = requests.geturlCheck the status code: 200 means success
if response.status_code == 200:
print”Page fetched successfully!”
# The content of the page is in response.text
# printresponse.text # Print first 500 characters
else:
printf”Failed to fetch page. Status code: {response.status_code}”
A successfulstatus_code
of200
indicates that the request was processed correctly. Kameleo 2 11 update to net 7
Other common codes include 404
Not Found, 403
Forbidden, 500
Internal Server Error.
Handling Request Headers
Websites often check request headers to determine if the request is coming from a legitimate browser or an automated script.
If your script gets blocked, modifying the User-Agent
header is often the first troubleshooting step.
-
Why User-Agent? It tells the server what kind of client is making the request e.g., Chrome on Windows, Firefox on Mac. Many sites block default
requests
User-Agents. -
Adding Headers:
url = ‘http://quotes.toscrape.com/‘
headers = { Kameleo v2 2 is available today'User-Agent': 'Mozilla/5.0 Windows NT 10.0. Win64. x64 AppleWebKit/537.36 KHTML, like Gecko Chrome/119.0.0.0 Safari/537.36'
}
response = requests.geturl, headers=headersprint"Page fetched with custom User-Agent!" printf"Failed with custom User-Agent. Status code: {response.status_code}"
You can find your browser’s current User-Agent by searching “what is my user agent” on Google.
Dealing with robots.txt
and Delays
As discussed earlier, always check robots.txt
before scraping.
To prevent overwhelming a server and appearing aggressive, introduce delays.
-
Implementing Delays:
import time How to bypass cloudflare with playwrightSimulate fetching multiple pages with a delay
For i in range3: # Fetching 3 pages for example
response = requests.getf"{url}/page/{i+1}/", headers=headers if response.status_code == 200: printf"Page {i+1} fetched." # Process page content here... else: printf"Failed to fetch page {i+1}. Status code: {response.status_code}" time.sleep2 # Wait for 2 seconds before the next request
A 2-5 second delay is a common starting point, but adjust based on the website’s load and your scraping volume.
Parsing HTML with BeautifulSoup
Once you have the HTML content response.text
, BeautifulSoup
allows you to navigate and extract data from it.
Creating a BeautifulSoup Object
The first step is to parse the HTML string into a BeautifulSoup
object.
from bs4 import BeautifulSoup
import requests
url = 'http://quotes.toscrape.com/'
response = requests.geturl
soup = BeautifulSoupresponse.text, 'lxml' # Using lxml parser for speed
printf"Parsed HTML with title: {soup.title.string}"
Navigating the Parse Tree
`BeautifulSoup` treats the HTML document as a tree structure, allowing you to access elements using dot notation or by specific methods.
* Direct Access:
printsoup.title # <title>Quotes to Scrape</title>
printsoup.title.name # title
printsoup.title.string # Quotes to Scrape
printsoup.p # The first <p> tag
* Accessing Attributes:
link = soup.find'a' # Finds the first <a> tag
if link:
printlink.get'href' # http://quotes.toscrape.com/
printlink # Same as above, convenient shorthand
Finding Elements with `find` and `find_all`
These are your primary tools for locating specific HTML elements.
* `findtag, attributes`: Returns the first element matching the criteria.
first_quote_div = soup.find'div', class_='quote' # Find the first div with class 'quote'
if first_quote_div:
printf"First quote author: {first_quote_div.find'small', class_='author'.text.strip}"
* `find_alltag, attributes`: Returns a list of all elements matching the criteria.
all_quote_divs = soup.find_all'div', class_='quote'
printf"Found {lenall_quote_divs} quotes on the page."
for quote_div in all_quote_divs:
text = quote_div.find'span', class_='text'.text.strip
author = quote_div.find'small', class_='author'.text.strip
tags =
printf"Quote: \"{text}\"\nAuthor: {author}\nTags: {', '.jointags}\n---"
Key Tip: Inspect the website's HTML structure using your browser's Developer Tools right-click -> "Inspect" or F12. This is crucial for identifying the correct tags, classes, and IDs to target. Look for unique attributes that consistently identify the data you need.
This foundation of fetching with `requests` and parsing with `BeautifulSoup` forms the backbone of most web scraping projects.
Practice these steps, and you'll be well on your way to extracting data from static web pages.
Advanced Scraping Techniques
Once you've mastered fetching and parsing static HTML, you'll quickly encounter websites that use dynamic content, require authentication, or employ anti-scraping measures.
This section delves into techniques to handle these more complex scenarios.
# Handling Dynamic Content JavaScript with Selenium
Many modern websites load content dynamically using JavaScript. This means that when you fetch the HTML with `requests`, the data you want might not be present in the initial `response.text` because it's loaded *after* the page renders in a browser. This is where `Selenium` comes in.
What is Selenium?
Selenium is primarily a tool for automating web browsers.
It allows you to simulate user interactions like clicking buttons, filling forms, scrolling, and waiting for elements to load.
Because it actually opens a browser like Chrome or Firefox, it can see and interact with all the dynamically loaded content.
* Installation:
```bash
pip install selenium
* Driver Setup: You'll need a browser driver e.g., `chromedriver` for Chrome, `geckodriver` for Firefox that matches your browser version. Download it from the official Selenium documentation e.g., https://chromedriver.chromium.org/downloads. Place the executable in a directory that's in your system's PATH, or specify its path in your script.
* Basic Usage:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Path to your ChromeDriver executable
chrome_driver_path = 'C:/path/to/chromedriver.exe' # Adjust this path!
# Set up the Chrome service
service = Serviceexecutable_path=chrome_driver_path
driver = webdriver.Chromeservice=service
url = 'https://www.example.com/dynamic-content-site' # Replace with a dynamic site
driver.geturl
# Wait for a specific element to be present e.g., a div with ID 'dynamic-data'
try:
element = WebDriverWaitdriver, 10.until
EC.presence_of_element_locatedBy.ID, 'dynamic-data'
print"Dynamic content loaded!"
# Now parse the page source with BeautifulSoup
soup = BeautifulSoupdriver.page_source, 'lxml'
# ... continue parsing with BeautifulSoup as usual
# For example, find the text of the dynamic element
# printsoup.findid='dynamic-data'.text
except Exception as e:
printf"Error loading dynamic content: {e}"
finally:
driver.quit # Always close the browser
Pros: Handles complex JavaScript, forms, logins, and AJAX.
Cons: Slower, more resource-intensive, requires browser driver management. Use it only when `requests` and `BeautifulSoup` aren't sufficient.
# Handling Forms and POST Requests
Many websites use forms for search, login, or submitting data.
While `requests.get` is for fetching, `requests.post` is for submitting data.
* How it works:
1. Inspect the form on the website using Developer Tools. Identify the form's `action` URL and its `method` GET or POST.
2. Identify the `name` attribute of each input field in the form.
These names will be the keys in your `data` dictionary.
3. Construct a dictionary where keys are input `name` attributes and values are the data you want to submit.
4. Send a `requests.post` request with the form URL and your `data` dictionary.
* Example Hypothetical Login:
login_url = 'https://www.example.com/login_page' # Replace with actual login URL
payload = {
'username': 'myuser',
'password': 'mypassword'
# Use a session to persist cookies important for login
with requests.Session as session:
login_response = session.postlogin_url, data=payload, headers=headers
if login_response.status_code == 200:
print"Login successful or at least, request sent successfully."
# Now, you can use the same session to access pages that require login
# protected_page = session.get'https://www.example.com/dashboard', headers=headers
# printprotected_page.text
printf"Login failed. Status code: {login_response.status_code}"
Crucial: The `requests.Session` object is vital here. It automatically persists cookies across requests, which is how websites maintain your login status.
# Dealing with Anti-Scraping Measures Proxies, IP Rotation
Websites implement anti-scraping techniques to protect their servers and data.
Recognizing and politely circumventing these is part of advanced scraping.
* Common Measures:
* IP Blocking: Blocking requests from an IP address sending too many requests.
* User-Agent Blocking: Blocking requests with known bot User-Agents.
* CAPTCHAs: Presenting challenges to verify if the user is human.
* Honeypots: Hidden links that bots follow, leading to their identification and blocking.
* Dynamic Content: Data loaded via JavaScript, making static HTML parsing difficult.
* Login Walls: Requiring authentication.
* Countermeasures:
* User-Agent Rotation: Use a list of diverse User-Agents and randomly select one for each request.
* _Real Data:_ Many scrapers use a pool of 50-100 common browser User-Agents.
* Proxies: Route your requests through different IP addresses.
* Free Proxies: Often unreliable, slow, and short-lived. Not recommended for serious projects.
* Paid Proxies: Offer better speed, reliability, and anonymity. Providers like Bright Data or Smartproxy offer residential or datacenter proxies.
* Residential Proxies: IPs from real residential users. harder to detect.
* Datacenter Proxies: IPs from data centers. faster but easier to detect.
* Example with Proxy:
```python
import requests
proxies = {
'http': 'http://username:password@your_proxy_ip:port',
'https': 'https://username:password@your_proxy_ip:port'
}
# Or for free proxies less reliable:
# proxies = {'http': 'http://10.10.1.10:3128'}
try:
response = requests.get'https://httpbin.org/ip', proxies=proxies, timeout=5
printresponse.json # Shows the IP address used for the request
except requests.exceptions.RequestException as e:
printf"Proxy request failed: {e}"
```
* Delays and Randomness: Implement random delays between requests `time.sleeprandom.uniform2, 5` to mimic human behavior.
* Headless Browsers Selenium: For CAPTCHAs or very complex dynamic content, Selenium is often the only way, but it's slow. Consider services like Anti-Captcha if you encounter many.
* Distributed Scraping: Use multiple machines or cloud functions with different IPs to distribute requests.
Important Note: The effectiveness of anti-scraping measures varies widely. Some sites are easy, others are extremely difficult. Always start with the simplest methods and only escalate to more complex ones like proxies or Selenium if necessary. Ethical scraping also means not attempting to bypass measures that are clearly designed to protect sensitive data or server integrity.
Data Storage and Export
Once you've successfully scraped data, the next critical step is to store it in a usable format. Raw data isn't very useful. structured, accessible data is.
# Saving Data to CSV
CSV Comma Separated Values is a very common and versatile format for tabular data.
It's human-readable and easily imported into spreadsheets or databases.
* Why CSV?
* Simplicity: Easy to understand and work with.
* Universality: Supported by almost all data analysis tools, spreadsheets Excel, Google Sheets, and databases.
* Lightweight: Small file sizes.
* Using Python's `csv` module:
import csv
# Example data e.g., from scraping quotes.toscrape.com
data_to_save =
{'text': 'The world as we have created it is a process of our thinking.
It cannot be changed without changing our thinking.', 'author': 'Albert Einstein', 'tags': },
{'text': 'It is our choices, Harry, that show what we truly are, far more than our abilities.', 'author': 'J.K. Rowling', 'tags': },
# ... more data
# Define the headers for your CSV file
fieldnames =
output_filename = 'quotes.csv'
with openoutput_filename, 'w', newline='', encoding='utf-8' as csvfile:
writer = csv.DictWritercsvfile, fieldnames=fieldnames
writer.writeheader # Writes the header row
for row in data_to_save:
# Ensure 'tags' are joined into a single string for CSV
row = ', '.joinrow # Convert list of tags to a single string
writer.writerowrow
printf"Data successfully saved to {output_filename}"
* `newline=''` is crucial to prevent extra blank rows in Windows.
* `encoding='utf-8'` ensures proper handling of special characters.
* `DictWriter` is excellent when your data is a list of dictionaries, as it maps dictionary keys to column names.
# Saving Data to JSON
JSON JavaScript Object Notation is another extremely popular format, especially for web-related data.
It's excellent for hierarchical or semi-structured data.
* Why JSON?
* Hierarchical: Naturally represents nested data structures.
* Web Standard: Widely used in web APIs and web applications.
* Readable: Relatively easy for humans to read.
* Using Python's `json` module:
import json
# Same data as above
output_filename = 'quotes.json'
with openoutput_filename, 'w', encoding='utf-8' as jsonfile:
json.dumpdata_to_save, jsonfile, indent=4, ensure_ascii=False
* `indent=4` makes the JSON output pretty-printed and more readable.
* `ensure_ascii=False` allows non-ASCII characters like Arabic or accented letters to be stored directly, rather than as Unicode escape sequences.
# Database Storage SQLite Example
For larger datasets, continuous scraping, or when you need to query your data efficiently, a database is often the best choice.
SQLite is a lightweight, file-based SQL database ideal for local development and smaller projects.
* Why SQLite?
* No Server Needed: The database is stored in a single file.
* Built-in: Python has built-in support for SQLite `sqlite3` module.
* SQL Power: Allows complex queries and data manipulation.
* Using Python's `sqlite3` module:
import sqlite3
# Connect to or create a SQLite database file
db_filename = 'quotes.db'
conn = sqlite3.connectdb_filename
cursor = conn.cursor
# Create a table if it doesn't exist
cursor.execute'''
CREATE TABLE IF NOT EXISTS quotes
id INTEGER PRIMARY KEY AUTOINCREMENT,
text TEXT NOT NULL,
author TEXT NOT NULL,
tags TEXT
'''
conn.commit # Save the table creation
# Example data from scraping
quotes_to_insert =
# Insert data into the table
for quote in quotes_to_insert:
# Join tags into a string for storage
tags_str = ', '.joinquote
cursor.execute
"INSERT INTO quotes text, author, tags VALUES ?, ?, ?",
quote, quote, tags_str
conn.commit # Save the inserted data
# Verify data by querying
print"\nQuotes in database:"
for row in cursor.execute"SELECT text, author, tags FROM quotes LIMIT 5":
printf"Text: {row}, Author: {row}, Tags: {row}"
conn.close # Close the connection
printf"\nData successfully stored in {db_filename}"
* `conn.commit` is essential to save any changes made to the database.
* Always close the connection with `conn.close` when you're done.
Choosing the right storage format depends on your project's needs. For quick, one-off analyses, CSV or JSON are great.
For larger, more complex, or ongoing data collection, a database like SQLite or PostgreSQL/MySQL for larger deployments offers superior management and query capabilities.
Best Practices and Ethical Considerations in Detail
Building on our earlier discussion, let's dive deeper into what truly makes a web scraper ethical, robust, and sustainable.
Ignoring these principles isn't just risky from a legal or technical standpoint. it's also a disservice to the internet ecosystem.
# Respect `robots.txt`
This file is the first and most critical point of contact for any web scraper.
It's a clear directive from the website owner about what parts of their site they prefer not to be crawled by automated agents.
* Location: Always check `https:///robots.txt` e.g., `https://www.amazon.com/robots.txt`.
* Understanding Directives: Look for `User-agent:` and `Disallow:`.
* `User-agent: *` applies to all bots.
* `User-agent: YourCustomScraperName` applies only to bots identifying with that name.
* `Disallow: /private/` means you should not scrape anything under the `/private/` path.
* `Disallow: /` means the entire site is off-limits.
* Crawl-delay: Some `robots.txt` files specify a `Crawl-delay:` directive, which indicates the minimum number of seconds to wait between requests. Adhere to this strictly.
* Action: If `robots.txt` explicitly disallows scraping a certain path or the entire site, do not proceed with scraping those areas. Find alternative data sources or, if truly necessary, contact the website owner for permission.
# Adhering to Terms of Service ToS
Many websites have specific ToS that govern usage, including automated data collection.
* Where to Find: Usually linked in the footer of the website e.g., "Terms," "Terms of Use," "Legal".
* Look For: Clauses related to "crawling," "scraping," "automated access," "data mining," or "republication."
* Consequences of Violation:
* IP Ban: Your IP address might be permanently blocked.
* Account Suspension: If you're scraping from an authenticated account.
* Legal Action: In severe cases, especially involving copyrighted data or competitive intelligence, companies might pursue legal action.
* Best Practice: If the ToS prohibits scraping, you have two ethical options:
1. Do not scrape.
2. Contact the website owner to seek explicit permission or inquire about an API.
# Rate Limiting and Back-off Strategies
Aggressive scraping can severely impact a website's performance, leading to slow loading times, increased server costs, and potential downtime. This is why rate limiting is crucial.
* Why? To avoid overwhelming the server, consuming excessive bandwidth, and getting your IP blocked.
* Implementation:
* Fixed Delay: The simplest method. `time.sleepX` after each request.
```python
import time
for url in urls:
response = requests.geturl
# process response
time.sleep3 # Wait 3 seconds
```
* Randomized Delay: More human-like.
import random
time.sleeprandom.uniform2, 5 # Wait between 2 and 5 seconds
* Adaptive Back-off: If you encounter a `429 Too Many Requests` status code, pause for an exponentially increasing amount of time e.g., 5 seconds, then 10, then 20.
* _Real Data:_ Many commercial scraping tools will implement an exponential back-off strategy, doubling the wait time after each `429` error, often with a maximum delay e.g., up to 60 seconds before aborting.
* General Rule: Aim for requests per minute that are far less than what a single human browsing the site would generate. A good starting point is 1 request every 2-5 seconds.
# User-Agent and Header Faking
While this can be seen as a circumvention tactic, it's often a necessary measure because many sites block Python's default `requests` User-Agent.
This isn't about deception for malicious purposes, but about appearing like a legitimate browser.
* Why? Some websites are configured to detect and block non-browser User-Agents.
* Method: Provide a `User-Agent` string that mimics a popular browser e.g., Chrome, Firefox.
'User-Agent': 'Mozilla/5.0 Windows NT 10.0. Win64. x64 AppleWebKit/537.36 KHTML, like Gecko Chrome/119.0.0.0 Safari/537.36',
'Accept-Language': 'en-US,en.q=0.9',
'Referer': 'https://www.google.com/' # Sometimes useful
* Rotation: For large-scale scraping, consider rotating through a list of common User-Agents to further distribute your footprint.
# Data Privacy and Security
This is a critical ethical and legal aspect, especially with increasing global privacy regulations like GDPR in Europe or CCPA in California.
* Never Scrape PII Personally Identifiable Information: Unless you have explicit consent and a legitimate, lawful basis, do not scrape names, email addresses, phone numbers, addresses, or any data that can identify an individual. This is a major legal risk.
* Data Security: If you do handle any sensitive data e.g., if you're scraping your own accounts, ensure it's stored securely encrypted, access-controlled and only for its intended purpose.
* Anonymization: If your goal is aggregate analysis, consider if the data can be anonymized or pseudonymized during or after scraping to remove any PII.
* Public vs. Private: Publicly accessible data does not automatically grant you the right to collect or use it. Always assess the privacy implications. For example, scraping public forum posts is different from scraping private social media profiles.
Final Thoughts on Ethics: As a professional, your integrity is paramount. Web scraping, when done responsibly, can be a powerful tool for data analysis and innovation. However, when misused, it can lead to legal issues, server strain, and reputational damage. Always err on the side of caution, respect website policies, and prioritize data privacy. If an API is available, always choose the API over scraping. It's the most ethical and often the most reliable way to get data.
Common Pitfalls and Troubleshooting
Even seasoned scrapers run into issues.
Understanding common pitfalls and how to troubleshoot them can save you hours of frustration.
# IP Bans and Blocked Requests
This is probably the most common issue.
Your scraper works for a few pages, then suddenly you start getting `403 Forbidden` or `429 Too Many Requests` errors.
* Symptoms:
* `requests.status_code` is `403` Forbidden, `429` Too Many Requests, or `503` Service Unavailable.
* The returned HTML content is an error page, a CAPTCHA, or a message stating you've been blocked.
* Solutions:
* Increase `time.sleep`: The simplest first step. Double or triple your delay.
* User-Agent Rotation: As discussed, cycle through different User-Agent strings.
* Proxies: The most effective solution for IP bans. Route your requests through a pool of rotating proxies.
* Session Management: Ensure you're using `requests.Session` if you need to persist cookies e.g., for login or subsequent requests.
* HTTP Headers: Add more "browser-like" headers e.g., `Accept-Language`, `Referer`, `DNT: 1`.
* Headless Browsers Selenium: For very aggressive detection e.g., JavaScript-based fingerprinting, a headless browser might be necessary, as it executes JavaScript.
* Reduce Concurrency: If running multiple scrapers, lower the number of simultaneous requests.
# Handling CAPTCHAs
CAPTCHAs are designed to tell humans and bots apart.
They are a significant barrier to automated scraping.
* Symptoms: You encounter an image, audio challenge, or "I'm not a robot" checkbox page instead of the content.
* Avoidance: The best solution is to avoid sites that use CAPTCHAs if possible, or scrape data that doesn't trigger them.
* Manual Intervention: For very small-scale scraping, you might manually solve a few CAPTCHAs.
* Third-Party CAPTCHA Solving Services: Services like Anti-Captcha or 2Captcha can solve CAPTCHAs for you via an API, typically for a small fee per solved CAPTCHA. This is the most common automated approach.
* Selenium with Human Interaction Discouraged for automation: While Selenium can open a browser, automating CAPTCHA solving without an external service is extremely difficult and usually not feasible.
* Change IP/User-Agent: Sometimes, just rotating your IP or User-Agent can bypass a CAPTCHA if it's based on suspicious patterns.
# Parsing Errors Missing Data, Incorrect Selectors
This happens when your `BeautifulSoup` selectors aren't targeting the correct elements, or the website's structure has changed.
* Your script runs but extracts empty lists or `None` values.
* The extracted data is incorrect or incomplete.
* Errors like `AttributeError: 'NoneType' object has no attribute 'text'` when trying to access `.text` or `.string` on an element that wasn't found.
* Inspect HTML Developer Tools: This is your primary debugging tool.
* Right-click -> Inspect on the data you want to extract.
* Examine the HTML structure: What are the tags, classes, and IDs of the elements containing your data?
* Are there multiple elements with the same class? Use `find_all` instead of `find`.
* Is the data inside an `iframe`? You'll need to switch to the `iframe`'s content with Selenium or scrape the iframe's `src` URL directly.
* Test Selectors in Console: In your browser's Developer Tools Console tab, you can test CSS selectors directly:
* `$$'div.my-class'` will return all elements matching the CSS selector.
* `$0` references the currently selected element in the Elements tab.
* Print HTML: Print the `response.text` or `soup.prettify` in your script to see what HTML your script is actually receiving. Sometimes, the server sends a different version to a bot than to a browser.
* Check for Dynamic Content: If the data isn't in `response.text` even after inspection, it's likely loaded dynamically via JavaScript. Switch to Selenium or investigate network requests for AJAX calls.
* Use `try-except` blocks: Gracefully handle cases where elements might not be found.
element = soup.find'div', class_='non-existent-class'
if element:
printelement.text
print"Element not found." # Prevents AttributeError
* Website Structure Changes: Websites frequently update their layouts. If a scraper suddenly stops working, the first thing to check is if the HTML structure has changed.
# Session Expiration and Cookie Handling
For authenticated scraping e.g., logging into a dashboard, maintaining a session is critical.
* Symptoms: You can log in, but subsequent requests to protected pages redirect you to the login page or return `401 Unauthorized`.
* Use `requests.Session`: This object automatically manages cookies for you across multiple requests.
s = requests.Session
login_response = s.postlogin_url, data=login_payload
# Now, use 's' for all subsequent requests to maintain the session
protected_page_response = s.getprotected_url
* Inspect Cookies: Use Developer Tools to see what cookies are set after logging in. Ensure your session is capturing these.
* Check Token-Based Authentication: Some sites use tokens e.g., CSRF tokens in forms or headers. You might need to scrape the token from the login page, then include it in your POST request.
Troubleshooting is an iterative process.
Start with the simplest checks status codes, delays, User-Agent, then move to more complex solutions proxies, Selenium only if necessary.
Patience and systematic debugging are your best allies.
When to Use a Dedicated Scraping Framework Scrapy
For larger, more complex, and ongoing scraping projects, `requests` and `BeautifulSoup` might start feeling a bit cumbersome.
This is where a dedicated web scraping framework like Scrapy comes into play.
# What is Scrapy?
Scrapy is a powerful, open-source web crawling and scraping framework written in Python.
It's designed for rapid development and offers a complete solution for extracting data from websites at scale.
Think of it as an entire ecosystem for scraping, not just a set of tools.
* Key Features:
* Asynchronous Request Handling: Scrapy can send multiple requests concurrently, making it very fast.
* Robust Spider Architecture: You define "spiders" Python classes that know how to crawl specific sites and extract data.
* Middlewares: Hooks for processing requests and responses globally e.g., for user-agent rotation, proxy integration, cookie management, retries.
* Pipelines: Process scraped items after they are extracted e.g., clean data, validate, save to database, export to CSV/JSON.
* Command-Line Tools: Easily create projects, generate spiders, and run crawls.
* Built-in Selectors: Supports CSS selectors and XPath for powerful data extraction.
* Logging and Statistics: Provides detailed insights into your crawl.
# Pros and Cons of Scrapy
Choosing Scrapy over `requests`/`BeautifulSoup` isn't always clear-cut.
Pros of Scrapy:
* Scalability: Designed for large-scale, distributed crawls. Easily handle millions of pages.
* Speed: Asynchronous I/O makes it incredibly fast at fetching pages.
* Structure and Organization: Enforces a clean, maintainable project structure, great for teams or complex projects.
* Extensibility: Highly customizable through middlewares and pipelines.
* Built-in Features: Handles common scraping challenges like retries, redirects, and cookie management out of the box.
* Less Boilerplate: Once set up, many common tasks require less manual coding than with `requests`/`BeautifulSoup`.
Cons of Scrapy:
* Steeper Learning Curve: More complex than `requests`/`BeautifulSoup`. There's a framework to learn, not just a couple of libraries.
* Overkill for Simple Tasks: For scraping a single page or a handful of pages, Scrapy might be too heavy.
* Debugging Can Be More Complex: The asynchronous nature and framework layers can make debugging challenging for beginners.
* Not Ideal for Heavy JavaScript: While Scrapy can integrate with headless browsers like Splash, its core is designed for static content. For very heavy JavaScript sites, Selenium might still be simpler for isolated tasks.
# When to Consider Using Scrapy
* Large-scale Data Collection: When you need to scrape hundreds of thousands or millions of pages.
* Regular, Ongoing Scrapes: For projects requiring daily, weekly, or monthly data updates from websites.
* Complex Website Structures: When navigating through many pages, handling pagination, and dealing with various data types across a site.
* Distributed Scraping: If you plan to run your scraper on multiple machines or in the cloud.
* Projects Requiring Robust Error Handling: Scrapy's built-in retry mechanisms and logging are invaluable.
* Team Projects: Its structured approach makes it easier for multiple developers to work on the same scraping project.
* Example Scenario: Imagine you need to scrape product details name, price, reviews, availability from all 50,000 products across 10 different e-commerce categories, and then store this data in a database for daily analysis. This is a perfect use case for Scrapy. You would define a spider for each e-commerce site, and Scrapy would handle the crawling, fetching, parsing, and data saving efficiently.
# Getting Started with Scrapy
* Installation: `pip install scrapy`
* Create a Project: `scrapy startproject myproject`
* Generate a Spider: `cd myproject` then `scrapy genspider example quotes.toscrape.com`
* Write Your Spider: Edit the `example.py` file in `myproject/spiders/`.
# myproject/spiders/example.py
import scrapy
class QuoteSpiderscrapy.Spider:
name = "quotes"
start_urls =
def parseself, response:
# Extract quotes
for quote in response.css'div.quote':
yield {
'text': quote.css'span.text::text'.get,
'author': quote.css'small.author::text'.get,
'tags': quote.css'div.tags a.tag::text'.getall,
}
# Follow pagination link
next_page = response.css'li.next a::attrhref'.get
if next_page is not None:
yield response.follownext_page, callback=self.parse
* Run the Spider: `scrapy crawl quotes -o quotes.json` This will save output to `quotes.json`
While the initial setup for Scrapy is more involved, its power and efficiency for complex and large-scale projects often justify the steeper learning curve.
For quick, one-off tasks, stick with `requests` and `BeautifulSoup`. for anything more ambitious, seriously consider Scrapy.
Future Trends and Ethical Alternatives to Web Scraping
While web scraping remains a potent tool, it's increasingly scrutinized, and new approaches and ethical alternatives are emerging. As data professionals, we must adapt.
# APIs as the Preferred Alternative
The most ethical, reliable, and often efficient way to get data from a website is through its official API Application Programming Interface.
* What is an API? An API is a set of defined rules that allows different software applications to communicate with each other. Websites that offer APIs essentially provide a controlled, programmatic way to access their data.
* Why are APIs better?
* Explicit Permission: Using an API means you have direct permission from the website owner to access their data. This bypasses all `robots.txt` and ToS issues related to scraping.
* Structured Data: API responses are typically in clean JSON or XML format, eliminating the need for complex HTML parsing.
* Stability: APIs are designed to be stable. Changes to the website's visual layout usually don't break the API.
* Efficiency: API calls are often faster and consume fewer resources than scraping.
* Rate Limits: APIs usually have clear rate limits, making it easy to comply without guesswork.
* How to Find APIs:
* Check the website's developer documentation e.g., "Developers," "API," "Integrations" link in the footer.
* Search for " API" on Google.
* Explore API marketplaces like RapidAPI or ProgrammableWeb.
* Example Hypothetical API Call:
# Assume a hypothetical API endpoint for quotes
api_url = 'https://api.quoteservice.com/quotes'
'Authorization': 'Bearer YOUR_API_KEY', # APIs often require authentication
'Accept': 'application/json'
params = {
'limit': 10,
'tag': 'wisdom'
response = requests.getapi_url, headers=headers, params=params
data = response.json
for quote in data:
printf"Quote: {quote} - Author: {quote}"
printf"API call failed: {response.status_code} - {response.text}"
Key takeaway: Always investigate whether an API exists before considering scraping. It's the professional and ethical path forward.
# Data as a Service DaaS
For specific data needs, sometimes buying pre-scraped or collected data from a specialized provider is the most efficient and ethical route.
* What is DaaS? Companies that specialize in data collection offer "Data as a Service." They scrape, clean, and provide data directly to you, often via an API or bulk downloads.
* Benefits:
* No Scraping Hassle: You don't need to manage scrapers, IP bans, or parsing logic.
* High Quality: Data is often cleaned, validated, and updated regularly.
* Ethical Sourcing: Reputable DaaS providers often have legal agreements or partnerships with data sources, or only collect publicly available data.
* Use Cases: Market research data, e-commerce product catalogs, public company financials, news archives.
* Consideration: Cost can be a factor, but it often outweighs the development and maintenance costs of a complex scraping infrastructure.
# Ethical Considerations in AI/ML Training
The rise of Artificial Intelligence and Machine Learning has placed an even greater spotlight on data sourcing.
Training AI models on scraped data presents significant ethical challenges.
* Copyright and IP: Using copyrighted text, images, or audio scraped from the web to train AI models without permission is a massive legal and ethical grey area. Developers of large language models LLMs and image generators face numerous lawsuits over this.
* Bias: If scraped data contains inherent biases e.g., historical biases in text, stereotypes in images, the AI model will learn and perpetuate those biases.
* Privacy: Scraping personal data, even if publicly visible, and using it to train AI models raises serious privacy concerns. An AI model "remembering" personal details could be a huge liability.
* Misinformation: Training on unverified or false information can lead to AI models that generate misinformation.
* Solution: Prioritize using ethically sourced datasets for AI/ML training:
* Licensed Datasets: Purchase or license datasets from reputable providers.
* Open-Source and Public Domain Datasets: Utilize datasets explicitly released for public use.
* Synthetic Data: Generate artificial data that mimics real-world patterns but doesn't contain actual sensitive or copyrighted information.
* Crowdsourced Data: Collect data directly from users with explicit consent.
The future of data acquisition leans towards responsible, transparent, and consent-driven methods.
While web scraping with Python remains a powerful skill for specific scenarios especially for personal research or data not available otherwise, the ethical frameworks and alternative data sourcing methods should always be at the forefront of a data professional's mind.
Building tools that are respectful of the web and its users is not just good practice.
it's essential for long-term sustainability and integrity.
Frequently Asked Questions
# What is web scraping with Python?
Web scraping with Python is the process of extracting data from websites using Python programming.
It involves writing scripts that automatically send requests to web servers, download web page content HTML, and then parse that content to find and extract specific pieces of information, such as product prices, news headlines, or contact details, which are then saved in a structured format like CSV or JSON.
# Is web scraping legal?
The legality of web scraping is a complex and highly debated topic that varies by jurisdiction and depends on several factors, including the type of data being scraped, how it's used, and the website's terms of service and `robots.txt` file.
Generally, scraping publicly available, non-copyrighted data for personal, non-commercial use tends to be less risky, while scraping personal data or copyrighted content for commercial use without permission can lead to legal issues.
Always consult a legal professional for specific advice.
# What are the essential Python libraries for web scraping?
The two most essential Python libraries for basic web scraping are `requests` for making HTTP requests to fetch web page content, and `BeautifulSoup4` often referred to as BeautifulSoup for parsing HTML and XML documents to extract data.
For handling dynamic content loaded by JavaScript, `Selenium` is also a crucial library.
# What is `robots.txt` and why is it important for scrapers?
`robots.txt` is a text file that website owners place in the root directory of their website e.g., `https://example.com/robots.txt`. It contains rules and directives that tell web crawlers and scrapers which parts of the site they are allowed or disallowed to access.
Respecting `robots.txt` is a fundamental ethical and often legal requirement for web scraping, as ignoring it can lead to IP bans or legal action.
# How do I handle dynamic content JavaScript when scraping?
When websites load content dynamically using JavaScript e.g., through AJAX calls, the data you want might not be present in the initial HTML fetched by `requests`. To handle this, you need to use a headless browser automation tool like `Selenium`. Selenium can open a real browser or a simulated one, execute JavaScript, and then provide you with the fully rendered HTML source code, which you can then parse with BeautifulSoup.
# What is the difference between `requests` and `BeautifulSoup`?
`requests` is a library for sending HTTP requests to websites.
It's responsible for fetching the raw HTML content of a web page, similar to what your web browser does when you type a URL.
`BeautifulSoup` or `BeautifulSoup4` is a library for parsing and navigating the HTML content that `requests` has fetched.
It allows you to search for specific elements like `div` tags, `a` links, etc. using their attributes like `class` or `id` and extract the data within them.
# How can I prevent my IP from being blocked while scraping?
To prevent your IP address from being blocked:
1. Implement Delays: Add `time.sleep` between requests to avoid overwhelming the server e.g., `time.sleeprandom.uniform2, 5`.
2. Rotate User-Agents: Change the `User-Agent` header with each request to mimic different browsers.
3. Use Proxies: Route your requests through a pool of rotating IP addresses residential proxies are generally more effective than datacenter proxies.
4. Handle HTTP Status Codes: Watch for `429` Too Many Requests or `403` Forbidden and implement exponential back-off.
# What are HTTP headers and why are they important in scraping?
HTTP headers are key-value pairs sent with every HTTP request and response.
They contain metadata about the request or response, such as the `User-Agent` client identification, `Referer` the previous page, `Accept-Language` preferred language, and `Cookies`. For scrapers, customizing headers, especially the `User-Agent`, is crucial because many websites use them to detect and block automated scripts.
# Can I scrape data from websites that require login?
Yes, you can scrape data from websites that require login.
You'll typically use `requests.Session` to handle the login process.
First, send a `POST` request to the login URL with your credentials username, password. If successful, the `Session` object will store the authentication cookies.
You can then use the same `Session` object for subsequent `GET` requests to access authenticated pages, as the cookies will be automatically sent with each request, maintaining your logged-in state.
# What is the difference between `find` and `find_all` in BeautifulSoup?
In BeautifulSoup:
* `find`: Returns the first HTML element that matches the specified tag and attributes. If no match is found, it returns `None`.
* `find_all`: Returns a list of all HTML elements that match the specified tag and attributes. If no matches are found, it returns an empty list.
# How do I store scraped data?
Common ways to store scraped data include:
* CSV Comma Separated Values: Simple, tabular format ideal for spreadsheets. Python's `csv` module is used.
* JSON JavaScript Object Notation: Lightweight, human-readable format good for hierarchical data. Python's `json` module is used.
* Databases: For larger datasets, real-time access, or complex queries, databases like SQLite built-in `sqlite3` module, MySQL, or PostgreSQL are excellent choices.
* Excel .xlsx: Using libraries like `openpyxl` or `pandas`.
# What is the best practice for delaying requests to a website?
The best practice is to use randomized delays between requests.
Instead of a fixed `time.sleep3`, use `time.sleeprandom.uniform2, 5`. This mimics more human-like browsing patterns and makes your scraper less predictable, reducing the chances of detection and blocking.
Adhering to any `Crawl-delay` specified in `robots.txt` is also crucial.
# Should I use Scrapy or `requests`/`BeautifulSoup`?
* Use `requests` and `BeautifulSoup` for:
* Simple, one-off scraping tasks.
* Scraping a small number of pages.
* Learning the basics of web scraping.
* Use Scrapy for:
* Large-scale, ongoing scraping projects millions of pages.
* Projects requiring robust error handling, concurrency, and structured data pipelines.
* When you need to crawl entire websites.
* Team-based projects where a structured framework is beneficial.
# What are some common anti-scraping measures websites use?
Websites employ various anti-scraping measures:
1. IP-based Blocking: Blocking requests from specific IP addresses.
2. User-Agent and Header Checks: Analyzing request headers to identify bots.
3. Rate Limiting: Restricting the number of requests from a single IP within a time frame.
4. CAPTCHAs: Presenting human verification challenges.
5. Honeypot Traps: Hidden links or elements that only bots would follow, leading to their detection.
6. Dynamic Content JavaScript: Rendering content client-side to make static parsing difficult.
7. Login Walls/Authentication: Requiring user accounts to access content.
# What is XPath and CSS selectors in web scraping?
Both XPath and CSS selectors are languages used to select elements in an HTML or XML document.
* CSS Selectors: Generally simpler and more concise. They are commonly used in web development for styling and are well-supported by BeautifulSoup `soup.select'div.product-name'`.
* XPath XML Path Language: More powerful and flexible than CSS selectors. It allows you to select elements based on their position, attributes, and relationships to other elements, and traverse both up and down the DOM tree. Scrapy has strong XPath support.
# Is it ethical to scrape data from websites without permission?
While the legality of scraping public data is debated, the ethical stance generally points towards respecting the website owner's wishes. This means:
* Checking `robots.txt`: Always obey its directives.
* Reading Terms of Service ToS: If the ToS prohibits scraping, it's ethically questionable to proceed.
* Avoiding Overload: Do not send requests so rapidly that you put a strain on the website's server.
* Data Usage: Be mindful of how you use the scraped data, especially concerning privacy and copyright. The most ethical approach is to seek permission or use official APIs if available.
# What is Data as a Service DaaS and why is it an alternative to scraping?
Data as a Service DaaS refers to companies or platforms that provide ready-to-use, structured data sets, often collected through their own hopefully ethical scraping operations, licensed agreements, or public data sources.
It's an alternative to scraping because you can simply purchase or subscribe to the data you need, eliminating the complexities and ethical/legal risks of building and maintaining your own scraper.
This is particularly useful for commercial-scale data needs.
# How do I handle pagination when scraping multiple pages?
To handle pagination e.g., "Next Page" links, you typically:
1. Scrape the data from the current page.
2. Locate the HTML element that points to the "Next Page" often an `<a>` tag with a specific class or ID.
3. Extract the `href` attribute the URL of that "Next Page" link.
4. If a next page URL exists, send a new request to that URL and repeat the process until no "Next Page" link is found.
This creates a loop that crawls through all paginated pages.
# What are web scraping proxies and when should I use them?
Web scraping proxies are intermediary servers that route your web requests through different IP addresses.
When you use a proxy, the target website sees the proxy's IP address instead of your own. You should use them when:
* Your IP address is being blocked or rate-limited by the target website.
* You need to scrape a large volume of data from a website with aggressive anti-scraping measures.
* You need to appear as if requests are coming from different geographic locations.
# What is the role of `try-except` blocks in web scraping?
`try-except` blocks are crucial for making your web scrapers robust.
They allow you to gracefully handle errors that might occur during the scraping process, such as:
* Network errors e.g., `requests.exceptions.ConnectionError`.
* HTTP errors e.g., `response.status_code` indicating a problem.
* Parsing errors e.g., an element you're trying to extract is `None` because its selector didn't find it.
By wrapping your scraping logic in `try-except`, your script can continue running even if individual requests or parsing steps fail, preventing it from crashing.
Leave a Reply