Cómo raspar Yahoo Finanzas en Python

En esta guía paso a paso, demostraremos cómo raspar Yahoo Finanzas usando Python
5 min read
Yahoo Finance scraping guide

TL:DR: Vamos a aprender cómo construir un raspador de Yahoo Finanzas con el propósito de extraer datos de valores para realizar análisis financieros para el comercio y la inversión.

Este tutorial cubrirá:

  • ¿Por qué raspar datos financieros de la Web?
  • Bibliotecas y herramientas de raspado financiero
  • Raspado de datos bursátiles de Yahoo Finanzas con Selenium

¿Por qué raspar datos financieros de la Web?

El raspado de datos financieros de la Web ofrece información valiosa que resulta útil en varios escenarios, entre ellos:  

  • Comercio automatizado: mediante la recopilación de datos de mercado históricos o en tiempo real, como los precios de las acciones y el volumen, los desarrolladores pueden crear estrategias de negociación automatizadas.  
  • Análisis técnico: los datos e indicadores históricos del mercado son muy importantes para los analistas técnicos. Les permiten identificar patrones y tendencias, lo que les ayuda a tomar decisiones de inversión.  
  • Modelización financiera: los investigadores y analistas pueden recopilar datos relevantes como estados financieros e indicadores económicos para construir modelos complejos que permitan evaluar el rendimiento de las empresas, prever beneficios y valorar oportunidades de inversión.  
  • Estudios de mercado: los datos financieros proporcionan gran cantidad de información sobre acciones, índices de mercado y materias primas. El análisis de estos datos ayuda a los investigadores a comprender las tendencias del mercado, el sentimiento y la salud del sector para tomar decisiones de inversión con conocimiento de causa.

Cuando se trata de seguir el mercado, Yahoo Finanzas es uno de los sitios web financieros más populares. Ofrece una amplia gama de información y herramientas a inversores y operadores, como datos históricos y en tiempo real sobre acciones, bonos, fondos de inversión, materias primas, divisas e índices de mercado. Además, ofrece artículos de noticias, estados financieros, estimaciones de analistas, gráficos y otros recursos valiosos.

Al raspar Yahoo Finanzas, puede acceder a una gran cantidad de información para apoyar su análisis financiero, la investigación y los procesos de toma de decisiones.  

Bibliotecas y herramientas de raspado financiero

Python se considera uno de los mejores lenguajes para raspado web gracias a su sintaxis, facilidad de uso y ecosistema rico de bibliotecas. Consulte nuestra guía sobre raspado web con Python.  

Para elegir las bibliotecas de raspado adecuadas entre las muchas disponibles, explore Yahoo Finanzas en su navegador. Observará que la mayoría de los datos del sitio se actualizan en tiempo real o cambian tras una interacción. Esto significa que el sitio depende en gran medida de AJAX para cargar y actualizar los datos de manera dinámica, sin necesidad de recargar la página. En otras palabras, se requiere una herramienta capaz de ejecutar JavaScript.

Selenium permite raspar sitios web dinámicos en Python. Renderiza el sitio en los navegadores web, realizando programáticamente operaciones en ellos aunque utilicen JavaScript para renderizar o recuperar datos.  

Gracias a Selenium, es posible raspar datos del sitio de destino con Python. ¡Veamos cómo!

Raspado de datos bursátiles de Yahoo Finanzas con Selenium

Siga este tutorial paso a paso y aprenda a construir un script Python de raspado web de Yahoo Finance.

Paso 1: Configuración  

Antes de sumergirse en el raspado de datos financieros, asegúrese de cumplir con los siguientes requisitos previos:

A continuación, utilice los siguientes comandos para configurar un proyecto Python con un entorno virtual:


mkdir yahoo-finance-scraper
cd yahoo-finance-scraper
python -m venv env

Esto inicializará la carpeta del proyecto yahoo-finance-scraper. Dentro de ella, se añade un archivo scraper.py como se indica a continuación:

print('Hello, World!')

Aquí se añadirá la lógica para raspar Yahoo Finanzas. Ahora mismo, es un script de ejemplo que sólo imprime “¡Hola, Mundo!”.

Ejecútelo para verificar que funciona:

python scraper.py

En el terminal, se debe ver:

Hello, World!

Genial, ya tiene un proyecto Python para su raspador de finanzas. Sólo queda añadir las dependencias del proyecto. Instale Selenium y el Webdriver Manager con el siguiente comando de terminal:

pip install selenium webdriver-manager

Esto puede tardar un poco, así que es importante tener paciencia.

webdriver-manager no es estrictamente necesario. Sin embargo, es muy recomendable, ya que hace que la gestión de los controladores web en Selenium sea mucho más fácil. Gracias a él, no es necesario descargar, configurar e importar manualmente el controlador web.

Actualizar scraper.py


from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager

# initialize a web driver instance to control a Chrome window
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))

# scraping logic...

# close the browser and free up the resources
driver.quit()

Este script simplemente instanciará una instancia de ChromeWebDriver. Lo utilizaremos próximamente para implementar la lógica de extracción de datos.

Paso 2: Conectarse a la página web de destino

 

Este es el aspecto de la URL de una página de bolsa de Yahoo Finanzas:

https://finance.yahoo.com/quote/AMZN

Como puede ver, se trata de una URL dinámica que cambia en función del símbolo del ticker. Si no se conoce el concepto, se trata de una abreviatura de cadena que se utiliza para identificar de forma exclusiva las acciones que cotizan en bolsa. Por ejemplo, “AMZN” es el símbolo de las acciones de Amazon.

Modifiquemos el script para que lea el ticker desde un argumento de la línea de comandos.


import sys

# if there are no CLI parameters
if len(sys.argv) <= 1:
    print('Ticker symbol CLI argument missing!')
    sys.exit(2)

# read the ticker from the CLI argument
ticker_symbol = sys.argv[1]

# build the URL of the target page
url = f'https://finance.yahoo.com/quote/{ticker_symbol}'

sys es una biblioteca estándar de Python que proporciona acceso a los argumentos de la línea de comandos. No olvidemos que el argumento con índice 0 es el nombre de nuestro script. Por lo tanto, es necesario tener como objetivo el argumento con el índice 1.

Después de leer el ticker de la CLI, se utiliza en una cadena f para producir la URL de destino para raspar.

Por ejemplo, supongamos que lanzamos el raspador web con el ticker de Tesla “TSLA:”

python scraper.py TSLA

url contendrá:

https://finance.yahoo.com/quote/TSLA

Si olvida el símbolo del ticker en el CLI, el programa fallará con el siguiente error:

Ticker symbol CLI argument missing!

Antes de abrir cualquier página en Selenium, se recomienda establecer el tamaño de la ventana para asegurarse de que todos los elementos son visibles:

driver.set_window_size(1920, 1080)

Ahora puede usar Selenium para conectarse a la página de destino con:

driver.get(url)

La función get() indica al navegador que visite la página deseada.

Este es el aspecto que tiene hasta ahora su script de raspado de datos financieros de Yahoo:


from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
import sys

# if there are no CLI parameters
if len(sys.argv) <= 1:
    print('Ticker symbol CLI argument missing!')
    sys.exit(2)

# read the ticker from the CLI argument
ticker_symbol = sys.argv[1]

# build the URL of the target page
url = f'https://finance.yahoo.com/quote/{ticker_symbol}'

# initialize a web driver instance to control a Chrome window
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))
# set up the window size of the controlled browser
driver.set_window_size(1920, 1080)
# visit the target page
driver.get(url)

# scraping logic...

# close the browser and free up the resources
driver.quit()

Si se ejecuta, se abrirá esta ventana durante una fracción de segundo antes de terminar:

Imagen de Yahoo Finanzas

Iniciar el navegador con la interfaz de usuario es útil para la depuración mediante la supervisión de lo que el raspador está haciendo en la página web. Al mismo tiempo, consume muchos recursos. Para evitarlo, hay que configurar Chrome para que se ejecute en modo headless (sin interfaz gráfica) con:


from selenium.webdriver.chrome.options import Options
# ...

options = Options()
options.add_argument('--headless=new')

driver = webdriver.Chrome(
    service=ChromeService(ChromeDriverManager().install()),
    options=options
)

El navegador controlado se iniciará ahora detrás de la escena, sin interfaz de usuario.

Paso 3: Inspeccionar la página de destino  

Si desea estructurar una estrategia de minería de datos eficaz, primero debe analizar la página web de destino. Abra su navegador y visite la página de acciones de Yahoo.

Si se encuentra en Europa, primero verá un modal pidiéndole que acepte las cookies:

Cookies de Yahoo

Para cerrarlo y seguir visitando la página deseada, debe hacer clic en “Aceptar todas” o “Rechazar todas”. Haga clic con el botón derecho del ratón en el primer botón y seleccione la opción “Inspeccionar” para abrir las DevTools de su navegador:

Yahoo inspeccionar

Aquí, se observa que se puede seleccionar ese botón con el siguiente selector CSS:

.consent-overlay .accept-all

Utilice estas líneas de hielo para tratar con el modal de consentimiento en Selenium:


try:
    # wait up to 3 seconds for the consent modal to show up
    consent_overlay = WebDriverWait(driver, 3).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, '.consent-overlay')))

    # click the "Accept all" button
    accept_all_button = consent_overlay.find_element(By.CSS_SELECTOR, '.accept-all')
    accept_all_button.click()
except TimeoutException:
    print('Cookie consent overlay missing')

WebDriverWait permite esperar a que ocurra una condición esperada en la página. Si no ocurre nada en el tiempo de espera especificado, lanza una TimeoutException. Dado que la cookie superpuesta sólo se muestra cuando su IP de salida es europea, puede manejar la excepción con una instrucción try-catch. De esta forma, el script seguirá ejecutándose cuando el modal de consentimiento no esté presente.

Para que el script funcione, deberá añadir las siguientes importaciones:


from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common import TimeoutException

Ahora, siga inspeccionando el sitio de destino en las DevTools y familiarícese con su estructura DOM.

Paso 4: Extraer los datos de stock  

Como habrá notado en el paso anterior, parte de la información más interesante se encuentra en esta sección:

Extraer datos bursátiles

Inspeccione el elemento HTML indicador de precios:

Tenga en cuenta que las clases CSS no son útiles para definir selectores adecuados en Yahoo Finanzas. Parecen seguir una sintaxis especial para un marco de estilo. En su lugar, céntrese en los demás atributos HTML. Por ejemplo, puede obtener el precio de las acciones con el selector CSS siguiente:

[data-symbol="TSLA"][data-field="regularMarketPrice"]

Siguiendo un enfoque similar, extraiga todos los datos bursátiles de los indicadores de precios con:


regular_market_price = driver\
    .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="regularMarketPrice"]')\
    .text
regular_market_change = driver\
    .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="regularMarketChange"]')\
    .text
regular_market_change_percent = driver\
    .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="regularMarketChangePercent"]')\
    .text\
    .replace('(', '').replace(')', '')
 
post_market_price = driver\
    .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="postMarketPrice"]')\
    .text
post_market_change = driver\
    .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="postMarketChange"]')\
    .text
post_market_change_percent = driver\
    .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="postMarketChangePercent"]')\
    .text\
    .replace('(', '').replace(')', '')

Después de seleccionar un elemento HTML mediante la estrategia específica del selector CSS, puede extraer su contenido con el campo de texto. Dado que los campos de porcentaje implican paréntesis redondos, éstos se eliminan con replace().

Se añaden a un diccionario de valores stock y se imprimen para verificar que el proceso de raspado de datos financieros funciona como se espera:


# initialize the dictionary
stock = {}

# stock price scraping logic omitted for brevity...

# add the scraped data to the dictionary
stock['regular_market_price'] = regular_market_price
stock['regular_market_change'] = regular_market_change
stock['regular_market_change_percent'] = regular_market_change_percent
stock['post_market_price'] = post_market_price
stock['post_market_change'] = post_market_change
stock['post_market_change_percent'] = post_market_change_percent

print(stock)

Ejecute el script en el valor que desea raspar y debería ver algo como:

{'regular_market_price': '193.17', 'regular_market_change': '+8.70', 'regular_market_change_percent': '+4.72%', 'post_market_price': '194.00', 'post_market_change': '+0.83', 'post_market_change_percent': '+0.43%'}

Puede encontrar más información útil en la tabla #quote-summary:

Tabla de resumen de cotizaciones

En este caso, se puede extraer cada campo de datos gracias al atributo data-test como en el selector CSS de abajo:

#quote-summary [data-test="PREV_CLOSE-value"]

Raspe todos ellos con:


previous_close = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="PREV_CLOSE-value"]').text
open_value = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="OPEN-value"]').text
bid = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="BID-value"]').text
ask = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="ASK-value"]').text
days_range = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="DAYS_RANGE-value"]').text
week_range = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="FIFTY_TWO_WK_RANGE-value"]').text
volume = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="TD_VOLUME-value"]').text
avg_volume = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="AVERAGE_VOLUME_3MONTH-value"]').text
market_cap = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="MARKET_CAP-value"]').text
beta = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="BETA_5Y-value"]').text
pe_ratio = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="PE_RATIO-value"]').text
eps = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="EPS_RATIO-value"]').text
earnings_date = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="EARNINGS_DATE-value"]').text
dividend_yield = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="DIVIDEND_AND_YIELD-value"]').text
ex_dividend_date = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="EX_DIVIDEND_DATE-value"]').text
year_target_est = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="ONE_YEAR_TARGET_PRICE-value"]').text

A continuación, se añaden al inventario (stock):


stock['previous_close'] = previous_close
stock['open_value'] = open_value
stock['bid'] = bid
stock['ask'] = ask
stock['days_range'] = days_range
stock['week_range'] = week_range
stock['volume'] = volume
stock['avg_volume'] = avg_volume
stock['market_cap'] = market_cap
stock['beta'] = beta
stock['pe_ratio'] = pe_ratio
stock['eps'] = eps
stock['earnings_date'] = earnings_date
stock['dividend_yield'] = dividend_yield
stock['ex_dividend_date'] = ex_dividend_date
stock['year_target_est'] = year_target_est

¡Fantástico! ¡Realizó raspado financiero de la web con Python!

Paso 5: Raspar diversos valores  

Una cartera de inversión diversificada consta de más de un valor. Para recuperar los datos de todos ellos, es necesario ampliar el script para raspar múltiples tickers.

En primer lugar, encapsule la lógica de raspado en una función:


def scrape_stock(driver, ticker_symbol):
    url = f'https://finance.yahoo.com/quote/{ticker_symbol}'
    driver.get(url)

    # deal with the consent modal...

    # initialize the stock dictionary with the
    # ticker symbol
    stock = { 'ticker': ticker_symbol }

    # scraping the desired data and populate 
    # the stock dictionary...

    return stock

A continuación, itere sobre los argumentos del ticker CLI y aplique la función de raspado:


if len(sys.argv) <= 1:
    print('Ticker symbol CLI arguments missing!')
    sys.exit(2)

# initialize a Chrome instance with the right
# configs
options = Options()
options.add_argument('--headless=new')
driver = webdriver.Chrome(
    service=ChromeService(ChromeDriverManager().install()),
    options=options
)
driver.set_window_size(1150, 1000)

# the array containing all scraped data
stocks = []

# scraping all market securities
for ticker_symbol in sys.argv[1:]:
    stocks.append(scrape_stock(driver, ticker_symbol))

Al final del ciclo for, la lista de diccionarios Python stocks contendrá todos los datos bursátiles.

Paso 6: Exportar los datos raspados a CSV  

Es posible exportar los datos recopilados a CSV con unas pocas líneas de código:


import csv

# ...

# extract the name of the dictionary fields
# to use it as the header of the output CSV file
csv_header = stocks[0].keys()

# export the scraped data to CSV
with open('stocks.csv', 'w', newline='') as output_file:
    dict_writer = csv.DictWriter(output_file, csv_header)
    dict_writer.writeheader()
    dict_writer.writerows(stocks)

Este fragmento crea un archivo stocks.csv con open(), lo inicializa con una fila de encabezado y lo rellena. En concreto, DictWriter.writerows() convierte cada diccionario en un registro CSV y lo añade al archivo de salida.

Dado que csv proviene de Python Standard Library, ni siquiera es necesario instalar una dependencia adicional para lograr el objetivo deseado.

Ha partido de datos brutos contenidos en una página web y tiene datos semiestructurados almacenados en un archivo CSV. Es hora de echar un vistazo a todo el raspador de Yahoo Finanzas.

Paso 7: Conjuntarlo todo  

Aquí está el archivo scraper.py completo:


from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common import TimeoutException
import sys
import csv

def scrape_stock(driver, ticker_symbol):
    # build the URL of the target page
    url = f'https://finance.yahoo.com/quote/{ticker_symbol}'

    # visit the target page
    driver.get(url)

    try:
        # wait up to 3 seconds for the consent modal to show up
        consent_overlay = WebDriverWait(driver, 3).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, '.consent-overlay')))

        # click the 'Accept all' button
        accept_all_button = consent_overlay.find_element(By.CSS_SELECTOR, '.accept-all')
        accept_all_button.click()
    except TimeoutException:
        print('Cookie consent overlay missing')

    # initialize the dictionary that will contain
    # the data collected from the target page
    stock = { 'ticker': ticker_symbol }

    # scraping the stock data from the price indicators
    regular_market_price = driver \
        .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="regularMarketPrice"]') \
        .text
    regular_market_change = driver \
        .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="regularMarketChange"]') \
        .text
    regular_market_change_percent = driver \
        .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="regularMarketChangePercent"]') \
        .text \
        .replace('(', '').replace(')', '')

    post_market_price = driver \
        .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="postMarketPrice"]') \
        .text
    post_market_change = driver \
        .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="postMarketChange"]') \
        .text
    post_market_change_percent = driver \
        .find_element(By.CSS_SELECTOR, f'[data-symbol="{ticker_symbol}"][data-field="postMarketChangePercent"]') \
        .text \
        .replace('(', '').replace(')', '')

    stock['regular_market_price'] = regular_market_price
    stock['regular_market_change'] = regular_market_change
    stock['regular_market_change_percent'] = regular_market_change_percent
    stock['post_market_price'] = post_market_price
    stock['post_market_change'] = post_market_change
    stock['post_market_change_percent'] = post_market_change_percent

    # scraping the stock data from the "Summary" table
    previous_close = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="PREV_CLOSE-value"]').text
    open_value = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="OPEN-value"]').text
    bid = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="BID-value"]').text
    ask = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="ASK-value"]').text
    days_range = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="DAYS_RANGE-value"]').text
    week_range = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="FIFTY_TWO_WK_RANGE-value"]').text
    volume = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="TD_VOLUME-value"]').text
    avg_volume = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="AVERAGE_VOLUME_3MONTH-value"]').text
    market_cap = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="MARKET_CAP-value"]').text
    beta = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="BETA_5Y-value"]').text
    pe_ratio = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="PE_RATIO-value"]').text
    eps = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="EPS_RATIO-value"]').text
    earnings_date = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="EARNINGS_DATE-value"]').text
    dividend_yield = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="DIVIDEND_AND_YIELD-value"]').text
    ex_dividend_date = driver.find_element(By.CSS_SELECTOR, '#quote-summary [data-test="EX_DIVIDEND_DATE-value"]').text
    year_target_est = driver.find_element(By.CSS_SELECTOR,
                                          '#quote-summary [data-test="ONE_YEAR_TARGET_PRICE-value"]').text

    stock['previous_close'] = previous_close
    stock['open_value'] = open_value
    stock['bid'] = bid
    stock['ask'] = ask
    stock['days_range'] = days_range
    stock['week_range'] = week_range
    stock['volume'] = volume
    stock['avg_volume'] = avg_volume
    stock['market_cap'] = market_cap
    stock['beta'] = beta
    stock['pe_ratio'] = pe_ratio
    stock['eps'] = eps
    stock['earnings_date'] = earnings_date
    stock['dividend_yield'] = dividend_yield
    stock['ex_dividend_date'] = ex_dividend_date
    stock['year_target_est'] = year_target_est

    return stock

# if there are no CLI parameters
if len(sys.argv) <= 1:
    print('Ticker symbol CLI argument missing!')
    sys.exit(2)

options = Options()
options.add_argument('--headless=new')

# initialize a web driver instance to control a Chrome window
driver = webdriver.Chrome(
    service=ChromeService(ChromeDriverManager().install()),
    options=options
)

# set up the window size of the controlled browser
driver.set_window_size(1150, 1000)

# the array containing all scraped data
stocks = []

# scraping all market securities
for ticker_symbol in sys.argv[1:]:
    stocks.append(scrape_stock(driver, ticker_symbol))

# close the browser and free up the resources
driver.quit()

# extract the name of the dictionary fields
# to use it as the header of the output CSV file
csv_header = stocks[0].keys()

# export the scraped data to CSV
with open('stocks.csv', 'w', newline='') as output_file:
    dict_writer = csv.DictWriter(output_file, csv_header)
    dict_writer.writeheader()
    dict_writer.writerows(stocks)

En menos de 150 líneas de código, ha construido un raspador web con todas las funciones para recuperar datos de Yahoo Finanzas.

Ejecútelo contra sus acciones objetivo como en el ejemplo siguiente:

python scraper.py TSLA AMZN AAPL META NFLX GOOG

Al final del proceso de raspado, este archivo stocks.csv aparecerá en la carpeta raíz de su proyecto:

Stocks csv

Conclusión

En este tutorial, hemos demostrado por qué Yahoo Finanzas es uno de los mejores portales financieros de la web y cómo extraer datos de él. En particular, abordamos cómo construir un raspador de Python que puede recuperar datos de valores de la misma. Como se muestra aquí, no es complejo y sólo requiere unas pocas líneas de código.

Al mismo tiempo, Yahoo Finanzas es un sitio dinámico que depende en gran medida de JavaScript. Cuando se trata de este tipo de sitios, un enfoque tradicional basado en una biblioteca HTTP y un analizador HTML no es suficiente. Además, estos sitios tan populares suelen aplicar tecnologías avanzadas de protección de datos. Para rasparlos necesita un navegador controlable que sea capaz de gestionar automáticamente CAPTCHAs, huellas digitales, reintentos automáticos y mucho más por usted. Esto es exactamente lo que hace nuestra nueva solución, Scraping Browser.  

¿No quiere ocuparse en absoluto del raspado web pero le interesan los datos financieros? Explore nuestro mercado de conjuntos de datos.