Gastbeitrag von Pit
Hand auf’s Herz: Amazon-Preise sind nicht selten die günstigsten auf dem Markt. Es gibt eine Menge Gründe, dort nicht zu kaufen. Am Ende siegt aber der Wunsch, zu sparen. Da es aber lästig ist, Amazon für jeden gewünschten Artikel aktiv im Browser aufzurufen, war ich auf der Suche nach einer Lösung, die mich automatisch informiert, sobald dort ein Artikelpreis reduziert wird.
Durch eine Web-Recherche stieß ich auf ein YouTube-Video des indischen Users BugsWriter:
BugsWriter erklärt darin, wie man mit den Entwickler-Tools des Browsers css-Klassen oder -IDs identifiziert und danach mit dem Programm pup filtert. Im Video demonstriert er das anhand einer Amazon-Artikelseite, aus der er den Preis ohne Punkt oder Komma und Cent-Beträge extrahiert und in eine Variable schreibt. Ein paar Script-Zeilen mehr lösen nur dann einen solchen Info-Dialog via notifly-send aus, wenn der hinterlegte Preis unterboten wurde:

Das Script
#!/bin/bash
# TUTORIAL => https://youtu.be/mtDoQDp0nj8
# Check: pup installiert?
command -v pup >/dev/null 2>&1 || { echo -e >&2 "++++++++++\n\nBenötigt wird die cli-Anwendung pup (zum "parsing" von html),\nes ist aber nicht installiert.\nAbbruch.\n\n++++++++++"; exit 1; }
### als ALTERPREIS nur Euro-Wert ohne Punkt/Komma und Cents !! ###
### start edit ###
ARTIKEL="HIER ARTIKEL-BEZEICHNUNG"
URL="HIER AMAZON URL"
ALTERPREIS=00
### stop editing below ###
userid=$(id -u)
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$userid/bus"
export DBUS_SESSION_BUS_ADDRESS
webpage=$(curl -s $URL --compressed -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0')
NEUERPREIS=$(echo $webpage | pup 'span[class="a-price-whole"] text{}' | sed -e 's/\.//' | head -n 1)
(( $NEUERPREIS < $ALTERPREIS )) && notify-send -i kalarm -a "REDUZIERT VON $ALTERPREIS € auf $NEUERPREIS €!" "$ARTIKEL" "<a href='$URL'>zum Amazon Angebot ...</a>" -t 0 -A OK
Variablen befüllen
Es sind nur drei Variablen zu befüllen:
- Artikelbezeichnung
- URL
- zu unterbietender Preis (ohne Punkt/Komma und Cents)
Die URL kann kurz gehalten werden. Beispiel:
Statt (lang)https://www.amazon.de/Blue-interne-Festplatte-Lese-Schreibgeschwindigkeit/dp/B073SBQMCX?ref_=Oct_DlandingS_D_8e8139b6_0
reicht auch (kurz)https://www.amazon.de/dp/B073SBQMCX
In der URL gelöscht ist die Artikelbezeichnung hinter amazon.de und beginnend mit ?ref alles was folgt.
Das Script als Muster abspeichern in einem Verzeichnis, das im Pfad enthalten ist (Check via echo $PATH) – z.B. unter dem Namen amazon-template, ausführbar machen mit chmod +x amazon-template und bei Bedarf mit zum Artikel passendem Namen kopieren und in der Kopie die drei Variablen korrigieren.
Zeitgesteuert …
Das Ganze als Cronjob konfigurieren und fertig:
Scraping Amazon Artikel, filtern nach Preis mittels pup und informiert via notify-send, wenn Preis kleiner als x:
30 */1 * * * /usr/bin/bash /home/pit/.local/bin/artikel1 >> /home/pit/.crontab.log 2>&1 30 */1 * * * /usr/bin/bash /home/pit/.local/bin/artikel2 >> /home/pit/.crontab.log 2>&1 30 */1 * * * /usr/bin/bash /home/pit/.local/bin/artikel3 >> /home/pit/.crontab.log 2>&1
Ich nutze Siduction (Distribution basierend auf Debian Unstable/Sid). Das Konsolenprogramm pup lässt sich über die Debian Paketverwaltung installieren. Ich hoffe aber, dass das oben beschriebene auch in anderen Umgebungen funktioniert. Kommentiert gern auch dann, wenn ihr auf Probleme stoßt.
Nochmals kurz zurück an alle, für die ein Einkauf bei Amazon moralisch schwierig ist: Das oben beschriebene lässt sich auf alle möglichen Websites/Shops bezogen anwenden. Amazon an dieser Stelle bitte nur exemplarisch verstehen.
Foto von Markus Winkler auf Unsplash

Für alle die mehr als nur einen Artikel begutachten wollen.
Zur aller erst würde ich eine CSV-Datei anlegen mit den gewünschten URLs;Beschreibung;Wunsch-Preis.
Beispiel der CSV-Datei mit dem Namen “AmazonProductList.csv” und der Inhalt:
Jetzt das Bash-Skript mit folgenden Namen “AmazonPriceInformerLoop.sh” und der Inhalt:
#!/bin/bash function checkMyPrice() { #$0 - Bash-Skript-Name URL="$1" ARTIKEL="$2" ALTERPREIS="$3" # curl - sollte installiert sein webpage=$(curl -Ss ${URL} -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0') # HTML-TAG (Einfacher): <span class="a-offscreen">....€</span> CLASSNAME="a-offscreen" # Filter den neuen Preis von der Webseite: NEUERPREIS=$( printf "%s" "${webpage}" | awk -F'<span class|</span>' '/class/ && /'${CLASSNAME}'/ {print $2}' | grep -i "${CLASSNAME}" | uniq | awk -F'>' '{print $2}' ) # Filter egrep: Entferne alles, aber lasse jede Ziffer stehen # Filter tr -d: Entferne jegliche Leerzeichen zwischen den Ziffern altpreis=$( echo "${ALTERPREIS}" | egrep -oE '[0-9]+' | tr -d [[:space:]] ) neupreis=$( echo "${NEUERPREIS}" | egrep -oE '[0-9]+' | tr -d [[:space:]] ) # Bedingung ob der neue Preis den alten unterboten hat. (( ${altpreis} > ${neupreis} )) && echo -e "${ARTIKEL}\n\nAlter-Preis: ${ALTERPREIS} \nNeuer-Preis: ${NEUERPREIS}" || echo "Produkt '${ARTIKEL}' selber Preis." } if [[ $# -ne 1 ]]; then echo "[Error] - No filename given as argument" exit 0 fi FILENAME=$( printf "%s" "$1" ) while read -r line; do URL=$( printf '%s' "${line}" | cut -sd ';' -f1 ) ARTIKEL=$( printf '%s' "${line}" | cut -sd ';' -f2 ) ALTERPREIS=$( printf '%s' "${line}" | cut -sd ';' -f3 ) checkMyPrice "$URL" "$ARTIKEL" "$ALTERPREIS" echo "---" done < "${FILENAME}"Dateinamen von beiden können den wünschen der Personen angepasst werden.
Jetzt folgt der aufruf:
Ausgabe wäre folende:
Das wäre es gewesen.
Dies habe ich nur verfasst, da ich weiter unten von “@tux nix” gelesen habe, wie er alles doppelt und dreifach geschrieben hat. Wollte ich eine kleine Alternative für Ihn anbieten.
Schöne Grüße
Für die Ubuntu 22.04.2 LTS Gnome kann folgende Notification benutzt werden im Script.
Einfach folgende Zeile entfernen:
(( ${altpreis} > ${neupreis} )) && echo -e "${ARTIKEL}\n\nAlter-Preis: ${ALTERPREIS} \nNeuer-Preis: ${NEUERPREIS}" || echo "Produkt '${ARTIKEL}' selber Preis."und mit dieser Zweizeilen ersetzen:
(( ${altpreis} > ${neupreis} )) && notify-send -u normal -t 2000 -a "myownscript" -c "MyOwnBashScript" "${ARTIKEL}" "REDUZIERT VON ${ALTERPREIS} auf ${NEUERPREIS} ! Zum Angebot: $URL"Folgende Zeile kann dann auch noch gelöscht werden:
Wenn man die Notification von ubuntu nutzen möchte.
Hinweis:
Das solls gewesen sein. Cron-Tab und price.timer wurden zu genüge erklärt weiter unten.
Einen schönen Tag auch wenn es gerade nur regnet.
Ich habe mal das Skript ausprobiert und es können 3 Zeilen entfernt werden.
Wer außerdem nicht pup installieren möchte und nur mit Linux Board-Mitteln agieren möchte.
Dem würde ich folgenden Befehl “awk” ans Herz legen.
Dieses Angepasste Skript ist genauer – Jetzt kann der Preis normal angegeben werden.
z.B.:
ALTERPREIS: 45,99 € -> wird gefiltert -> 4599
NEUERPREIS: 100,89 € -> wird gefiltert -> 10089
#!/bin/bash URL="https://www.amazon.de/dp/B08C1KN5J2" ARTIKEL="Fire TV Stick mit Alexa" ALTERPREIS="45,99 €" webpage=$(curl -Ss $URL -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0') CLASSNAME="a-offscreen" NEUERPREIS=$( printf "%s" "${webpage}" | awk -F'<span class|</span>' '/class/ && /'${CLASSNAME}'/ {print $2}' | grep -i "${CLASSNAME}" | uniq | awk -F'>' '{print $2}' ) # Filter: Nur zahlen erkennen und alles andere ignorieren altpreis=$( echo "${ALTERPREIS}" | egrep -oE '[0-9]+' | tr -d [[:space:]] ) neupreis=$( echo "${NEUERPREIS}" | egrep -oE '[0-9]+' | tr -d [[:space:]] ) (( ${altpreis} > ${neupreis} )) && echo -e "${ARTIKEL}\n\nAlter-Preis: ${ALTERPREIS} €\nNeuer-Preis: ${NEUERPREIS}" || echo "Produkt '${ARTIKEL}' selber Preis."Und dabei lernte ich noch das “awk” noch einen Kniff hat. Einfach mal googlen oder andere Suchmaschine:
awk -F'[<>]' '/Filter/ {getline; print $0}Genial. Dann noch etwas “cut | sed | grep”, wie es einem beliebt.
Würde mich mehr über Skripte freuen, um neue Wege des Skripting zu gehen.
Schöne Grüße
Ich kenne mich mit awk so gut wie gar nicht aus und bin beeindruckt darüber, wie kompakt dein Script ist. Cool auch, dass es die kompletten Beträge inkl. Cent ausspielt. Die 3 Zeilen aus meinem Script, die du entfernt hast, brauche ich, damit notify-send funktioniert.
Das unterschreibe ich gern!
Ich hätte für Dich noch einen kleinen Trick.
Deine Code Zeilen
Ändern in
Sieht für mich entspannter aus. Aber das ist mein Look-And-Feel, dass muss anderen nicht zu sagen. Nur als Ergänzung – Falls es dich gewurmt hat, dass es ein drei Zeiler ist statt einer Zeile.
Danke für Deinen @pit_ Positiven feedback.^^
Also ich habe bisher als bekennender, glücklicher Konsumsklave von Amazon, die Erfahrung gemacht, dass Amazon häufig nicht das günstigste Angebot hat und dass das gleiche Produkt von Drittanbietern (auch auf Amazon) oder bei ebay günstiger ist. Kann sein, weil ich bisher ein solches Script nicht hatte. Aber Amazon hat – für mich – einen derzeit noch ungeschlagenen Vorteil: Service, der seinen Namen auch verdient hat. Mit Zustellungen durch Amazon selbst hat es bei mir noch nie(!) Probleme gegeben, ganz im Gegensatz zu DHL, DPD und kürzlich auch UPS. Im letzteren Fall hat Amazon trotz direkter Bestellung diesen für die Zustellung beauftragt gehabt (was vorkommt). Prompt gab es Probleme. In den Amazon-Service-Chat gut vorbeireitet gegangen, Problem geschildert, “Einen Moment bitte”, ein paar Minuten gewartet, “Vielen Dank, dass Sie einen Moment gewartet haben. Wir konnten das Problem nachvollziehen. Ersatzlieferung kommt morgen bei Ihnen an”. Ich war baff! Und dem war auch noch so! Am nächsten Tag war die Ersatzlieferung da. Sowas hab ich noch selten erlebt. Von meinen Erfahrungen mit dem DHL-Service wo ich frech angelogen wurde (alles dokumentiert!) ganz zu schweigen.
Ja, Amazon ist pöse. Nicht ganz so pöse wie Putin, aber pöse. Für mich als Kunde aber das kleinere Übel, von dem ich mich wenigstens nicht verarscht fühle.
In einem der youtube-Kanäle von ARTE kam kürzlich ein Beitrag der Amazon ganz fiese Kundenfang-Methoden mit Suchtpotential attestiert. Kann ich für mich nicht nachvollziehen. Das PRIME-Angebot lehne ich immer ab. Und ich kann wochen- und monatelang überleben ohne was bei Amazon zu bestellen. Häufig hilft mir Amazon sogar Geld zu sparen indem ich dort gerade nichts einkaufe.
Hallo Pit,
mal wieder etwas Nettes aus deiner “Werkstatt”.
Du weißt ich mag die Kommandozeile und RegEx, deshalb ein Änderungsvorschlag zu Zeile 18 im Skript.
NEUERPREIS=$(echo [...] text{}' | cut -s -d, -f1 | sed -e 's/^ *//' -e 's/\.//' | head -n 1Die Änderung erfolgt nach ” text{}’ |”
Da sowieso cut benutzt wird, gleich zu Beginn. Die zusätzliche Option “-s” gibt nur Trefferzeilen aus und dann nur das, was vor dem Komma steht. Damit entfällt die Suche nach und das Ersetzen von “€”.
Es reicht ein sed Aufruf, dem mit der Option “-e” die auszuführenden Befehle mitgegeben werden.
Ersterer entfern alle Leerzeichen am Anfang der Zeile (Das “g” ist nicht notwendig, da wir nur am Anfang suchen.), der zweite entfernt den tausender Punkt (Auch hier kein “g”, das reicht für Beträge bis 999.999,99 €).
Bei Tests fand ich Webseiten, die den Preis mit dem Suchmuster von pup mehrfach enthielten. Beispiel:
das produziert bei dem Test “(( $NEUERPREIS < $ALTERPREIS ))” einen Fehler.
Deshalb die Erweiterung um “head -n 1”.
Moin @akli – freue mich, von dir zu lesen! Danke für deine Tipps! Ich konnte (auch wegen @tuxnix’ Kommentar) das pup-Kommando verschlanken und auf eines reduzieren. Damit erübrigt sich cut u. auch sed ist nur noch einmal notwendig: Für den Tausenderpunkt. Hier habe ich sed so wie von dir empfohlen verwendet u. am Ende auch nach head gepiped. Ferdinand baut das oben alles ein.
Ich habe das script noch um 3 weitere Anbieter erweitert. Nur Amazon ist dann doch ein bisschen wenig gewesen. Und dabei stellte sich dann heraus, dass Amazon bei diesem Produkt im Vergleich sogar das teuerste Angebot von allen hatte. Vielleicht hat ja noch jemand Spaß daran und erweitert das script noch um eins zwei weitere Händler.
pup macht Spaß. 😉
#!/bin/bash
#file -> /usr/local/bin/priceinfo
# TUTORIAL => https://youtu.be/mtDoQDp0nj8
# siehe Artikel => https://linuxnews.de/hausgemachter-preisalarm-fuer-amazon-artikel/
### als LIMIT nur Euro-Wert ohne Punkt/Komma und Cents !!
# Amazon
ARTIKEL1=”WD-Blue SSD 2,5” 1TB”
URL1=”https://www.amazon.de/dp/B073SBQMCX”
LIMIT1=100
# Reichelt
ARTIKEL2=”WD-Blue SSD 2,5” 2TB”
URL2=”https://www.reichelt.de/wd-blue-3d-ssd-2-tb-wds200t2b0a-p209968.html?r=1″
LIMIT2=160
# Saturn
ARTIKEL3=”WD-Blue SSD 2,5” 4TB”
URL3=”https://www.saturn.de/de/product/_wd-3d-nand-2582198.html”
LIMIT3=340
# Mediamarkt
ARTIKEL4=”WD-Blue SSD 2,5” 1TB”
URL4=”https://www.mediamarkt.de/de/product/_wd-blue-sa510-wds100t3b0a-ssd-1-tb-ssd-sata-6-gbps-25-zoll-intern-2813150.html”
LIMIT4=80
#PAGES
PAGE1=$(curl -s $URL1 –compressed -H ‘User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0’)
PRICE1=$(echo $PAGE1 | pup ‘span#tp_price_block_total_price_ww’ | pup ‘span.a-offscreen text{}’ | grep € | sed ‘s/^..//g’ | sed ‘s/ €//g’ | cut -d, -f1)
PAGE2=$(curl -s $URL2 –compressed -H ‘User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0’)
PRICE2=$(echo $PAGE2 | pup ‘div[class=”av_price”] text{}’ | grep , | sed ‘s/,//g’)
PAGE3=$(curl -s $URL3 –compressed -H ‘User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0’)
PRICE3=$(echo $PAGE3 | pup ‘span[class=”sc-hLBbgP hyJOYg”] text{}’ | sed ‘s/€ //g’ | sed ‘s/,//g’ )
PAGE4=$(curl -s $URL4 –compressed -H ‘User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0’)
PRICE4=$(echo $PAGE4 | pup ‘span[class=”sc-hLBbgP gdjA-dX”] text{}’ | sed ‘s/€ //g’ | sed ‘s/,//g’ )
#dbus
userid=$(id -u)
DBUS_SESSION_BUS_ADDRESS=”unix:path=/run/user/$userid/bus”
export DBUS_SESSION_BUS_ADDRESS
#Messages
if [ $PRICE1 -le $LIMIT1 ]; then
echo “$ARTIKEL1 für $PRICE1,- => $URL1” && notify-send -a “Preisinfo” “$ARTIKEL1 – $PRICE1 €” “<a href=’$URL1′>Amazon</a>” -t 0 -A OK
fi
if [ $PRICE2 -le $LIMIT2 ]; then
echo “$ARTIKEL2 für $PRICE2,- => $URL2” && notify-send -a “Preisinfo” “$ARTIKEL2 – $PRICE2 €” “<a href=’$URL2′>Reichelt</a>” -t 0 -A OK
fi
if [ $PRICE3 -le $LIMIT3 ]; then
echo “$ARTIKEL3 für $PRICE3,- => $URL3” && notify-send -a “Preisinfo” “$ARTIKEL3 – $PRICE3 €” “<a href=’$URL3′>Saturn</a>” -t 0 -A OK
fi
if [ $PRICE4 -le $LIMIT4 ]; then
echo “$ARTIKEL4 für $PRICE4,- => $URL4” && notify-send -a “Preisinfo” “$ARTIKEL4 – $PRICE4 €” “<a href=’$URL4′>Mediamarkt</a>” -t 0 -A OK
fi
Alternativ zu den cronjobs die im Artikel beschrieben werden kann auch ein systemd service/timer eingesetzt werden.
Service:
#file-> ~/.config/systemd/user/priceinfo.service
[Unit]
Description=priceinfo
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/priceinfo
[Install]
WantedBy=basic.target
Timer:
#file-> ~/.config/systemd/user/priceinfo.timer
[Unit]
Description=preisinfo
[Timer]
OnCalendar=09:15:00
#OnCalendar=daily
Persistent=true
#OnBootSec=20m
[Install]
WantedBy=basic.target
Die Orte und Namen unter denen die Dateien jeweils abgespeichert werden sollten , hab ich oben in den Dateien notiert: #file->
Das script wird wie immer ausführbar gemacht mit:
sudo chmod +x /usr/local/bin/priceinfo
Der Timer wird aktiviert mit dem Befehl:
systemctl –user enable –now priceinfo.timer
Spannend!
Ich habe das mal ausprobiert. Copy & paste aus dem Kommentar erfordert allerdings Nacharbeit, da der Blog z.B. Gänsefüßchen und Hochkomma typografisch umgewandelt und damit das Script zerhaut.
Dein Ansatz ist insgesamt cool:
Ein Artikel, mehrere Anbieter. Das Preislimit u. die Artikelbezeichnung würde ich dann nur noch einmal hinterlegen u. ggf. Variablen für die verschiedenen Anbieter einbauen.
Dein alternativer pup-Aufruf (mit eckigen Klammern) hat mir auch geholfen. Der macht’s am Ende deutlich einfacher. (“pup ‘span[class=”…”] text{}’ “)
Der eingebaute Editor funktioniert bei mehreren Codeblöcken in einen post offenbar nicht so wie er soll. Beim Absenden war der code noch markiert, bei der Ausgabe des Post waren sie weg.
Sorry, wenn du jetzt nacharbeiten musst.
Ja, man kann an dem Script noch weiter stricken. Ich bin mal gespannt darauf, wohin das noch führen wird. 😉
P.S.: Beim letzten Befehl müssen jeweils 2 Bindestriche vor user und now gesetzt werden!:
systemctl --user enable --now priceinfo.timer-> akli 👍
„Isch ‘abe gar kein Amazon, Signorina.“
In Anspielung auf eine Werbung von vor über dreißig Jahren.
> Es gibt eine Menge Gründe, dort nicht zu kaufen.
Und die sollten überwiegen 😉 Es _gibt_ andere, die es besser machen (vermutlich fast alle).
Aber interessanter Artikel – _pup_ kennengelernt.
Das Script wirft hier leider einen Fehler. Preis auf der Webseite ist 1.699,00€
1.699 1.699
./preisalarm.sh: Zeile 21: ((: 1.699
1.699 < 1699 : Syntaxfehler: Ungültiger arithmetischer Operator. (fehlerverursachendes Zeichen ist “.699
1.699 < 1699 “)
Lösung:
Siehe mein Kommentar von 16. Juni 2023 14:02 und den von tux nix 16. Juni 2023 7:47
Er hat das Skript auf verschiedene Webseiten angepasst und es in den systemd integriert.
Danke für den Hinweis, @Stefan. Grund für den Fehler ist der Tausenderpunkt. Bei meinen Tests war kein Artikel > 999 dabei. Der Punkt kann mit einem zusätzlichen sed leicht eliminiert werden. Ich habe Ferdinand ein Update für das Script geschickt, das er in Kürze oben einbauen wird.
Immer wieder toll zu erleben. Zusammen wird es meist noch besser.
Dank an Pit, Stefan, Tux nix und natürlich Ferdinand
> Nochmals kurz zurück an alle, für die ein Einkauf bei Amazon moralisch schwierig ist:
Ich nehme nicht an, dass andere Händler “moralisch” besser sind. Aber Amazon ist für den Kunden praktisch.