Volver al blog
La ciencia del web scraping
Mihai MaximLast updated on Mar 31, 20267 min read

Preguntas frecuentes sobre el web scraping: respuestas y consejos

Preguntas frecuentes sobre el web scraping: respuestas y consejos

Adentrarse en el mundo del web scraping puede resultar un poco abrumador. Hay que elegir el lenguaje de programación adecuado, la biblioteca correcta y lidiar con muchos contratiempos imprevistos. Rápidamente se convierte en algo difícil de asimilar. ¡Pero no dejes que eso te desanime! En este artículo, he respondido a algunas de las preguntas más frecuentes sobre el web scraping. Descubrirás qué están haciendo otras personas y a qué retos se han enfrentado. Esto te ayudará a orientar tu propio proceso de toma de decisiones. Tanto si eres nuevo en el campo como si eres un profesional experimentado, aquí hay algo para todos.

¿Por qué mi scraper no ve los mismos datos que mi navegador?

Has escrito un script para extraer HTML de un sitio web, pero no estás obteniendo todos los datos. Has probado tus selectores en el navegador y deberían funcionar, ¿verdad? No siempre. Los sitios web que dependen de JavaScript para renderizarse no funcionarán con una simple solicitud GET. Existen bibliotecas como Puppeteer y Selenium que utilizan navegadores sin interfaz gráfica para renderizar JavaScript. Te permiten realizar la solicitud en el contexto de un navegador y esperar a que JavaScript termine de ejecutarse. De esta forma, puedes obtener el HTML completo. Puede que no siempre necesites un navegador sin interfaz gráfica para obtener los datos que faltan. Busca etiquetas <script> en el HTML. Los datos que faltan podrían estar ocultos dentro de etiquetas <script> como variables de JavaScript.

¿Cómo puedo extraer datos de un sitio web que utiliza clases CSS generadas?

Algunos sitios web utilizan bibliotecas que crean automáticamente nombres de clase únicos para los diferentes componentes de la página. Esto puede dificultar el uso de selectores CSS tradicionales para seleccionar elementos específicos.

Una solución es utilizar expresiones XPath en su lugar. Los selectores XPath se basan en el diseño de la página, en lugar de en nombres de clase específicos. Esto significa que, incluso si cambian los nombres de clase, el selector XPath seguirá siendo capaz de localizar el elemento deseado.

Por ejemplo, si tienes un componente HTML que tiene este aspecto:

<div class="container">

    <div class="subcontainer_af21">

        <ul class="ul_ax1">

            <li class="li_adef">

                <a href="https://link1">Winter Storm</a>

            </li>

        </ul>

        <ul class="ul_cgt4">

            <li class="li_ocv2">

                <a href="https://lin2">SpaceX</a>

            </li>

        </ul>

    </div>

</div>

Puedes seleccionar el segundo elemento <a> con:

//div[@class='container']/div/ul[2]/li/a

¿Es Cheerio más rápido que Puppeteer?

Sí, en general se considera que Cheerio es más rápido que Puppeteer. Esto se debe a que Cheerio es una biblioteca del lado del servidor que trabaja directamente con el contenido HTML. Puppeteer es una biblioteca de automatización de navegadores que controla un navegador sin interfaz gráfica para cargar páginas web e interactuar con ellas. Cheerio tiene la limitación de que solo puede trabajar con páginas estáticas; no tiene la capacidad de interactuar con el navegador como lo hace Puppeteer

¿Son los selectores XPath mejores que los selectores CSS?

Depende del contexto. Si lo que buscas es extraer datos basándote en la posición de los elementos, XPath es la mejor opción. Sin embargo, si lo que buscas es extraer datos basándote en propiedades como la clase o el identificador, los selectores CSS son una mejor opción.

¿Es Playwright mejor que Puppeteer?

Ambos ofrecen funcionalidades similares, pero Playwright es compatible con varios navegadores, incluidos Chrome, Firefox y Safari. Puppeteer solo es compatible con Chrome y Chromium.

Playwright ofrece un mejor soporte para trabajar con múltiples pestañas y ventanas. También cuenta con soporte integrado para gestionar contextos de navegador, cookies y almacenamiento. Playwright es más adecuado para proyectos complejos.

¿Cómo puedo evitar los bloqueos de IP?

En general, puedes intentar espaciar tus solicitudes. Utiliza diferentes direcciones IP. Utiliza proxies. Intenta alterar la huella digital del navegador. Para la mayoría de la gente, esta es una batalla interminable. La buena noticia es que no tiene por qué ser así. Puedes utilizar nuestra solución, WebScrapingAPI. WebScrapingAPI proporciona una API que se encargará de todo el trabajo pesado por ti. Puede ejecutar JavaScript, rotar proxies e incluso gestionar CAPTCHAs. Nunca tendrás que preocuparte por que te bloqueen la IP. Pero no te fíes solo de nuestra palabra. Puedes probarlo gratis.

¿Cómo extraer texto de HTML con BeautifulSoup?

Puedes utilizar la biblioteca BeautifulSoup. Aquí tienes un ejemplo de cómo extraer texto utilizando la función .get_text():

from bs4 import BeautifulSoup

html_doc = """

<html>

 <head>

   <title>title of the page</title>

 </head>

 <body>

   <p>a paragraph</p>

   <a href='https://link.com'>a link</a>

 </body>

</html>

"""

soup = BeautifulSoup(html_doc, 'html.parser')

paragraph_text = soup.find('p').text

print(paragraph_text)

#Prints 'a paragraph'

link_text = soup.find('a').text

print(link_text)

#Prints 'a link'

all_text = soup.get_text()

print(all_text)

"""

title of the page

a paragraph

a link

"""

¿Cómo extraer texto de HTML con Selenium?

Así es como puedes hacerlo en Selenium:

from selenium import webdriver

from selenium.webdriver.common.by import By

DRIVER_PATH = 'path/to/chromedriver'

driver = webdriver.Chrome(executable_path=DRIVER_PATH)

driver.get("https://en.wikipedia.org/wiki/Main_Page")

# get all the h2 elements

content = driver.find_element(By.TAG_NAME, "h2")

print(content.text)

# Prints 'From today's featured article'

¿Cómo seleccionar elementos HTML por texto con BeautifulSoup?

Con BeautifulSoup, puedes utilizar el método soup.find con el parámetro text=re.compile("<text>"):

from bs4 import BeautifulSoup

import re

html_doc = """

<html>

<body>

  <p class="my_paragraph">a paragraph.</p>

  <p class="my_paragraph">another paragraph.</p>

</body>

</html>

"""

soup = BeautifulSoup(html_doc, 'html.parser')

# find the first pTag that contains the text 'a par'

pTag = soup.find("p", text=re.compile("a par"))

print(pTag)

¿Cómo seleccionar elementos HTML por texto con Selenium?

En Selenium, puedes hacerlo con XPath:

from selenium import webdriver

from selenium.webdriver.common.by import By

DRIVER_PATH = 'path/to/chromedriver'

driver = webdriver.Chrome(executable_path=DRIVER_PATH)

driver.get("https://en.wikipedia.org/wiki/Main_Page")

# get all the elements with class vector-body

span = driver.find_element(By.XPATH, "//span[contains(text(), 'Did')]")

print(span.text)

# Prints 'Did you know ...'

driver.quit()

¿Cómo encontrar elementos HTML con selectores CSS en BeautifulSoup?

Así es como puedes hacerlo con BeautifulSoup y los métodos find y find_all:

from bs4 import BeautifulSoup

html_doc = """

<html>

  <body>

    <p class="my_paragraph">First paragraph.</p>

    <p class="my_paragraph">Second paragraph..</p>

    <p>Last paragraph.</p>

  </body>

</html>

"""

soup = BeautifulSoup(html_doc, 'html.parser')

# find all elements with class 'my_paragraph

elements = soup.find_all(class_="my_paragraph")

for element in elements:

    print(element.text)

# prints 'First paragraph.' and 'Second paragraph..'

¿Cómo encontrar elementos HTML por clase con Selenium?

Así es como se puede hacer con Selenium:

from selenium import webdriver

from selenium.webdriver.common.by import By

DRIVER_PATH = 'path/to/chromedriver'

driver = webdriver.Chrome(executable_path=DRIVER_PATH)

driver.get("https://en.wikipedia.org/wiki/Main_Page")

# get all the elements with class vector-body

elements = driver.find_elements(By.CLASS_NAME, "vector-body")

for element in elements:

   print(element.text)

driver.quit()

¿Cómo usar XPath con BeautifulSoup?

Necesitarás la biblioteca de Python lxml:

import requests

from bs4 import BeautifulSoup

from lxml import etree

response = requests.get("https://en.wikipedia.org/wiki/Main_Page")

soup = BeautifulSoup(response.content, 'html.parser')

dom = etree.HTML(str(body))

xpath_str = '//h1//text()'

print(dom.xpath(xpath_str))

#Prints ['Main Page', 'Welcome to ', 'Wikipedia']

¿Cómo esperar a que se cargue la página en Selenium?

Si simplemente quieres esperar un tiempo determinado antes de que se agote el tiempo de espera al intentar encontrar cualquier elemento, puedes utilizar la función driver.implicitly_wait(time_in_seconds):

from selenium import webdriver

from selenium.webdriver.common.by import By

DRIVER_PATH = 'C:/Users/Michael/Desktop/chromedriver'

driver = webdriver.Chrome(executable_path=DRIVER_PATH)

driver.implicitly_wait(10)

driver.get("https://en.wikipedia.org/wiki/Main_Page")

element = driver.find_element(By.ID, "not_found_id")

# the element does not exist, but it waits 10 seconds for it

text = element.text

print(text)

# Close the browser

driver.quit()

También puedes optar por esperar hasta que se cumpla una determinada condición:

from selenium import webdriver

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

DRIVER_PATH = 'C:/Users/Michael/Desktop/chromedriver'

driver = webdriver.Chrome(executable_path=DRIVER_PATH)

driver.get("https://en.wikipedia.org/wiki/Main_Page")

# Wait for the element with id 'content' to be present on the page

wait = WebDriverWait(driver, 10)

element = wait.until(EC.presence_of_element_located((By.ID, "content")))

element = driver.find_element(By.ID, "content")

text = element.text

print(text)

# Close the browser

driver.quit()

¿Cómo encontrar elementos HTML con selectores CSS en Puppeteer?

En Puppeteer, puedes utilizar las funciones page.$() y page.$$() para seleccionar elementos con selectores CSS. La función page.$() se utiliza para encontrar el primer elemento que coincida con el selector. La función page.$$() se utiliza para encontrar todos los elementos que coincidan con el selector.

const puppeteer = require('puppeteer');

(async () => {

  const browser = await puppeteer.launch({

    headless: false,

  });

 

  const page = await browser.newPage();

  await page.goto('https://www.scrapethissite.com/pages/simple/');

  // Extract the first odd row element 

  const firstOddRow = await page.$('.container .row');

  console.log(await firstOddRow.evaluate(node => node.textContent));

  // Extract all the odd rows

  const allOddRows = await page.$$('.container .row');

  for (const oddRow of allOddRows) {

    console.log(await oddRow.evaluate(node => node.textContent));

  }

  await browser.close();

})();

¿Cómo encontrar elementos HTML con selectores CSS en Playwright?

A continuación te mostramos cómo hacerlo con Playwright. Es muy similar a Puppeteer:

const { chromium } = require('playwright');

(async () => {

  const browser = await chromium.launch({

    headless: false,

  });

  const context = await browser.newContext();

  const page = await context.newPage();

  await page.goto('https://www.scrapethissite.com/pages/simple/');

  // Extract the first odd row element

  const firstOddRow = await page.$('.container .row');

  console.log(await firstOddRow.textContent());

  // Extract all the odd rows

  const allOddRows = await page.$$('.container .row');

  for (const oddRow of allOddRows ) {

    console.log(await oddRow.textContent());

  }

  await browser.close();

})();

¿Cómo encontrar elementos HTML con selectores CSS en cheerio?

Con cheerio, tendrás que recuperar el HTML (yo utilicé la biblioteca request para hacerlo) y luego pasarlo a la biblioteca cheerio:

const request = require('request');

const cheerio = require('cheerio');

const url = 'https://www.scrapethissite.com/pages/simple/';

request(url, (error, response, html) => {

  if (!error && response.statusCode === 200) {

    const $ = cheerio.load(html);

    const firstOddRow = $('.container .row').first();

    console.log(firstOddRow.text());

    const allOddRows = $('.container .row');

    allOddRows.each((i, oddRow) => {

      console.log($(oddRow).text());

    });

  }

});

¿Cómo se utiliza XPath con Puppeteer?

Con Puppeteer, puedes usar la función page.$x() para seleccionar elementos con selectores XPath:

const puppeteer = require('puppeteer');

(async () => {

  const browser = await puppeteer.launch();

  const page = await browser.newPage();

  await page.goto('https://www.scrapethissite.com/pages/forms/');

  // Extract the table header elements

  const allTableHeaders = await page.$x('//table/tbody/tr[1]//th');

  for(let i = 0; i < allTableHeaders.length; i++) {

    const header = await page.evaluate(el => el.textContent, allTableHeaders[i]);

    console.log(header.trim());

  }

  await browser.close();

})();

// Output:

// Team Name

// Year

// Wins

// Losses

// OT Losses

// Win %

// Goals For (GF)

// Goals Against (GA)

// + / -

¿Cómo se usa XPath con Playwright?

const { chromium } = require('playwright');

(async () => {

  const browser = await chromium.launch({

    headless: false,

  });

  const context = await browser.newContext();

  const page = await context.newPage();

  await page.goto('https://www.scrapethissite.com/pages/forms/');

  // Extract the table header elements

  const allTableHeaders = await page.locator('xpath=//table/tbody/tr[1]//th').all();

 

  for (let i = 0; i < allTableHeaders.length; i++) {

    const headerText = await allTableHeaders[i].innerText();

    console.log(headerText);

  }

  await browser.close();

})();

Cualquier cadena de selector que comience por // o .. se considera un selector XPath. Por ejemplo, Playwright convierte «//html/body» en «xpath=//html/body».

¿Cómo encontrar elementos HTML por texto en Puppeteer?

En Puppeteer, la forma más sencilla de buscar elementos por texto es utilizar la función text() de XPath:

const puppeteer = require('puppeteer');

(async () => {

  const browser = await puppeteer.launch({

    headless: false,

  });

  const page = await browser.newPage();

  await page.goto('https://en.wikipedia.org/wiki/Web_scraping');

   // Select all the p tags texts that contain the word "prevent" 

   const pTags = await page.$x('//p[contains(text(), "prevent")]/text()');

   for(let i = 0; i < pTags.length; i++) {

     const pTag = await page.evaluate(el => el.textContent, pTags[i]);

     console.log(pTag,"\n");

   }

  await browser.close();

})();

//Output:

There are methods that some websites use to prevent web scraping, such as detecting and disallowing bots from crawling (viewing) their pages. In response, there are web scraping systems that rely on using techniques in ...     

¿Cómo buscar elementos HTML por texto en Playwright?

Si quieres buscar elementos por texto en Playwright, puedes utilizar la función allInnerTexts() en combinación con XPath.

const { chromium } = require('playwright');

(async () => {

  const browser = await chromium.launch({

    headless: false,

  });

  const context = await browser.newContext();

  const page = await context.newPage();

  await page.goto('https://en.wikipedia.org/wiki/Web_scraping');

  // Select all the p tags texts that contain the word "prevent" 

  const pTags  = await page.locator('//p[contains(text(), "prevent")]').allInnerTexts();

 

  for (let i = 0; i < pTags.length; i++) {

    console.log(pTags[i], "\n");

  }

  await browser.close();

})();

¿Cómo buscar elementos HTML por texto en cheerio?

const request = require('request');

const cheerio = require('cheerio');

const url = 'https://en.wikipedia.org/wiki/Web_scraping';

request(url, (error, response, html) => {

  if (!error && response.statusCode === 200) {

    const $ = cheerio.load(html);

  // Select all the p tags texts that contain the word "prevent" 

    const elements = $('p').filter((i, el) => $(el).text().includes('prevent'));

    elements.each((i, el) => {

        console.log($(el).text());

    });

  }

});

¿Cómo esperar a que aparezcan los selectores en Puppeteer?

En Puppeteer, puedes utilizar la función page.waitForSelector() para esperar a que aparezca un elemento específico en la página antes de continuar con el script. Puedes utilizarla tanto con selectores CSS como con selectores XPath:

await page.waitForSelector('.basic-element', { timeout: 10000 });

await page.waitForXPath("//div[@class='basic-element']"), { timeout: 10000 });

El parámetro timeout especifica el tiempo máximo de espera en milisegundos.

También puedes esperar a que un elemento alcance un estado determinado:

await page.waitForSelector('.basic-element', { visible: true });

// wait until the element becomes visible

¿Cómo esperar a que aparezcan selectores en Playwright?

Playwright es similar a Puppeteer. Puedes utilizar el método page.waitForSelector() para esperar a que aparezca un elemento específico en la página.

await page.waitForSelector('.element-class', { timeout: 10000 });

También puedes esperar a que un elemento alcance un estado determinado:

await page.waitForSelector('.basic-element', { state: 'visible' });

// wait for element to become visible

Conclusión

El web scraping es un tema muy amplio y este artículo solo aborda la superficie. Elegir la herramienta adecuada para tu caso de uso específico es fundamental. Por ejemplo, si quieres extraer datos de un sitio web utilizando JavaScript, la biblioteca cheerio es una buena opción. Sin embargo, si el sitio web requiere que JavaScript se cargue por completo, Puppeteer o Playwright son mejores opciones. El web scraping es un reto, pero comprender las herramientas puede ahorrarte muchos dolores de cabeza. Espero que este artículo haya ampliado tu perspectiva y te deseo lo mejor en tus proyectos de web scraping.

Acerca del autor
Mihai Maxim, Desarrollador Full Stack @ WebScrapingAPI
Mihai MaximDesarrollador Full Stack

Mihai Maxim es desarrollador full stack en WebScrapingAPI, donde colabora en todas las áreas del producto y ayuda a crear herramientas y funciones fiables para la plataforma.

Empieza a crear

¿Estás listo para ampliar tu recopilación de datos?

Únete a más de 2000 empresas que utilizan WebScrapingAPI para extraer datos de la web a escala empresarial sin ningún gasto de infraestructura.