Einführung
Die Python-Bibliothek requests ist ein leistungsstarkes Werkzeug für die Interaktion mit Webdiensten und APIs. In diesem Tutorial lernen Sie, wie Sie HTTP-Anfragen senden und Antwortdaten mit Python parsen. Am Ende dieses Labors werden Sie in der Lage sein, wertvolle Informationen aus verschiedenen Arten von API-Antworten zu extrahieren, wodurch Sie datengesteuerte Anwendungen erstellen und Webinteraktionen automatisieren können.
Installation der Requests-Bibliothek und Erstellen einer einfachen Anfrage
In diesem ersten Schritt installieren wir die Python-Bibliothek requests und erstellen unsere erste HTTP-Anfrage, um Daten von einer öffentlichen API abzurufen.
Installieren von Requests
Die requests-Bibliothek ist ein Drittanbieter-Paket, das mit pip, dem Paketinstallationsprogramm von Python, installiert werden muss. Beginnen wir mit der Installation:
pip install requests
Sie sollten eine Ausgabe sehen, die bestätigt, dass requests erfolgreich installiert wurde.
Erstellen Ihrer ersten HTTP-Anfrage
Erstellen wir nun eine Python-Datei, um eine einfache HTTP-Anfrage zu erstellen. Erstellen Sie in der WebIDE eine neue Datei namens basic_request.py im Verzeichnis /home/labex/project.
Fügen Sie der Datei den folgenden Code hinzu:
import requests
## Make a GET request to a public API
response = requests.get("https://jsonplaceholder.typicode.com/todos/1")
## Print the status code
print(f"Status code: {response.status_code}")
## Print the raw response content
print("\nRaw response content:")
print(response.text)
## Print the response headers
print("\nResponse headers:")
for header, value in response.headers.items():
print(f"{header}: {value}")
Dieser Code sendet eine GET-Anfrage an einen Beispiel-API-Endpunkt und gibt Informationen über die Antwort aus.
Verstehen des Response-Objekts
Lassen Sie uns den Code ausführen, um zu sehen, welche Informationen wir zurückbekommen. Führen Sie im Terminal Folgendes aus:
python basic_request.py
Sie sollten eine Ausgabe ähnlich dieser sehen:
Status code: 200
Raw response content:
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
Response headers:
Date: Mon, 01 Jan 2023 12:00:00 GMT
Content-Type: application/json; charset=utf-8
...
Das Response-Objekt enthält mehrere wichtige Attribute:
status_code: HTTP-Statuscode (200 bedeutet Erfolg)text: Der Antwortinhalt als Zeichenkette (String)headers: Ein Dictionary der Antwort-Header
Bei der Arbeit mit Webanfragen helfen Ihnen diese Attribute, die Antwort des Servers zu verstehen und entsprechend zu behandeln.
HTTP-Statuscodes
HTTP-Statuscodes geben an, ob eine Anfrage erfolgreich war oder fehlgeschlagen ist:
- 2xx (wie 200): Erfolg
- 3xx (wie 301): Weiterleitung (Redirection)
- 4xx (wie 404): Client-Fehler
- 5xx (wie 500): Server-Fehler
Ändern wir unseren Code, um auf eine erfolgreiche Antwort zu prüfen. Erstellen Sie eine neue Datei namens check_status.py mit diesem Inhalt:
import requests
try:
## Make a GET request to a valid URL
response = requests.get("https://jsonplaceholder.typicode.com/todos/1")
## Check if the request was successful
if response.status_code == 200:
print("Request successful!")
else:
print(f"Request failed with status code: {response.status_code}")
## Try an invalid URL
invalid_response = requests.get("https://jsonplaceholder.typicode.com/invalid")
print(f"Invalid URL status code: {invalid_response.status_code}")
except requests.exceptions.RequestException as e:
print(f"An error occurred: {e}")
Führen Sie diesen Code aus, um zu sehen, wie verschiedene URLs unterschiedliche Statuscodes zurückgeben:
python check_status.py
Sie sollten sehen, dass die gültige URL den Statuscode 200 zurückgibt, während die ungültige URL den Statuscode 404 zurückgibt.
Parsen von JSON-Antwortdaten
Viele moderne APIs geben Daten im JSON-Format (JavaScript Object Notation) zurück. In diesem Schritt lernen Sie, wie Sie JSON-Antworten parsen und mit den Daten in Python arbeiten.
Verstehen von JSON
JSON ist ein leichtgewichtiges Datenaustauschformat, das für Menschen leicht zu lesen und zu schreiben ist und für Maschinen leicht zu parsen und zu generieren ist. Es basiert auf Schlüssel-Wert-Paaren, ähnlich wie Python-Dictionaries.
Hier ist ein Beispiel für ein JSON-Objekt:
{
"name": "John Doe",
"age": 30,
"email": "john@example.com",
"is_active": true,
"hobbies": ["reading", "swimming", "cycling"]
}
Parsen von JSON-Antworten
Die requests-Bibliothek vereinfacht das Parsen von JSON-Antworten mit der Methode .json(). Erstellen wir eine neue Datei namens parse_json.py und fügen Sie den folgenden Code hinzu:
import requests
## Make a request to a GitHub API endpoint that returns JSON data
response = requests.get("https://api.github.com/users/python")
## Check if the request was successful
if response.status_code == 200:
## Parse the JSON response
data = response.json()
## Print the parsed data
print("Parsed JSON data:")
print(f"Username: {data['login']}")
print(f"Name: {data.get('name', 'Not provided')}")
print(f"Followers: {data['followers']}")
print(f"Public repositories: {data['public_repos']}")
## Print the type to verify it's a Python dictionary
print(f"\nType of parsed data: {type(data)}")
## Access nested data
print("\nAccessing specific elements:")
print(f"Avatar URL: {data['avatar_url']}")
else:
print(f"Request failed with status code: {response.status_code}")
Führen Sie dieses Skript aus, um zu sehen, wie die JSON-Daten in ein Python-Dictionary geparst werden:
python parse_json.py
Sie sollten eine Ausgabe sehen, die Informationen über den GitHub-Benutzer anzeigt, einschließlich seines Benutzernamens, der Anzahl der Follower und der Anzahl der Repositorys.
Arbeiten mit Datenlisten
Viele APIs geben Listen von Objekten zurück. Sehen wir uns an, wie man diese Art von Antwort behandelt. Erstellen Sie eine Datei namens json_list.py mit diesem Inhalt:
import requests
## Make a request to an API that returns a list of posts
response = requests.get("https://jsonplaceholder.typicode.com/posts")
## Check if the request was successful
if response.status_code == 200:
## Parse the JSON response (this will be a list of posts)
posts = response.json()
## Print the total number of posts
print(f"Total posts: {len(posts)}")
## Print details of the first 3 posts
print("\nFirst 3 posts:")
for i, post in enumerate(posts[:3], 1):
print(f"\nPost #{i}")
print(f"User ID: {post['userId']}")
print(f"Post ID: {post['id']}")
print(f"Title: {post['title']}")
print(f"Body: {post['body'][:50]}...") ## Print just the beginning of the body
else:
print(f"Request failed with status code: {response.status_code}")
Führen Sie dieses Skript aus, um zu sehen, wie eine Liste von JSON-Objekten verarbeitet wird:
python json_list.py
Sie sollten Informationen über die ersten drei Beiträge sehen, einschließlich ihrer Titel und des Beginns ihres Inhalts.
Fehlerbehandlung beim JSON-Parsen
Manchmal enthält eine Antwort möglicherweise keine gültigen JSON-Daten. Sehen wir uns an, wie man dies elegant handhabt. Erstellen Sie eine Datei namens json_error.py mit diesem Code:
import requests
import json
def get_and_parse_json(url):
try:
## Make the request
response = requests.get(url)
## Check if the request was successful
response.raise_for_status()
## Try to parse the JSON
try:
data = response.json()
return data
except json.JSONDecodeError:
print(f"Response from {url} is not valid JSON")
print(f"Raw response: {response.text[:100]}...") ## Print part of the raw response
return None
except requests.exceptions.HTTPError as e:
print(f"HTTP error: {e}")
except requests.exceptions.RequestException as e:
print(f"Request error: {e}")
return None
## Test with a valid JSON endpoint
json_data = get_and_parse_json("https://jsonplaceholder.typicode.com/posts/1")
if json_data:
print("\nValid JSON response:")
print(f"Title: {json_data['title']}")
## Test with a non-JSON endpoint
html_data = get_and_parse_json("https://www.example.com")
if html_data:
print("\nThis should not print as example.com returns HTML, not JSON")
else:
print("\nAs expected, could not parse HTML as JSON")
Führen Sie dieses Skript aus, um zu sehen, wie verschiedene Arten von Antworten behandelt werden:
python json_error.py
Sie sollten sehen, dass der Code sowohl gültige JSON-Antworten als auch Nicht-JSON-Antworten erfolgreich verarbeitet.
Parsen von HTML-Inhalten mit BeautifulSoup
Bei der Arbeit mit Webdaten werden Sie oft auf HTML-Antworten stoßen. Für das Parsen von HTML ist die Python-Bibliothek BeautifulSoup ein hervorragendes Werkzeug. In diesem Schritt lernen wir, wie man Informationen aus HTML-Antworten extrahiert.
Installieren von BeautifulSoup
Zuerst installieren wir BeautifulSoup und seinen HTML-Parser:
pip install beautifulsoup4
Grundlegendes HTML-Parsen
Erstellen wir eine Datei namens parse_html.py, um eine Webseite abzurufen und zu parsen:
import requests
from bs4 import BeautifulSoup
## Make a request to a webpage
url = "https://www.example.com"
response = requests.get(url)
## Check if the request was successful
if response.status_code == 200:
## Parse the HTML content
soup = BeautifulSoup(response.text, 'html.parser')
## Extract the page title
title = soup.title.text
print(f"Page title: {title}")
## Extract all paragraphs
paragraphs = soup.find_all('p')
print(f"\nNumber of paragraphs: {len(paragraphs)}")
## Print the text of the first paragraph
if paragraphs:
print(f"\nFirst paragraph text: {paragraphs[0].text.strip()}")
## Extract all links
links = soup.find_all('a')
print(f"\nNumber of links: {len(links)}")
## Print the href attribute of the first link
if links:
print(f"First link href: {links[0].get('href')}")
else:
print(f"Request failed with status code: {response.status_code}")
Führen Sie dieses Skript aus, um zu sehen, wie man grundlegende Informationen von einer HTML-Seite extrahiert:
python parse_html.py
Sie sollten eine Ausgabe sehen, die den Seitentitel, die Anzahl der Absätze, den Text des ersten Absatzes, die Anzahl der Links und die URL des ersten Links anzeigt.
Finden bestimmter Elemente
Sehen wir uns nun an, wie man bestimmte Elemente mit CSS-Selektoren findet. Erstellen Sie eine Datei namens html_selectors.py:
import requests
from bs4 import BeautifulSoup
## Make a request to a webpage with more complex structure
url = "https://quotes.toscrape.com/"
response = requests.get(url)
## Check if the request was successful
if response.status_code == 200:
## Parse the HTML content
soup = BeautifulSoup(response.text, 'html.parser')
## Find all quote elements
quote_elements = soup.select('.quote')
print(f"Number of quotes found: {len(quote_elements)}")
## Process the first 3 quotes
print("\nFirst 3 quotes:")
for i, quote_element in enumerate(quote_elements[:3], 1):
## Extract the quote text
text = quote_element.select_one('.text').text
## Extract the author
author = quote_element.select_one('.author').text
## Extract the tags
tags = [tag.text for tag in quote_element.select('.tag')]
## Print the information
print(f"\nQuote #{i}")
print(f"Text: {text}")
print(f"Author: {author}")
print(f"Tags: {', '.join(tags)}")
else:
print(f"Request failed with status code: {response.status_code}")
Führen Sie dieses Skript aus, um zu sehen, wie man CSS-Selektoren verwendet, um bestimmte Elemente zu extrahieren:
python html_selectors.py
Sie sollten eine Ausgabe sehen, die Informationen über die ersten drei Zitate anzeigt, einschließlich des Zitattests, des Autors und der Tags.
Erstellen eines einfachen Web Scrapers
Lassen Sie uns alles zusammenfügen, um einen einfachen Web-Scraper zu erstellen, der strukturierte Daten von einer Webseite extrahiert. Erstellen Sie eine Datei namens quotes_scraper.py:
import requests
from bs4 import BeautifulSoup
import json
import os
def scrape_quotes_page(url):
## Make a request to the webpage
response = requests.get(url)
## Check if the request was successful
if response.status_code != 200:
print(f"Request failed with status code: {response.status_code}")
return None
## Parse the HTML content
soup = BeautifulSoup(response.text, 'html.parser')
## Extract all quotes
quotes = []
for quote_element in soup.select('.quote'):
## Extract the quote text
text = quote_element.select_one('.text').text.strip('"')
## Extract the author
author = quote_element.select_one('.author').text
## Extract the tags
tags = [tag.text for tag in quote_element.select('.tag')]
## Add the quote to our list
quotes.append({
'text': text,
'author': author,
'tags': tags
})
## Check if there's a next page
next_page = soup.select_one('.next a')
next_page_url = None
if next_page:
next_page_url = 'https://quotes.toscrape.com' + next_page['href']
return {
'quotes': quotes,
'next_page': next_page_url
}
## Scrape the first page
result = scrape_quotes_page('https://quotes.toscrape.com/')
if result:
## Print information about the quotes found
quotes = result['quotes']
print(f"Found {len(quotes)} quotes on the first page")
## Print the first 2 quotes
print("\nFirst 2 quotes:")
for i, quote in enumerate(quotes[:2], 1):
print(f"\nQuote #{i}")
print(f"Text: {quote['text']}")
print(f"Author: {quote['author']}")
print(f"Tags: {', '.join(quote['tags'])}")
## Save the quotes to a JSON file
output_dir = '/home/labex/project'
with open(os.path.join(output_dir, 'quotes.json'), 'w') as f:
json.dump(quotes, f, indent=2)
print(f"\nSaved {len(quotes)} quotes to {output_dir}/quotes.json")
## Print information about the next page
if result['next_page']:
print(f"\nNext page URL: {result['next_page']}")
else:
print("\nNo next page available")
Führen Sie dieses Skript aus, um Zitate von einer Website zu scrapen:
python quotes_scraper.py
Sie sollten eine Ausgabe sehen, die Informationen über die auf der ersten Seite gefundenen Zitate anzeigt, und die Zitate werden in einer JSON-Datei namens quotes.json gespeichert.
Überprüfen Sie die JSON-Datei, um die strukturierten Daten zu sehen:
cat quotes.json
Die Datei sollte ein JSON-Array von Zitatobjekten enthalten, jedes mit den Eigenschaften Text, Autor und Tags.
Arbeiten mit binären Antwortinhalten
Bisher haben wir uns auf textbasierte Antworten wie JSON und HTML konzentriert. Die requests-Bibliothek kann jedoch auch binäre Inhalte wie Bilder, PDFs und andere Dateien verarbeiten. In diesem Schritt lernen wir, wie man binäre Inhalte herunterlädt und verarbeitet.
Herunterladen eines Bildes
Beginnen wir mit dem Herunterladen eines Bildes. Erstellen Sie eine Datei namens download_image.py:
import requests
import os
## URL of an image to download
image_url = "https://httpbin.org/image/jpeg"
## Make a request to get the image
response = requests.get(image_url)
## Check if the request was successful
if response.status_code == 200:
## Get the content type
content_type = response.headers.get('Content-Type', '')
print(f"Content-Type: {content_type}")
## Check if the content is an image
if 'image' in content_type:
## Create a directory to save the image if it doesn't exist
output_dir = '/home/labex/project/downloads'
os.makedirs(output_dir, exist_ok=True)
## Save the image to a file
image_path = os.path.join(output_dir, 'sample_image.jpg')
with open(image_path, 'wb') as f:
f.write(response.content)
## Print information about the saved image
print(f"Image saved to: {image_path}")
print(f"Image size: {len(response.content)} bytes")
else:
print("The response does not contain an image")
else:
print(f"Request failed with status code: {response.status_code}")
Führen Sie dieses Skript aus, um ein Bild herunterzuladen:
python download_image.py
Sie sollten eine Ausgabe sehen, die bestätigt, dass das Bild heruntergeladen und in /home/labex/project/downloads/sample_image.jpg gespeichert wurde.
Herunterladen einer Datei mit Fortschrittsanzeige
Beim Herunterladen großer Dateien kann es nützlich sein, eine Fortschrittsanzeige anzuzeigen. Erstellen wir ein Skript, das den Download-Fortschritt anzeigt. Erstellen Sie eine Datei namens download_with_progress.py:
import requests
import os
import sys
def download_file(url, filename):
## Make a request to get the file
## Stream the response to handle large files efficiently
response = requests.get(url, stream=True)
## Check if the request was successful
if response.status_code != 200:
print(f"Request failed with status code: {response.status_code}")
return False
## Get the total file size if available
total_size = int(response.headers.get('Content-Length', 0))
if total_size:
print(f"Total file size: {total_size/1024:.2f} KB")
else:
print("Content-Length header not found. Unable to determine file size.")
## Create a directory to save the file if it doesn't exist
os.makedirs(os.path.dirname(filename), exist_ok=True)
## Download the file in chunks and show progress
print(f"Downloading {url} to {filename}...")
## Initialize variables for progress tracking
downloaded = 0
chunk_size = 8192 ## 8 KB chunks
## Open the file for writing
with open(filename, 'wb') as f:
## Iterate through the response chunks
for chunk in response.iter_content(chunk_size=chunk_size):
if chunk: ## Filter out keep-alive chunks
f.write(chunk)
downloaded += len(chunk)
## Calculate and display progress
if total_size:
percent = downloaded * 100 / total_size
sys.stdout.write(f"\rProgress: {percent:.1f}% ({downloaded/1024:.1f} KB)")
sys.stdout.flush()
else:
sys.stdout.write(f"\rDownloaded: {downloaded/1024:.1f} KB")
sys.stdout.flush()
## Print a newline to ensure the next output starts on a new line
print()
return True
## URL of a file to download
file_url = "https://speed.hetzner.de/100MB.bin"
## Path where the file will be saved
output_path = '/home/labex/project/downloads/test_file.bin'
## Download the file
success = download_file(file_url, output_path)
if success:
## Get file stats
file_size = os.path.getsize(output_path)
print(f"\nDownload complete!")
print(f"File saved to: {output_path}")
print(f"File size: {file_size/1024/1024:.2f} MB")
else:
print("\nDownload failed.")
Führen Sie dieses Skript aus, um eine Datei mit Fortschrittsanzeige herunterzuladen:
python download_with_progress.py
Sie sehen eine Fortschrittsanzeige, die sich während des Downloads der Datei aktualisiert. Beachten Sie, dass dies eine 100MB-Datei herunterlädt, was je nach Ihrer Verbindungsgeschwindigkeit einige Zeit dauern kann.
Um den Download abzubrechen, können Sie Strg+C drücken.
Arbeiten mit Antwort-Headern und Metadaten
Beim Herunterladen von Dateien enthalten die Antwort-Header oft nützliche Metadaten. Erstellen wir ein Skript, das Antwort-Header im Detail untersucht. Erstellen Sie eine Datei namens response_headers.py:
import requests
def check_url(url):
print(f"\nChecking URL: {url}")
try:
## Make a HEAD request first to get headers without downloading the full content
head_response = requests.head(url)
print(f"HEAD request status code: {head_response.status_code}")
if head_response.status_code == 200:
## Print all headers
print("\nResponse headers:")
for header, value in head_response.headers.items():
print(f" {header}: {value}")
## Extract content type and size
content_type = head_response.headers.get('Content-Type', 'Unknown')
content_length = head_response.headers.get('Content-Length', 'Unknown')
print(f"\nContent Type: {content_type}")
if content_length != 'Unknown':
size_kb = int(content_length) / 1024
size_mb = size_kb / 1024
if size_mb >= 1:
print(f"Content Size: {size_mb:.2f} MB")
else:
print(f"Content Size: {size_kb:.2f} KB")
else:
print("Content Size: Unknown")
## Check if the server supports range requests
accept_ranges = head_response.headers.get('Accept-Ranges', 'none')
print(f"Supports range requests: {'Yes' if accept_ranges != 'none' else 'No'}")
else:
print(f"HEAD request failed with status code: {head_response.status_code}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
## Check a few different URLs
check_url("https://httpbin.org/image/jpeg")
check_url("https://speed.hetzner.de/100MB.bin")
check_url("https://example.com")
Führen Sie dieses Skript aus, um detaillierte Informationen zu Antwort-Headern anzuzeigen:
python response_headers.py
Sie sehen eine Ausgabe, die die Header für verschiedene Arten von Inhalten anzeigt, einschließlich Bilder, Binärdateien und HTML-Seiten.
Das Verständnis von Antwort-Headern ist für viele Webentwicklungsaufgaben von entscheidender Bedeutung, wie z.B.:
- Bestimmen von Dateitypen und -größen vor dem Herunterladen
- Implementieren von fortsetzbaren Downloads mit Bereichsanforderungen (range requests)
- Überprüfen von Caching-Richtlinien und Ablaufdaten
- Umgang mit Weiterleitungen und Authentifizierung
Zusammenfassung
In diesem Lab haben Sie gelernt, wie Sie mit der Python-requests-Bibliothek arbeiten, um mit Webdiensten und APIs zu interagieren. Sie verfügen nun über die Fähigkeiten, um:
- HTTP-Anfragen zu stellen und Antwortstatuscodes und -fehler zu behandeln
- JSON-Daten aus API-Antworten zu parsen
- Informationen aus HTML-Inhalten mit BeautifulSoup zu extrahieren
- Binäre Inhalte wie Bilder und Dateien herunterzuladen und zu verarbeiten
- Mit Antwort-Headern und Metadaten zu arbeiten
Diese Fähigkeiten bilden die Grundlage für viele Python-Anwendungen, einschließlich Web Scraping, API-Integration, Datenerfassung und Automatisierung. Sie können jetzt Anwendungen erstellen, die mit Webdiensten interagieren, nützliche Informationen von Websites extrahieren und verschiedene Arten von Webinhalten verarbeiten.
Um weiter zu lernen, könnten Sie Folgendes erkunden:
- Authentifizierungsmethoden für den Zugriff auf geschützte APIs
- Arbeiten mit komplexeren APIs, die bestimmte Header oder Anfrageformate erfordern
- Erstellen eines vollständigen Web Scraping-Projekts, das Daten sammelt und analysiert
- Erstellen einer Python-Anwendung, die sich in mehrere APIs integriert
Denken Sie daran, dass es beim Scraping von Websites oder der Verwendung von APIs wichtig ist, die Nutzungsbedingungen zu überprüfen und Ratenbegrenzungen zu respektieren, um eine Blockierung zu vermeiden.



