Forex, auch Devisenhandel genannt, ist ein internationaler Markt, auf dem Menschen verschiedene Währungen elektronisch außerbörslich (OTC) handeln – mit der Besonderheit, dass es keinen zentralen Marktplatz gibt.
Es ist ein bisschen so, als würde man Geld tauschen, wenn man in den Urlaub fährt, nur dass (auf dem Devisenmarkt) Menschen Währungen kaufen und verkaufen, um von Wertänderungen zu profitieren.
Menschen aus aller Welt handeln rund um die Uhr, fünf Tage die Woche, mit Währungen, was ihn zu einem der größten Finanzmärkte der Welt macht. Und wie bei jeder finanziellen Entscheidung helfen Ihnen die richtigen Daten dabei, genaue und profitable Investitionen zu tätigen.
Der Forex-Markt unterliegt starken Schwankungen. Daher verschafft Ihnen die Vorhersage potenzieller Aufwärts- oder Abwärtsbewegungen einen unfairen Vorteil und erzielt die gewünschten Ergebnisse.
In diesem Artikel extrahieren wir Währungsdaten aus Yahoo Finance mit Pythons Requests und Beautiful Soup und exportieren sie mit Pandas in eine CSV-Datei.
Inhaltsverzeichnis
TL;DR über das Scraping von Forex-Daten mit Beautiful Soup (BS4)
Für diejenigen mit Erfahrung gibt es hier die vollständige Codebasis:
import requests
from bs4 import BeautifulSoup
import pandas as pd
forex_data = ()
payload = {
'api_key': 'YOUR_API_KEY',
'country_code': 'us',
'url': 'https://finance.yahoo.com/currencies'
}
response = requests.get('https://api.scraperapi.com', params=payload)
soup = BeautifulSoup(response.content, 'html.parser')
table = soup.find('tbody')
all_currencies = table.select('tr')
for currency in all_currencies:
name = currency.find('td', attrs={'aria-label': 'Name'}).text
last_price = currency.select_one('td(aria-label="Last Price")').text
change = currency.find('td', attrs={'aria-label': 'Change'}).text
percentage = currency.select_one('td(aria-label="% Change") > fin-streamer > span').text
forex_data.append({
'Currency': name,
'Last Price': last_price,
'Change': change,
'% Change': percentage
})
df = pd.DataFrame(forex_data)
df.to_csv('forex.csv', index=False)
Um zu erfahren, wie wir es aufgebaut haben und welchen Denkprozess dahinter steckt, lesen Sie bitte weiter.
1. Grundlegendes zur HTML-Struktur von Yahoo Finance
Bevor wir mit dem Codieren beginnen, werfen wir zunächst einen Blick auf die Währungsseite von Yahoo, um zu verstehen, womit wir es zu tun haben.
Die verfügbaren Währungen auf der Seite scheinen zumindest optisch in einem Tabellenformat angezeigt zu werden.
An dieser Stelle müssen wir zwei Dinge überprüfen:
- Stellen Sie sicher, dass wir aus der rohen HTML-Datei auf diese Daten zugreifen können – mit anderen Worten, dass der Inhalt nicht über AJAX eingefügt wird.
- Stellen Sie sicher, dass der HTML-Code auch als Tabelle strukturiert ist.
Um Nummer eins zu erledigen, kopieren Sie einen der Währungsnamen und klicken Sie mit der rechten Maustaste auf die Seite > Seitenquelle anzeigen.
Jetzt suchen wir nach dem Text, den wir kopiert haben. Wenn es im Quellcode erscheint, können wir die Daten mit einer einfachen Anfrage extrahieren.
Super, wir haben es gefunden! Diese Prüfung ist wichtig, denn wenn der Inhalt über JavaScript eingefügt wird, müssen wir einen anderen Ansatz wählen. Wir könnten beispielsweise auf die „versteckte API“ abzielen, von der die Seite die Daten erhält, wie wir es beim Scrapen dieser dynamischen Tabelle getan haben, oder wir könnten auch einen Headless-Browser wie Selenium oder Puppeteer (Option Node.js) verwenden.
Bei der zweiten Überprüfung werden Sie überrascht sein, wie oft Websites Tabellen ohne das Traditionelle anzeigen table > thead > tbody > tr > td
Wenn Sie also eine Tabelle wie diese finden, überprüfen Sie vor dem Feiern immer den HTML-Code im Browser.
Weitere tolle Neuigkeiten! Die Daten in einer gut strukturierten Tabelle zu haben, erleichtert den gesamten Prozess und wir könnten mit Pandas sogar die gesamte Tabelle extrahieren. In diesem Tutorial verwenden wir jedoch BS4 zum Parsen der Tabelle und verwenden Pandas nur zum Exportieren der Ergebnisse.
Weiter geht's. Jedes tr-Tag stellt eine Zeile in der Tabelle dar – die Sie visuell sehen können, indem Sie mit der Maus darüber fahren.
Jede Zelle wird durch ein td-Tag dargestellt…
… und alle Zeilen befinden sich innerhalb des tbody-Tags.
Das wissend. Ein guter Plan wäre, auf den Körper zu zielen und dann alle Zeilen in einer Variablen zu speichern. Dann können wir die Liste der Zeilen durchlaufen und den Namen, den letzten Preis, die Änderung und die prozentuale Änderung jeder Währung extrahieren.
Nachdem wir nun unseren Spielplan haben, programmieren wir unseren Scraper!
2. Starten des Forex-Datenextraktionsprojekts
Erstellen wir zunächst ein neues Verzeichnis für unser Projekt und unsere Python-Datei. Wir haben unsere forex_scraper.py genannt – sehr originell, oder?
Als nächstes importieren wir alle notwendigen Abhängigkeiten:
import requests
from bs4 import BeautifulSoup
import pandas as pd
Nachdem unsere Abhängigkeiten fertig sind, ist es an der Zeit, unsere Initialen zu senden get()
Anfrage. Obwohl Yahoo Finance über viele öffentliche Daten verfügt, heißt das nicht, dass sie nicht versuchen werden, Ihre Skripte zu blockieren. Wenn Sie Ihre Anfrage direkt von Ihrem Computer aus senden, kann dies dazu führen, dass Ihre IP vorübergehend oder sogar dauerhaft gesperrt wird.
Um dieses Problem zu vermeiden, verwenden wir ScraperAPI, um alle gefundenen Anti-Scraping-Mechanismen zu umgehen und sicherzustellen, dass wir eine erfolgreiche Antwort vom Server erhalten. Machen Sie sich an dieser Stelle keine Gedanken über die Preise, denn der kostenlose Plan bietet Ihnen 5.000 API-Credits für die ersten 7 Tage und 1.000 API-Credits pro Monat.
Erstellen Sie einfach ein kostenloses ScraperAPI-Konto und kopieren Sie Ihren API-Schlüssel. Wir übergeben dann den Schlüssel und unsere Ziel-URL über eine Nutzlast, die als Parameter zum Endpunkt von ScraperAPI hinzugefügt wird:
payload = {
'api_key': 'YOUR_API_KEY',
'country_code': 'us',
'url': 'https://finance.yahoo.com/currencies'
}
response = requests.get('https://api.scraperapi.com', params=payload)
Außerdem verwenden wir die country_code
Parameter, um ScraperAPI anzuweisen, beim Senden unserer Anfragen immer US-Proxys zu verwenden.
Um eine Erfolgsquote von 99,99 % zu gewährleisten, nutzt ScraperAPI maschinelles Lernen und jahrelange statistische Analysen, um die beste Kombination aus IP und Headern auszuwählen und etwaige zusätzliche Komplexitäten zu bewältigen.
Da wir nichts weiter hinzuzufügen haben, senden wir die Anfrage und print()
den Statuscode, um zu überprüfen, ob es funktioniert, indem Sie:
print(response.status_code)
Nachdem Sie das Skript ausgeführt haben, sollte in Ihrem Terminal eine 200 angezeigt werden.
3. Zugriff auf Daten aus der ersten Zelle
Wenn Sie dem folgen, gibt das Skript an dieser Stelle den gesamten Roh-HTML-Code zurück – Sie können ihn sehen, wenn Sie (response) anstelle des status_code ausgeben – wir müssen ihn also mit Beautiful Soup analysieren, um ihn in einen analysierten Code umzuwandeln Baum, der es uns ermöglicht, die verschiedenen Knoten zu durchlaufen und die Daten zu extrahieren.
soup = BeautifulSoup(response.content, 'html.parser'
Jetzt befinden sich alle Knoten in einem Suppenobjekt, auf das wir das verwenden können .find()
Und .select()
Methoden zur gezielten Ausrichtung auf bestimmte Elemente. Nach dem Plan wählen wir nun den Körper des Tisches aus, der dazwischen gewickelt wird
table = soup.find('tbody')
.find()
gibt das erste gefundene Element zurück, und da es nur ein tbody-Element gibt, funktioniert es für uns einwandfrei.
Im Fall der Zeilen möchten wir, dass unser Skript eine Liste mit allen zurückgibt tr
Elemente und nicht nur das erste, also werden wir es verwenden .select()
– das eine Liste aller Elemente zurückgibt, die den von uns übergebenen Kriterien entsprechen – in unserer Tabellenvariablen.
all_currencies = table.select('tr')
Notiz: wir könnten auch das nutzen .find_all()
Methode, aber wir wollen zeigen, wie man beide verwendet.
Nachdem wir nun unsere Zeilenliste haben, können wir jede Zelle durchlaufen und Daten daraus extrahieren. Das heißt, jede Zelle ist eine td
Element, wie können wir unserem Scraper also mitteilen, aus welchen Zellen er die Daten extrahieren soll?
Wenn Sie die Struktur richtig verstanden haben, alle
tags. So we can imagine each row like this:
Jedes Rechteck ist ein td
Element, und die Liste beginnt bei 0. Theoretisch könnten Sie alle td-Tags innerhalb der Zeile als Ziel verwenden und dann jede Spalte anhand ihrer Position im Index auswählen.
Zum Glück offenbart uns eine nähere Betrachtung der Elemente einen einfacheren Weg. Alle Elemente innerhalb der Zeilen haben ein aria-label
Attribut mit einem sehr beschreibenden Wert.
Beispielsweise hat das Währungspaar den Wert „Name“ und der letzte Preis darunter den Wert „Letzter Preis“. Um den Namen jeder Währung anzusprechen, können wir eine Schleife wie diese erstellen:
for currency in all_currencies:
name = currency.find('td', attrs={'aria-label': 'Name'}).text
print(name)
Sie erhalten eine Liste mit 24 Währungen auf Ihrem Terminal ausgedruckt, was bedeutet, dass unser Skript bisher funktioniert!
4. Alle Daten zu einem Array hinzufügen
Die Ausrichtung auf die restlichen Datenpunkte erfolgt nach einem sehr ähnlichen Prozess, jedoch mit einigen geringfügigen Änderungen.
Im Gegensatz zum Währungsnamen befindet sich der Text der Zellen „Letzter Preis“ in einem anderen – seltsam aussehenden – Element innerhalb der Währung td
.
Bei Verwendung des .find()
Methode, es gab das Element zurück, aber wir konnten die Daten damit nicht extrahieren .text
. Stattdessen haben wir die verwendet select_one()
Methode, die eine etwas andere Syntax verwendet, um auf ein einzelnes Element abzuzielen, und es hat funktioniert:
last_price = currency.select_one('td(aria-label="Last Price")').text
Für die Spalte „Änderung“ haben wir die gleiche Methode wie für „Name“ verwendet:
change = currency.find('td', attrs={'aria-label': 'Change'}).text
Und schließlich mussten wir bei der prozentualen Änderung etwas kreativer werden, um das Ziel zu erreichen span
Element, in dem der Text bereitgestellt wird, ohne dass eine Menge geschrieben werden muss .find()
Methoden:
percentage = currency.select_one('td(aria-label="% Change") > fin-streamer > span').text
Notiz: Achten Sie auf die Unterschiede zwischen den find()
Und select()
Methoden, da sie Ihr Hauptwerkzeug zum einfachen Extrahieren von Daten mithilfe von CSS-Selektoren sind.
Da alle Daten von unserem Parser abgerufen werden, fügen wir vor der Nutzlast ein leeres Array hinzu ...
… und nutzen Sie die .append()
Methode zum Formatieren und Speichern aller Daten in forex_data:
forex_data.append({
'Currency': name,
'Last Price': last_price,
'Change': change,
'% Change': percentage
})
Dieses letzte Snippet wird in die for-Schleife eingefügt, nachdem das letzte Element extrahiert wurde. Im Grunde extrahiert unser Skript jedes Element und hängt es dann an das Array an, wobei jedes Element einen Namen hat und das Ganze ein einzelnes Element bildet.
Folgendes erhalten wir nach dem Drucken des Arrays:
(
{
"Currency":"EUR/USD",
"Last Price":"1.1031",
"Change":"-0.0018",
"% Change":"-0.17%"
},
{
"Currency":"USD/JPY",
"Last Price":"133.9490",
"Change":"+0.3320",
"% Change":"+0.25%"
},
{
"Currency":"USD/GBP",
"Last Price":"1.2495",
"Change":"+0.0030",
"% Change":"+0.24%"
},
{
"Currency":"USD/AUD",
"Last Price":"0.6630",
"Change":"+0.0024",
"% Change":"+0.36%"
},
{
"Currency":"USD/NZD",
"Last Price":"0.6148",
"Change":"+0.0029",
"% Change":"+0.48%"
},
{
"Currency":"EUR/JPY",
"Last Price":"147.6980",
"Change":"+0.2040",
"% Change":"+0.14%"
},
{
"Currency":"GBP/JPY",
"Last Price":"167.3310",
"Change":"+0.7770",
"% Change":"+0.47%"
},
{
"Currency":"EUR/GBP",
"Last Price":"0.8826",
"Change":"-0.0027",
"% Change":"-0.31%"
},
{
"Currency":"EUR/CAD",
"Last Price":"1.4996",
"Change":"-0.0051",
"% Change":"-0.34%"
},
{
"Currency":"EUR/SEK",
"Last Price":"11.3484",
"Change":"-0.0526",
"% Change":"-0.46%"
},
{
"Currency":"EUR/CHF",
"Last Price":"0.9858",
"Change":"+0.0024",
"% Change":"+0.24%"
},
{
"Currency":"EUR/HUF",
"Last Price":"373.0700",
"Change":"-0.7500",
"% Change":"-0.20%"
},
{
"Currency":"EUR/JPY",
"Last Price":"147.6980",
"Change":"+0.2040",
"% Change":"+0.14%"
},
{
"Currency":"USD/CNY",
"Last Price":"6.9215",
"Change":"-0.0041",
"% Change":"-0.06%"
},
{
"Currency":"USD/HKD",
"Last Price":"7.8495",
"Change":"+0.0009",
"% Change":"+0.01%"
},
{
"Currency":"USD/SGD",
"Last Price":"1.3348",
"Change":"-0.0005",
"% Change":"-0.03%"
},
{
"Currency":"USD/INR",
"Last Price":"81.6850",
"Change":"-0.0350",
"% Change":"-0.04%"
},
{
"Currency":"USD/MXN",
"Last Price":"18.0482",
"Change":"-0.0895",
"% Change":"-0.49%"
},
{
"Currency":"USD/PHP",
"Last Price":"55.7100",
"Change":"+0.0500",
"% Change":"+0.09%"
},
{
"Currency":"USD/IDR",
"Last Price":"14,699.0000",
"Change":"-130.0000",
"% Change":"-0.88%"
},
{
"Currency":"USD/THB",
"Last Price":"34.0600",
"Change":"+0.1450",
"% Change":"+0.43%"
},
{
"Currency":"USD/MYR",
"Last Price":"4.4600",
"Change":"+0.0050",
"% Change":"+0.11%"
},
{
"Currency":"USD/ZAR",
"Last Price":"18.2845",
"Change":"-0.1103",
"% Change":"-0.60%"
},
{
"Currency":"USD/RUB",
"Last Price":"80.5300",
"Change":"-1.5710",
"% Change":"-1.91%"
}
)
Notiz: Wir haben einen JSON-Formatierer verwendet, um das Ergebnis visuell zu organisieren, da es in Ihrem Terminal ausgedruckt nicht so aussieht. Dennoch kommt es auf die Name:Wert-Organisation an.
5. Exportieren der gecrackten Forex-Finanzdaten in eine CSV-Datei
Hier wird sich unsere Initiative, die Daten in einem Array zu speichern, auszahlen! Da wir die Reihenfolge und alle Informationen bereits in forex_data haben, können wir einfach einen Datenrahmen mit Pandas erstellen:
df = pd.DataFrame(forex_data)
Die Namen werden zu Spalten und jeder Datenpunkt wird unter dem bereits angegebenen liegen.
Für die letzte Berührung verwenden wir die .to_csv()
Methode zum Erstellen der Datei im Verzeichnis unseres Projekts:
df.to_csv('forex.csv', index=False)
Wenn Sie mitgemacht haben, sollte Ihr Projekt so aussehen:
import requests
from bs4 import BeautifulSoup
import pandas as pd
forex_data = ()
payload = {
'api_key': 'YOUR_API_KEY',
'country_code': 'us',
'url': 'https://finance.yahoo.com/currencies'
}
response = requests.get('https://api.scraperapi.com', params=payload)
soup = BeautifulSoup(response.content, 'html.parser')
table = soup.find('tbody')
all_currencies = table.select('tr')
for currency in all_currencies:
name = currency.find('td', attrs={'aria-label': 'Name'}).text
last_price = currency.select_one('td(aria-label="Last Price")').text
change = currency.find('td', attrs={'aria-label': 'Change'}).text
percentage = currency.select_one('td(aria-label="% Change") > fin-streamer > span').text
forex_data.append({
'Currency': name,
'Last Price': last_price,
'Change': change,
'% Change': percentage
})
df = pd.DataFrame(forex_data)
df.to_csv('forex.csv', index=False)
Nachdem Sie dieses Skript ausgeführt haben, finden Sie die folgende CSV-Datei:
Sammeln Sie Forex-Finanzdaten automatisch mit ScraperAPI
Herzlichen Glückwunsch, Sie haben Ihren ersten Forex-Scraper gebaut! Wir hoffen, dass Ihnen dieses Web-Scraping-Tutorial genauso viel Spaß gemacht hat wie uns das Schreiben. Natürlich ist das erst der Anfang.
Wenn Sie beide Male, als wir Ihnen die Ergebnisse angezeigt haben, aufmerksam gemacht haben, sind die Werte für jedes Währungspaar unterschiedlich. Das liegt daran, dass Yahoo Finance die Preise auf der Seite ständig aktualisiert, sodass Sie bei jeder Anfrage einen leicht unterschiedlichen Wert erhalten.
Mit anderen Worten: Der nächste Schritt auf diesem Weg besteht darin, einen Web-Scraping-Planer so einzurichten, dass das Skript einige Male am Tag oder in der Woche automatisch ausgeführt wird. Auf diese Weise können Sie mit der Erstellung historischer Daten beginnen, die Sie in Ihre Handelsalgorithmen einspeisen können.
Ihre Web-Scraping-Lösung bietet keine automatische Scraping-Funktion? Schauen Sie sich ScraperAPI an. Mit unserer DataPipeline-Lösung können Sie bis zu 10.000 URLs termingerecht erfassen und Benachrichtigungen erhalten, wenn die Aufgaben erledigt sind. Melden Sie sich hier bei ScraperAPI an, um es auszuprobieren.
Darüber hinaus können Sie diese Informationen auch vergleichen, indem Sie andere Forex-Datenquellen wie TradingView auswerten. Denken Sie daran: Je mehr Daten Sie haben, desto bessere Vorhersagen können Sie treffen. Beginnen Sie also jetzt mit der Erstellung.
Bis zum nächsten Mal, viel Spaß beim Schaben!