Cómo scrapear artículos de Medium con Python

Comentarios: 0

Extraer artículos de Medium puede ser de suma importancia para fines como evaluación de contenidos, recopilación de datos o seguimiento de autores y sus obras. En este tutorial, aprenderemos a scrapear medium - un sitio web de artículos para escritores, utilizando el lenguaje de programación python. Discutiremos cómo se pueden extraer datos como el título del artículo, el nombre del autor, el nombre de la publicación y el propio cuerpo del texto a partir de una URL web dada de un artículo de Medium.

Requisitos

Para este tutorial, vamos a scrapear este artículo de Medium: "9 Python Built-in Decorators That Optimize Your Code Significantly".

Antes de empezar, instala las siguientes librerías:

  • Requests: Para enviar peticiones HTTP a Medium.
  • lxml: Para analizar contenido HTML.
  • Pandas: Para guardar los datos en un archivo CSV.

Instálelos con los siguientes comandos:


pip install requests
pip install lxml 
pip install pandas

Entender la importancia de las cabeceras y los proxies

Medium utiliza técnicas de detección de bots para evitar el scraping no autorizado. Unas cabeceras y proxies adecuados son cruciales para evitar la detección de bots y para un scraping responsable.

Cabeceras: simulan una solicitud como si procediera de un navegador real. Incluyen información como el tipo de navegador, los tipos de contenido aceptados y el comportamiento de almacenamiento en caché.


headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-language': 'en-IN,en;q=0.9',
    'cache-control': 'no-cache',
    'dnt': '1',
    'pragma': 'no-cache',
    'priority': 'u=0, i',
    'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Linux"',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'none',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
}

Proxies: Los proxies pueden enmascarar tu dirección IP, rotándola periódicamente para que sea menos probable que las peticiones sean bloqueadas por Medium. Aquí tienes un ejemplo de uso con autenticación de dirección IP:


proxies = {
    'http': 'IP:PORT',
    'https': 'IP:PORT'
}

response = requests.get(
 'https://medium.com/techtofreedom/9-python-built-in-decorators-that-optimize-your-code-significantly-bc3f661e9017',
    headers=headers,
    proxies=proxies
)

Enviar una solicitud a Medium

A continuación te explicamos cómo configurar las cabeceras y enviar una petición a la URL del artículo:


import requests

# Cabeceras para simular una petición real del navegador
headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-language': 'en-IN,en;q=0.9',
    'cache-control': 'no-cache',
    'dnt': '1',
    'pragma': 'no-cache',
    'priority': 'u=0, i',
    'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Linux"',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'none',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
}

url = 'https://medium.com/techtofreedom/9-python-built-in-decorators-that-optimize-your-code-significantly-bc3f661e9017'
response = requests.get(url, headers=headers)

Extracción de datos

Una vez tenemos el contenido de la página, podemos parsearlo y extraer información relevante.

Percibiendo el contenido HTML

Usaremos lxml para analizar la respuesta HTML y extraer elementos específicos. He aquí cómo hacerlo:


from lxml.html import fromstring

parser = fromstring(response.text)

# Extraer datos
title = parser.xpath('//h1[@data-testid="storyTitle"]/text()')[0]
author = parser.xpath('//a[@data-testid="authorName"]/text()')[0]
publication_name = parser.xpath('//a[@data-testid="publicationName"]/p/text()')[0]
publication_date = parser.xpath('//span[@data-testid="storyPublishDate"]/text()')[0]
content = '\n '.join(parser.xpath('//div[@class="ci bh ga gb gc gd"]/p/text()'))
auth_followers = parser.xpath('//span[@class="pw-follower-count bf b bg z bk"]/a/text()')[0]
sub_title = parser.xpath('//h2[@id="1de6"]/text()')[0]

Ahora, crearemos un diccionario para guardar todos los datos extraídos. Así será más fácil guardarlos en un archivo CSV.


# Guardar datos en un diccionario
article_data = {
    'Title': title,
    'Author': author,
    'Publication': publication_name,
    'Date': publication_date,
    'Followers': auth_followers,
    'Subtitle': sub_title,
    'Content': content,
}

print(article_data)

Guardar datos en un archivo CSV

Por último, vamos a guardar los datos en un archivo CSV para su posterior análisis o mantenimiento de registros.


import pandas as pd

# Convertir diccionario en DataFrame y guardar como CSV
df = pd.DataFrame([article_data])
df.to_csv('medium_article_data.csv', index=False)
print("Data saved to medium_article_data.csv")

Código completo

Aquí tienes el código completo para scrapear los datos de los artículos de Medium:


import requests
from lxml.html import fromstring
import pandas as pd

# Cabeceras para imitar un navegador
headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-language': 'en-IN,en;q=0.9',
    'cache-control': 'no-cache',
    'dnt': '1',
    'pragma': 'no-cache',
    'priority': 'u=0, i',
    'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Linux"',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'none',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
}


proxies = {
    'http': 'IP:PORT',
    'https': 'IP:PORT'
}

# Solicitar la página
url = 'https://medium.com/techtofreedom/9-python-built-in-decorators-that-optimize-your-code-significantly-bc3f661e9017'
response = requests.get(url, headers=headers, proxies=proxies)

# Análisis de la página
parser = fromstring(response.text)

# Extraer datos
title = parser.xpath('//h1[@data-testid="storyTitle"]/text()')[0]
author = parser.xpath('//a[@data-testid="authorName"]/text()')[0]
publication_name = parser.xpath('//a[@data-testid="publicationName"]/p/text()')[0]
publication_date = parser.xpath('//span[@data-testid="storyPublishDate"]/text()')[0]
content = '\n '.join(parser.xpath('//div[@class="ci bh ga gb gc gd"]/p/text()'))
auth_followers = parser.xpath('//span[@class="pw-follower-count bf b bg z bk"]/a/text()')[0]
sub_title = parser.xpath('//h2[@id="1de6"]/text()')[0]

# Guardar datos
article_data = {
    'Title': title,
    'Author': author,
    'Publication': publication_name,
    'Date': publication_date,
    'Followers': auth_followers,
    'Subtitle': sub_title,
    'Content': content,
}

# Guardar en CSV
df = pd.DataFrame([article_data])
df.to_csv('medium_article_data.csv', index=False)
print("Data saved to medium_article_data.csv")

El scraping de contenidos de Medium debe realizarse de forma responsable. Una carga excesiva de peticiones en los servidores puede afectar al rendimiento del servicio, y el scraping de datos sin permiso puede infringir las condiciones de uso del sitio web. Comprueba siempre el archivo robots.txt y las condiciones antes de hacer scraping de cualquier sitio web.

Comentarios:

0 Comentarios