Bevor wir mit dem Schreiben unseres Skripts beginnen, überprüfen wir, ob die Installation von Puppeteer erfolgreich war:
import puppeteer from 'puppeteer';
async function scrapeIdealistaData(idealista_url: string): Promise<void> {
// Launch Puppeteer
const browser = await puppeteer.launch({
headless: false,
args: ['--start-maximized'],
defaultViewport: null
})
// Create a new page
const page = await browser.newPage()
// Navigate to the target URL
await page.goto(idealista_url)
// Close the browser
await browser.close()
}
scrapeIdealistaData("https://www.idealista.com/pt/alquiler-viviendas/toledo/buenavista-valparaiso-la-legua/")
Hier öffnen wir ein Browserfenster, erstellen eine neue Seite, navigieren zu unserer Ziel-URL und schließen den Browser. Der Einfachheit und zur visuellen Fehlerbehebung halber öffne ich das Browserfenster im maximierten Modus im Nicht-Headless-Modus.
Da alle Einträge die gleiche Struktur und die gleichen Daten haben, können wir in unserem Algorithmus alle Informationen für die gesamte Immobilienliste extrahieren. Nach Ausführung des Skripts können wir alle Ergebnisse durchlaufen und zu einer einzigen Liste zusammenfassen.
Um die URLs aller Immobilien zu erhalten, suchen wir die Ankerelemente mit der Klasse „item-link“. Anschließend wandeln wir das Ergebnis in ein JavaScript-Array um und ordnen jedes Element dem Wert des „href“-Attributs zu.
// Extract listings location
const listings_location = await page.evaluate(() => {
const locations = document.querySelectorAll('a.item-link')
const locations_array = Array.from(locations)
return locations ? locations_array.map(a => a.getAttribute('href')) : []
})
console.log(listings_location.length, listings_location)
Für die Titel können wir dann dasselbe Ankerelement verwenden, nur dass wir diesmal dessen „title“-Attribut extrahieren.
// Extract listings titles
const listings_title = await page.evaluate(() => {
const titles = document.querySelectorAll('a.item-link')
const titles_array = Array.from(titles)
return titles ? titles_array.map(t => t.getAttribute('title')) : []
})
console.log(listings_title.length, listings_title)
Für die Preise suchen wir die „span“-Elemente mit zwei Klassennamen: „item-price“ und „h2-simulated“. Es ist wichtig, die Elemente so eindeutig wie möglich zu identifizieren, damit das Endergebnis nicht verfälscht wird. Auch diese müssen in ein Array umgewandelt und dann ihrem Textinhalt zugeordnet werden.
// Extract listings prices
const listings_price = await page.evaluate(() => {
const prices = document.querySelectorAll('span.item-price.h2-simulated')
const prices_array = Array.from(prices)
return prices ? prices_array.map(p => p.textContent) : []
})
console.log(listings_price.length, listings_price)
Das gleiche Prinzip wenden wir auf die Objektdetails an, indem wir die „div“-Elemente mit dem Klassennamen „item-detail-char“ analysieren.
// Extract listings details
const listings_detail = await page.evaluate(() => {
const details = document.querySelectorAll('div.item-detail-char')
const details_array = Array.from(details)
return details ? details_array.map(d => d.textContent) : []
})
console.log(listings_detail.length, listings_detail)
Und schließlich die Beschreibung der Immobilien. Hier wenden wir einen zusätzlichen regulären Ausdruck an, um alle unnötigen Zeilenumbruchzeichen zu entfernen.
// Extract listings descriptions
const listings_description = await page.evaluate(() => {
const descriptions = document.querySelectorAll('div.item-description.description')
const descriptions_array = Array.from(descriptions)
return descriptions ? descriptions_array.map(d => d.textContent.replace(/(\r\n|\n|\r)/gm, "")) : []
})
console.log(listings_description.length, listings_description)
Nun sollten Sie 5 Listen haben, eine für jeden Datensatz, den wir gescrapt haben. Wie bereits erwähnt, sollten wir diese in einer einzigen Liste zusammenfassen. Auf diese Weise lassen sich die gesammelten Informationen viel einfacher weiterverarbeiten.
// Group the lists
const listings = []
for (let i = 0; i < listings_location.length; i++) {
listings.push({
url: listings_location[i],
title: listings_title[i],
price: listings_price[i],
details: listings_detail[i],
description: listings_description[i]
})
}
console.log(listings.length, listings)
Das Endergebnis sollte wie folgt aussehen:
[
{
url: '/pt/inmueble/99004556/',
title: 'Apartamento em ronda de Buenavista, Buenavista-Valparaíso-La Legua, Toledo',
price: '750€/mês',
details: '\n3 quart.\n115 m² área bruta\n2º andar exterior com elevador\nOntem \n',
description: 'Apartamento para alugar na Ronda Buenavista, em Toledo.Três quartos e duas casas de banho, sala, cozinha, terraço, garagem e arrecadação....'
},
{
url: '/pt/inmueble/100106615/',
title: 'Moradia em banda em Buenavista-Valparaíso-La Legua, Toledo',
price: '1.000€/mês',
details: '\n4 quart.\n195 m² área bruta\nOntem \n',
description: 'Magnífica casa geminada para alugar com 3 andares, 4 quartos aconchegantes, 3 banheiros, sala ampla e luminosa, cozinha totalmente equipa...'
},
{
url: '/pt/inmueble/100099977/',
title: 'Moradia em banda em calle Francisco Ortiz, Buenavista-Valparaíso-La Legua, Toledo',
price: '800€/mês',
details: '\n3 quart.\n118 m² área bruta\n10 jan \n',
description: 'O REMAX GRUPO FV aluga uma casa mobiliada na Calle Francisco Ortiz, em Toledo.Moradia geminada com 148 metros construídos, distribuídos...'
},
{
url: '/pt/inmueble/100094142/',
title: 'Apartamento em Buenavista-Valparaíso-La Legua, Toledo',
price: '850€/mês',
details: '\n4 quart.\n110 m² área bruta\n1º andar exterior com elevador\n10 jan \n',
description: 'Apartamento muito espaçoso para alugar sem móveis, cozinha totalmente equipada.Composto por 4 quartos, 1 casa de banho, terraço.Calefaç...'
}
]