Ergebnis aus Print Funktion in CSV

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
newbieee
User
Beiträge: 7
Registriert: Sonntag 7. März 2021, 13:12

Hallo Zusammen,

ich probiere mich gerade im Web Scraping aus und wollte mir als Test die Preise einer Preisvergleichsseite u.a. über Beautiful Soup ziehen. Da auf einer Seite mehrere Preise in der gleichen Klasse sind, lass ich sie mir alle über soup.findAll ausgeben. Das Problem hierbei ist, dass nicht nur der Preis, sondern noch zusätzlicher Text ausgegeben wird, den ich nicht brauche. Wenn ich das Ergebnis der soup.findAll Funktion jedoch in der Print Funktion ausgebe (s. Code) erhalte ich genau das was ich will, nämlich nur den Preis.
Wie kann ich jetzt das Ergebnis der Print Funktion in meiner CSV speichern? Kann mir da jemand weiter helfen?


...

Code: Alles auswählen

    def getdata(link):
        r=requests.get(f'Link')
        soup = BeautifulSoup(r.text, 'html.parser')
        price = soup.findAll('span', class_= 'Text15')
        for item in price:
            print(f'{item.text:<25}')   ##### Diese Print Funktion gibt mir den Preis, so wie gewünscht #####
        return item
...

Viele Grüße
neeewbie :)
Benutzeravatar
Dennis89
User
Beiträge: 1153
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

Python bietet das 'csv'-Modul an, damit kann man Dateien auslesen oder Daten in Dateien schreiben. Informationen dazu findest du in der Dokumentation ink.Beispiel:
https://docs.python.org/3/library/csv.h ... hlight=csv

Schau mal ob du es damit hinbekommst, ansonsten kannst du dein Problem gern beschrieben.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
newbieee
User
Beiträge: 7
Registriert: Sonntag 7. März 2021, 13:12

Hallo Dennis,

das habe ich schon. Hab es vergessen zu posten... :D

Code: Alles auswählen

    def main():
        results = [getdata(links) for links in links]
        df = pd.DataFrame(results)
        df.to_csv('TESTV3'+ '.csv',index=False)
        return
        
Das Problem ist halt, das ich das aus de print Funktion nicht in die csv bekomme, sondern nur die ganzen Klassseninhalte, die ich durch soup.findAll bekomme.

Also wenn mir jemand sagen kann, wie ich das aus der Print Funktion in eine CSV bekomme, wäre mirt sehr geholfen.

VG
Benutzeravatar
Dennis89
User
Beiträge: 1153
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

du möchtest 'item.text:<25' haben die Funktion gibt aber mit 'return item' nur das 'item' nach dem letzten Schleifendurchlauf zurück. Die Funktion muss dass zurückgeben, das du weiter verarbeiten willst.
Du könntest dir auch die 'items' in eine Leiste schreiben und beim schreiben in die Datei den richtigen Preis aus der Liste aussuchen.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
newbieee
User
Beiträge: 7
Registriert: Sonntag 7. März 2021, 13:12

Hallo Dennis,

ich wollte das Ergebnis aus soup.findAll als Text formatieren, also soupfindAll(...).text. Das geht scheinbar nicht. Wie wäre deine Vorgehensweise? Ich stehe da grad auf dem Schlauch.

VG
Newbie
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Was geht nicht? Mit Dennis` Antwort ist eigentlich alles scho gesagt: Du mußt die Preise in einer Liste speichern.
newbieee
User
Beiträge: 7
Registriert: Sonntag 7. März 2021, 13:12

Ja die Ergebnisse aus der Print Funktion oder nicht? Und die muss ich ja erstmal als Variable definieren um sie in einer Liste zu speichern oder?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Anders herum wird ein Schuh draus. Die print-Funktion hat kein Ergebnis, sondern Du übergibst der print-Funktion einen Wert, den Du statt dessen in einer Liste speichern sollst.
newbieee
User
Beiträge: 7
Registriert: Sonntag 7. März 2021, 13:12

Ja richtig, aber ich formatiere ja meinen Input der Print Funktion mit item.text:<25. Wenn ich das nur mit item mache, also nicht in der Print Klammer, bekomme ich eine Fehlermeldung:
AttributeError: 'list' object has no attribute 'text'
Das Problem kann ich nicht lösen...
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Zeige den Code zur Fehlermeldung.
newbieee
User
Beiträge: 7
Registriert: Sonntag 7. März 2021, 13:12

Fehlermeldung:

Code: Alles auswählen

    results = f'{[getdata(links) for links in links].text:<25}'

AttributeError: 'list' object has no attribute 'text'

Code: Alles auswählen

from requests_html import HTMLSession
import requests
import pandas as pd
from bs4 import BeautifulSoup




def get_links(search): 
    r=s.get('link...')
    links = r.html.find('div.objTabelle2Inhalt tr.objTabelle2 td.objTabelle2Links a.LinkProduct[href]') 
    link=[links.attrs['href'] for links in links if links.attrs['href']!='']   
    return link



def getdata(link): 
    r=requests.get(f'{link]')
    soup = BeautifulSoup(r.text, 'html.parser')
    price = soup.findAll('span', class_= 'Text15')
    for item in price:
        print(f'{item.text:<25}')#{item.next_sibling} # In der Schleife lasse ich mir die Print Funktion ausgeben. Hier erhalte ich genau das, was ich haben will. Das bekomme ich aber nicht unten in die def main(): rein 
    return link
            
             
def main():
    search=' '
    links= get_links(search)
    print(f'Found{len(links)}links')
    link = f'{[getdata(links) for links in links].text:<25}' # Das ist ja die Variable die in die CSV geschrieben wird. Hier erhalte ich die Fehlermeldung.
    df = pd.DataFrame(results)
    df.to_csv('TESTV3'+ '.csv',index=False)
    return

if __name__=='__main__':
    s = HTMLSession()
    main()
Um ehrlich zu sein weiß ich auch gar nicht genau was das "text:<25" macht, aber es funktioniert.... :| Wird mir dann nur Text mit weniger als 25 Zeichen angezeigt? Habe das auch mal mit 5 ausprobiert und habe das gleiche Ergebnis erhalten...
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Da ist so einiges nicht in Ordnung. Benutze keine globalen Variablen, und keine Einbuchstabigen Namen, die sagen nichts aus. Also get_links muß `s`, besser aber `session` als Argument bekommen. Warum benutzt Du aber für das eine request_html und für das andere requests mit BeautifulSoup? Das ist doch total inkonsistent. Entscheide Dich für eins.
`r` ist `response`. 'link...' ist kein gültiger Link, genausowenig wie '{link]' einer ist.
findAll ist veraltet und sollte durch find_all ersetzt werden.
Wenn Du nicht weißt, wie man Formatstrings anwendet, warum benutzt Du sie dann an allen unmöglichen Stellen?

Mit Singular und Plural hast Du auch deine Probleme. `for links in links`? In der Liste links ist ein Element ein Link. Und wenn Du da eine neue Liste erzeugst, sind das wieder viele und nicht nur ein Link.

`getdata` müßte wohl `get_prices` heißen, dann müßte auch klar sein, dass Du innerhalb dieser Funktion etwas ändern müßtest.
Auch hier wieder verschleiert die falsche Benutzung von Singular und Plural den eigentlichen Sinn.
In `main` willst Du dann auch keine Listcomprehension innerhalb eines Formatstrings, sondern eine ganz normaler for-Schleife. Was die tut, sollte dann hoffentlicher klarer werden, wenn Du die besseren Namen benutzt.
`results` ist nicht definiert.
Antworten