Understanding urllib and urllib2 Differences
Both urllib and urllib2 modules handle URL operations, but they serve different purposes. The key distinctions include:
- urllib2.urlopen can accept either a Request object or a URL, while urllib.urlopen only accepts URLs
- When using a Request object with urllib2, you can set custom headers for the URL
- urllib provides the urlencode function, which urllib2 lacks - this is why they're often used together
Example with urllib2 and Request Object
# Creating a request with custom headers and POST data
from urllib2 import Request, urlopen
from urllib import urlencode
web_request = Request(url='http://www.example.com')
web_request.add_header('User-Agent', 'Python Web Scraper')
web_request.add_data(urlencode({'key': 'value'}))
# Sending the request
response = urlopen(web_request)
urllib Module Features
Handling Unicode in urlencode
urlencode doesn't directly process unicode objects, so unicode needs to be encoded first:
# Encoding unicode to utf-8 before URL encoding
from urllib import urlencode
encoded_data = urlencode(u'unicode_string'.encode('utf-8'))
Basic URL Fetching
# Fetching a webpage and saving it to a file
from urllib import urlopen
web_url = 'http://m.example.com/some-page'
response = urlopen(web_url)
page_content = response.read()
# Save to file
with open('webpage.html', 'w') as output_file:
output_file.write(page_content)
# Display response object attributes
print dir(response)
URL Encoding and Decoding
The urllib module provides several functions for URL encoding and decoding:
from urllib import quote, unquote, quote_plus, unquote_plus, urlencode
# Basic URL encoding
encoded_string = quote('This is a test')
print 'Encoded:', encoded_string # Spaces become %20
decoded_string = unquote(encoded_string)
print 'Decoded:', decoded_string
# URL encoding with plus for spaces
encoded_with_plus = quote_plus('This is a test')
print 'Encoded with plus:', encoded_with_plus
decoded_from_plus = unquote_plus(encoded_with_plus)
print 'Decoded from plus:', decoded_from_plus
# Encoding dictionary data
form_data = {'username': 'johndoe', 'password': 'secure123'}
encoded_form = urlencode(form_data)
print 'Encoded form:', encoded_form
File Download with urlretrieve
The urlretrieve function is useful for simple file downloads:
from urllib import urlretrieve
file_url = 'http://m.example.com/some-resource'
urlretrieve(file_url, 'downloaded_file.html')
urllib2 Module Features
urllib2 provides advanced features for handling HTTP requests, including:
- Basic authentication
- Redirect handling
- Cookie management
- Custom headers
Basic Request Handling
# Simple URL request
from urllib2 import urlopen
web_url = 'http://m.example.com/some-page'
response = urlopen(web_url)
page_content = response.read()
Using Request Objects
# Creating and using a Request object
from urllib2 import Request, urlopen
web_url = 'http://m.example.com/some-page'
request = Request(web_url)
response = urlopen(request)
page_content = response.read()
Request Class Parameters
The Request class accepts several parameters:
- URL - The target URL as a string
- data - Additional data to send to the server (for POST requests)
- headers - Dictionary of HTTP headers
- origin_req_host - The originating request host (optional)
- unverifiable - Whether the request is unverifiable (optional)
POST Request Example
# Sending POST data
from urllib2 import Request, urlopen
from urllib import urlencode
target_url = 'http://www.example.com/submit-form'
form_values = {
'name': 'John Doe',
'location': 'New York',
'language': 'Python'
}
post_data = urlencode(form_values)
request = Request(target_url, post_data)
response = urlopen(request)
page_content = response.read()
Adding Custom Headers
# Request with custom headers
from urllib2 import Request, urlopen
from urllib import urlencode
target_url = 'http://www.example.com/submit-form'
browser_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
form_values = {
'name': 'Jane Smith',
'email': 'jane@example.com'
}
headers = {'User-Agent': browser_agent}
post_data = urlencode(form_values)
request = Request(target_url, post_data, headers)
response = urlopen(request)
page_content = response.read()
Adding Headers to Requests
# Adding headers to a request
from urllib2 import Request, urlopen
request = Request('http://www.example.com/')
request.add_header('Referer', 'http://www.python.org/')
response = urlopen(request)
Global Opener Configuration
# Configuring global opener
from urllib2 import Request, urlopen, build_opener, install_opener
request = Request('http://www.python.org/')
opener = build_opener()
install_opener(opener)
response = urlopen(request)
Error Handling
When making HTTP requests, various errors can occur. urllib2 provides specific exception classes:
- URLError - For general URL-related errors
- HTTPError - For HTTP-specific errors (404, 403, etc.)
# Handling HTTP errors
from urllib2 import urlopen, URLError, HTTPError
try:
response = urlopen('http://www.example.com/nonexistent-page')
page_content = response.read()
except HTTPError as e:
print 'HTTP Error:', e.code, e.reason
except URLError as e:
print 'URL Error:', e.reason
Summary of When to Use Each Library
- urllib.urlretrieve() - Best for simple file downloads where you don't need to process the content
- urllib2 with Request objects - Ideal for forms, authentication, and requests requiring custom headers
- urllib.urlencode() - Use when encoding dictionary data for URL parameters
requests Library
requests is a third-party library that builds on urllib3, inheriting all its features while adding convenience:
- HTTP connection keep-alive and connection pooling
- Cookie session support
- File upload capabilities
- Automatic response encoding detection
- International URL support
- Automatic POST data encoding
Basic requests Usage
# Basic requests usage
import requests
# GET request
response = requests.get('http://www.example.com/users')
# POST request
data = {'first_name': 'John', 'last_name': 'Doe', 'pwd': 'password123'}
response = requests.post('http://www.example.com/users', data=data)
# Other HTTP methods
response = requests.put('http://www.example.com/users/update')
response = requests.delete('http://www.example.com/users/delete')
# Accessing response data
if response.headers['content-type'] == 'application/':
_data = response.()
else:
text_data = response.text
requests Features
- International domain and URL support
- Keep-Alive and connection pooling
- Persistent cookie sessions
- Browser-style SSL verification
- Basic/Digest authentication
- Cookie handling
- Automatic decompression
- Unicode response bodies
- Multipart file uploads
- Connection timeouts
- .netrc support
- Thread safety
Installation
requests is not part of Python's standard library and must be installed separately:
# Using pip
pip install requests
# Using easy_install
easy_install requests
Limitations
While requests offers many conveniences, it has some limitations:
- Not designed for asynchronous calls
- Can be slower than urllib for certain operations
- Standard urllib can be used as an alternative