Como fazer Web Scraping no Idealista: Um guia completo (atualização de 2023)
Raluca Penciuc em Mar 03 2023

Idealista é um dos principais sítios Web de imobiliário no Sul da Europa, fornecendo uma grande quantidade de informações sobre propriedades para venda e aluguer. Está disponível em Espanha, Portugal e Itália, listando milhões de casas, quartos e apartamentos.
Para empresas e particulares que procuram obter informações sobre o mercado imobiliário espanhol, o sítio web pode ser uma ferramenta preciosa. O Web scraping da Idealista pode ajudá-lo a extrair esta informação valiosa e utilizá-la de várias formas, tais como estudos de mercado, geração de leads e criação de novas oportunidades de negócio.
Neste artigo, forneceremos um guia passo a passo sobre como raspar o site usando TypeScript. Cobriremos os pré-requisitos, a raspagem real dos dados das propriedades e como melhorar o processo, e por que usar um raspador profissional é melhor do que criar o seu próprio.
No final do artigo, terá os conhecimentos e as ferramentas necessárias para extrair dados do Idealista e utilizá-los de forma útil para a sua empresa.
Pré-requisitos
Antes de começarmos, vamos assegurar-nos de que dispomos das ferramentas necessárias.
Primeiro, baixe e instale o Node.js do site oficial, certificando-se de usar a versão Long-Term Support (LTS). Isso também instalará automaticamente o Node Package Manager (NPM), que usaremos para instalar outras dependências.
Para este tutorial, usaremos o Visual Studio Code como nosso ambiente de desenvolvimento integrado (IDE), mas você pode usar qualquer outro IDE de sua escolha. Crie uma nova pasta para seu projeto, abra o terminal e execute o seguinte comando para configurar um novo projeto Node.js:
npm init -y
Isto criará um ficheiro package.json no seu diretório de projeto, que armazenará informações sobre o seu projeto e as suas dependências.
Em seguida, precisamos instalar o TypeScript e as definições de tipo para o Node.js. O TypeScript oferece tipagem estática opcional que ajuda a evitar erros no código. Para fazer isso, execute no terminal:
npm install typescript @types/node --save-dev
Pode verificar a instalação executando:
npx tsc --versão
O TypeScript usa um arquivo de configuração chamado tsconfig.json para armazenar opções do compilador e outras configurações. Para criar esse arquivo em seu projeto, execute o seguinte comando:
npx tsc -init
Certifique-se de que o valor de "outDir" esteja definido como "dist". Desta forma, iremos separar os ficheiros TypeScript dos ficheiros compilados. Pode encontrar mais informações sobre este ficheiro e as suas propriedades na documentação oficial do TypeScript.
Agora, crie um diretório "src" no seu projeto e um novo ficheiro "index.ts". É aqui que vamos manter o código de raspagem. Para executar o código TypeScript, é necessário compilá-lo primeiro, portanto, para garantir que não nos esqueçamos dessa etapa extra, podemos usar um comando definido de forma personalizada.
Vá ao ficheiro "package.json" e edite a secção "scripts" desta forma:
"scripts": {
"test": "npx tsc && node dist/index.js"
}
Desta forma, quando for executar o script, basta digitar "npm run test" no seu terminal.
Por fim, para extrair os dados do site, usaremos o Puppeteer, uma biblioteca de navegador sem cabeça para Node.js que permite controlar um navegador da Web e interagir com sites de forma programática. Para instalá-la, execute este comando no terminal:
npm install puppeteer
É altamente recomendado quando se pretende garantir a integridade dos dados, uma vez que muitos sítios Web actuais contêm conteúdo gerado dinamicamente. Se estiver curioso, pode consultar a documentação do Puppeteer antes de continuar para ver o que ele é capaz de fazer.
Localização dos dados
Agora que tem o seu ambiente configurado, podemos começar a procurar extrair os dados. Para este artigo, optei por extrair a lista de casas e apartamentos disponíveis numa região de Toledo, em Espanha: https://www.idealista.com/pt/alquiler-viviendas/toledo/buenavista-valparaiso-la-legua/.
Vamos extrair os seguintes dados de cada anúncio na página:
- o URL;
- o título;
- o preço;
- os pormenores (número de quartos, superfície, etc.);
- a descrição
Pode ver todas estas informações destacadas na imagem de ecrã abaixo:

Ao abrir as Ferramentas do desenvolvedor em cada um desses elementos, você poderá observar os seletores CSS que usaremos para localizar os elementos HTML. Se não sabe muito bem como funcionam os selectores CSS, pode consultar este guia para principiantes.
Extração de dados
Para começar a escrever o nosso script, vamos verificar se a instalação do Puppeteer correu bem:
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/")
Aqui, abrimos uma janela do navegador, criamos uma nova página, navegamos até o URL de destino e fechamos o navegador. Por uma questão de simplicidade e depuração visual, abro a janela do navegador maximizada no modo sem cabeça.
Como todas as listagens têm a mesma estrutura e dados, podemos extrair todas as informações de toda a lista de propriedades no nosso algoritmo. Depois de executar o script, podemos percorrer todos os resultados e compilá-los numa única lista.
Para obter o URL de todas as propriedades, localizamos os elementos âncora com a classe "item-link". Em seguida, convertemos o resultado numa matriz JavaScript e mapeamos cada elemento para o valor do atributo "href".
// 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)
Depois, para os títulos, podemos utilizar o mesmo elemento âncora, só que desta vez vamos extrair o seu atributo "title".
// 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)
Para os preços, localizamos os elementos "span" com 2 nomes de classe: "item-price" e "h2-simulated". É importante identificar os elementos da forma mais única possível, para não alterar o resultado final. Também precisa de ser convertido numa matriz e depois mapeado para o seu conteúdo de texto.
// 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)
Aplicamos o mesmo princípio para os detalhes da propriedade, analisando os elementos "div" com o nome de classe "item-detail-char".
// 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)
E, finalmente, a descrição das propriedades. Aqui aplicamos uma expressão regular extra para remover todos os caracteres de nova linha desnecessários.
// 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)
Agora você deve ter 5 listas, uma para cada dado que extraímos. Como mencionei anteriormente, devemos centralizá-las numa única. Desta forma, a informação que recolhemos será muito mais fácil de processar.
// 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)
O resultado final deve ser o seguinte:
[
{
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ç...'
}
]
Contornar a deteção de bots
Se executou o seu script pelo menos 2 vezes durante este tutorial, já deve ter reparado nesta página irritante:

O Idealista utiliza o DataDome como proteção antibot, que incorpora um desafio GeeTest CAPTCHA. O utilizador deve mover a peça do puzzle até que a imagem esteja completa e, em seguida, deve ser redireccionado para a página de destino.
Pode facilmente fazer uma pausa no seu script Puppeteer até resolver o desafio utilizando este código:
await page.waitForFunction(() => {
const pageContent = document.getElementById('main-content')
return pageContent !== null
}, {timeout: 10000})
Isto diz ao nosso script para esperar 10 segundos até que um seletor CSS especificado apareça no DOM. Deve ser o suficiente para resolver o CAPTCHA e depois deixar a navegação ser concluída.

... A não ser que a página do Idealista o bloqueie na mesma.
Nesta altura, o processo tornou-se mais complexo e exigente, e nem sequer conseguiu aumentar a escala do seu projeto.
Como já mencionei, Idealista é protegido por DataDome. Recolhem vários dados do navegador para gerar e associar uma impressão digital única ao utilizador. Se suspeitarem, recebe o desafio CAPTCHA acima, que é bastante difícil de resolver automaticamente.
Entre os dados do navegador recolhidos, encontramos:
- propriedades do objeto Navigator (deviceMemory, hardwareConcurrency, idiomas, plataforma, userAgent, webdriver, etc.)
- controlos de prazos e de desempenho
- WebGL
- Deteção de IP WebRTC
- registo dos movimentos do rato
- incoerências entre o User-Agent e o seu sistema operativo
- e muito mais.
Uma forma de ultrapassar estes desafios e continuar a fazer scraping em grande escala é utilizar uma API de scraping. Estes tipos de serviços fornecem uma forma simples e fiável de aceder a dados de sítios Web como o Idealista.com, sem a necessidade de construir e manter o seu próprio raspador.
O WebScrapingAPI é um exemplo de um produto deste género. O seu mecanismo de rotação de proxy evita completamente os CAPTCHAs, e a sua base de conhecimentos alargada permite aleatorizar os dados do browser para que se pareça com um utilizador real.
A configuração é rápida e fácil. Basta registar uma conta para receber a sua chave de API. Esta pode ser acedida a partir do seu painel de controlo e é utilizada para autenticar os pedidos que envia.

Como já configurou o seu ambiente Node.js, podemos utilizar o SDK correspondente. Execute o seguinte comando para o adicionar às dependências do seu projeto:
npm install webscrapingapi
Agora só falta ajustar os selectores CSS anteriores à API. A poderosa caraterística das regras de extração torna possível analisar dados sem modificações significativas.
import webScrapingApiClient from 'webscrapingapi';
const client = new webScrapingApiClient("YOUR_API_KEY");
async function exampleUsage() {
const api_params = {
'render_js': 1,
'proxy_type': 'residential',
'timeout': 60000,
'extract_rules': JSON.stringify({
locations: {
selector: 'a.item-link',
output: '@href',
all: '1'
},
titles: {
selector: 'a.item-link',
output: '@title',
all: '1'
},
prices: {
selector: 'span.item-price.h2-simulated',
output: 'text',
all: '1'
},
details: {
selector: 'div.item-detail-char',
output: 'text',
all: '1'
},
descriptions: {
selector: 'div.item-description.description',
output: 'text',
all: '1'
}
})
}
const URL = "https://www.idealista.com/pt/alquiler-viviendas/toledo/buenavista-valparaiso-la-legua/"
const response = await client.get(URL, api_params)
if (response.success) {
// Group the lists
const listings = []
for (let i = 0; i < response.response.data.locations.length; i++) {
listings.push({
url: response.response.data.locations[i],
title: response.response.data.titles[i],
price: response.response.data.prices[i],
details: response.response.data.details[i],
description: response.response.data.descriptions[i].replace(/(\r\n|\n|\r)/gm, "")
})
}
console.log(listings.length, listings)
} else {
console.log(response.error.response.data)
}
}
exampleUsage();
Conclusão
Neste artigo, mostramos como fazer o scraping do Idealista, um popular site espanhol de imóveis, usando TypeScript e Puppeteer. Passamos pelo processo de configuração dos pré-requisitos e raspagem dos dados, e discutimos algumas maneiras de melhorar o código.
O Web scraping Idealista pode fornecer informações valiosas para empresas e particulares. Utilizando as técnicas descritas neste artigo, é possível extrair dados como URLs de propriedades, preços e descrições do sítio Web.
Além disso, se quiser evitar as medidas antibot e a complexidade do processo de raspagem, utilizar um raspador profissional pode ser mais eficiente e fiável do que criar o seu próprio raspador.
Seguindo os passos e técnicas descritos neste guia, pode desbloquear o poder do web scraping Idealista e usá-lo para apoiar as suas necessidades de negócio. Quer seja para pesquisa de mercado, geração de leads ou criação de novas oportunidades de negócios, o web scraping Idealista pode ajudá-lo a ficar à frente da concorrência.
Notícias e actualizações
Mantenha-se atualizado com os mais recentes guias e notícias sobre raspagem da Web, subscrevendo a nossa newsletter.
We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

Artigos relacionados

Saiba qual é o melhor browser para contornar os sistemas de deteção Cloudflare enquanto faz web scraping com o Selenium.


Saiba como usar proxies com node-fetch, um cliente HTTP JavaScript popular, para criar raspadores da Web. Entenda como os proxies funcionam na raspagem da Web, integre proxies com node-fetch e crie um raspador da Web com suporte a proxy.


Saiba como usar o Playwright para raspagem e automação da Web com nosso guia abrangente. Desde a configuração básica até técnicas avançadas, este guia cobre tudo.
