Schleife mit mehreren Versuchen

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
KosmoKramer
User
Beiträge: 2
Registriert: Mittwoch 22. Mai 2019, 12:19

Hallo
Ich versuche ein Script zu schreiben in dem Daten von einer Immobiliensuchmaschine abgefragt werden und in einer .txt Datei gespeichert wird.
Da nicht alle Inserate vollständige Informationen haben, versuche ich das Script so aufzubauen, dass die einzelnen Variablen abgefragt werden und falls eine nicht im Quellcode der Seite vorhanden ist, zur nächsten gesprungen wird und das Script nicht abbricht.

Wie genau Programmiere ich diesen Ablauf?
Das war mein Ansatz bis jetzt:

Code: Alles auswählen

try: 
		Preis = Stelle im Quellcode
		Stadtteil = Stelle im Quellcode
	#Falls der Stadtteil nicht angegeben wurden ist gib mir einfach nur den Preis
	except as Exception e:
		Preis = Stelle im Quellcode	
	
		 
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Exceptions sind dazu da, Code ab einem bestimmten Punkt abzubrechen. Was du suchst ist ein Weg etwas nur dann zu machen, wenn eine Bedingung zutrifft. Pro-Tipp: wenn das Wörtchen wenn nicht wär....
Sirius3
User
Beiträge: 17745
Registriert: Sonntag 21. Oktober 2012, 17:20

@KosmoKramer: realer Code mit realen Beispielwerten hilft ungemein.

Du sprichst von Abbruch, aber wie passiert der Abbruch? Verursachst Du den explizit? Oder implizit?
Mit den von Dir gegebenen Informationen kann man nur sagen: sorge einfach dafür, dass es keinen Abbruch gibt.
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

1. Benutze "if" (Bezüglich "Pro-Tipp: wenn das Wörtchen wenn nicht wär...." - __deets__)

2. Was erhältst du, wenn "Stadtteil" kein Inhalt hat - None/"" /[] /{} oder was? Könntest nämlich dies ja vergleichen und, bevor dein Skript etwas in die Textdatei schreibt, gegebenfalls das Schreiben von "Stadtteil" überspringen.
Z.b:

Code: Alles auswählen

if Stadtteil != None: #vorhanden
    #schreibe stadtteil
#schreibe preis


Wäre so meine Idee, aber deine Beschreibung lässt viele Fragen offen, daher kann ich nur vermuten, was du meinst. Ich weiß z.b. Nicht, ob du aus der Datei mehrmals die Werte für die Variablen ausliest.
Das ganze musst du zwar noch etwas vervollständigen, z.b mit der For-Schleife (vorher musst du den source_code erstmal lesen lassen), damit du alle Werte bekommst.
Zuletzt geändert von xXSkyWalkerXx1 am Donnerstag 23. Mai 2019, 08:09, insgesamt 2-mal geändert.
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

@Skywalker Das Beispiel in 2. ist unglücklich. Wenn der Preis sowieso geschrieben wird, muss den einfach außerhalb der Bedingung schreiben. Dann spart man sich den Else-Block.
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

Stimmt, hast Recht! :D

EDIT: Hab's im Post noch geändert.
KosmoKramer
User
Beiträge: 2
Registriert: Mittwoch 22. Mai 2019, 12:19

Hey vielen Dank für die Antworten. Ich hatte leider jetzt erst wieder Zeit mich daran zu setzten.

Das hier ist mein vollständiger Code:

Code: Alles auswählen

import requests
import json
from bs4 import BeautifulSoup as bs
import datetime as dt 
import os
import re
import time
import urllib.request
from urllib.request import urlopen
import csv

linklist = ["https://www.immobilienscout24.de/Suche/S-2/Wohnung-Kauf/Nordrhein-Westfalen/Duesseldorf/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/true?enteredFrom=result_list", "https://www.immobilienscout24.de/Suche/S-2/P-2/Wohnung-Kauf/Nordrhein-Westfalen/Duesseldorf/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/true","https://www.immobilienscout24.de/Suche/S-2/P-3/Wohnung-Kauf/Nordrhein-Westfalen/Duesseldorf/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/true"]

for links in linklist:
	res = requests.get(links)
	soup = bs(res.content, 'lxml')
	r = re.compile(r'resultListModel:(.*)')
	data = soup.find('script', text=r).text
	script = r.findall(data)[0].rstrip(',')
	#resultListModel: 
	results = json.loads(script)
	ids = [item['@id'] for item in results['searchResponseModel']['resultlist.resultlist']['resultlistEntries'][0]['resultlistEntry']]
	print(ids)

	data = json.dumps(ids)
	houseinfo = {}
	Flattyp = ()


csvData = [['id','purchasePrice','Spacesize','District','Flattyp','Flattypp','Rooms']]

def get_house_info (House):
	for id in ids:
			sourceCode = urllib.request.urlopen('https://www.immobilienscout24.de/expose/' + str(id)).read()
			purchasePrice = str(sourceCode).split('"purchasePrice":')[1].split(',"geoCode"')[0]
			Spacesize = str(sourceCode).split('"area":')[1].split('},"details"')[0]
			District = str(sourceCode).split('"quarter":')[1].split('},')[0]
			if Flattyp != str(sourceCode).split('"is24qa-typ grid-item three-fifths">')[1].split('</dd> </dl> <dl class')[0]:
				Flattyp == "nicht vorhanden"
			else:
				Flattyp = str(sourceCode).split('"is24qa-typ grid-item three-fifths">')[1].split('</dd> </dl> <dl class')[0]
			Rooms = str(sourceCode).split('is24qa-zimmer grid-item three-fifths"> ')[1].split(' </dd> </dl> <dl class=')[0]
			parking_space = str(sourceCode).split('<dd class="is24qa-garage-stellplatz grid-item three-fifths">')[1].split('</dd> </dl>')[0]
			if parking_space != str(sourceCode).split('<dd class="is24qa-garage-stellplatz grid-item three-fifths">')[1].split('</dd> </dl>')[0]:
				parking_space = "nicht vorhanden"
			else: 
				parking_space = str(sourceCode).split('<dd class="is24qa-garage-stellplatz grid-item three-fifths">')[1].split('</dd> </dl>')[0]
			
			with open('fooneu23.txt', 'a') as csvfile:
				cols = ['id', 'price', 'size', 'district', 'flattyp', 'rooms', 'parking_space','Flattypp']
				dict_result = {'id': id, 'price': purchasePrice, 'size': Spacesize, 'district': District, 'flattyp': Flattyp, 'rooms': Rooms, 'parking_space':parking_space, 'Flattypp':Flattypp}
				writer = csv.DictWriter(csvfile, fieldnames=cols)
				writer.writeheader()
				writer.writerow(dict_result)

			csvfile.close()



		
	
get_house_info(ids)

Ich habe versucht das ganze jetzt so mit einem If-Statement zu lösen:
Bekomme dabei jedoch eine Fehlermeldung.

Code: Alles auswählen

			if Flattyp != str(sourceCode).split('"is24qa-typ grid-item three-fifths">')[1].split('</dd> </dl> <dl class')[0]:
				Flattyp == "nicht vorhanden"
			else:
				Flattyp = str(sourceCode).split('"is24qa-typ grid-item three-fifths">')[1].split('</dd> </dl> <dl class')[0]
Fehlermeldung:
"UnboundLocalError: local variable 'Flattyp' referenced before assignment"

Es wäre klasse wenn mir jemand weiterhelfen könnte.
Benutzeravatar
__blackjack__
User
Beiträge: 13099
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@KosmoKramer: Welchen Wert hat denn `Flattyp` Deiner Meinung nach bevor dieses ``if`` das erste mal ausgeführt wird? Und wo wird der gesetzt? Ich sehe da nur ein `Flattyp` auf Modulebene was nichts mit dem lokalen Namen `Flattyp` in der Funktion zu tun hat.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Funktionen und Methoden sollten alles was sie ausser Konstanten benötigen als Argument(e) übergeben bekommen.

Du scheinst da HTML mit Zeichenkettenoperationen zu verarbeiten – das ist kaputt, das macht man nicht. Du hast doch sogar schon einen HTML-Parser eingebunden, dann nutze den auch.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17745
Registriert: Sonntag 21. Oktober 2012, 17:20

@KosmoKramer: Eingerückt wird mit vier Leerzeichen pro Ebene und nicht 1 oder 2 Tabs. Variablennamen werden nach Konvention klein_mit_unterstrich geschrieben.
Die Klasse BeautifulSoup sollte man nicht mit bs abkürzen.
datetime, os und time werden importiert aber nicht genutzt.
Warum benutzt Du urllib, wo doch schon requests verwendet wird?
In Zeile 19 verwendest Du findall statt search, obwohl Du nur das erste Element benutzt.
Die for-Schleife ist unsinnig, weil nur mit dem letzten Element etwas gemacht wird.
Bei Zeilen 25 - 28 werden drei Variablen definiert, die weder in noch außerhalb der for-Schleife benutzt werden.
`get_house_info` hat ein Argument `House` das nicht verwendet wird und `ids` wird benutzt, obwohl es kein Argument ist.
Hier wird urllib benutzt, obwohl Du an anderer Stelle requests benutzt. Strings setzt man nicht per + zusammen, sondern benutzt Stringformatierung. `sourceCode` ist bereits ein String, das immer wieder in einen String umzuwandeln, ist unsinnig.
HTML bearbeitet man nicht mit String-Funktionen, sondern, wie Du in der ersten for-Schleife schon machst, mit BeautifulSoup.
Daher möchte ich mich gar nicht erst durch die vielen splits arbeiten, die zum Teil auch doppelt gemacht werden. Besonders bei parking_space wird es lustig, da Du der Variable einen Wert zuweist, dann mit dem identischen Wert vergleichst und falls der tatsächlich immer noch gleich ist, der Variable nochmal diese Wert zuweist.
Es gibt ein Flattypp mit doppel-P, das wie ein Schreibfehler aussieht und nicht definiert ist.
Flattyp wird dagegen verwendet, bevor es definiert wird. Aber auch hier verstehe ich die if-Abfrage, wie auch bei parking_space schon, nicht.

Als erstes mußt Du also der ersten for-Schleife einen Sinn geben, oder entfernen, und die Ermittlung der IDs in eine Funktion packen. In der Funktion get_house_info urllib auf requests und das Stringgemetzel durch BeautifulSoup ersetzen.
Antworten