Как скрапить статьи на ресурсе Medium с использованием Python

Комментарии: 0

Извлечение статей с Medium может быть важным для оценки контента, сбора данных или мониторинга авторов и их работ. В этом руководстве рассматривается процесс скрапинга Medium — сайта для писателей, с использованием языка программирования Python. Обсуждается методика извлечения данных, таких как название статьи, имя автора, название публикации и текст из URL статьи на Medium.

Предустановки

Для этого руководства будет проводиться скрапинг следующей статьи на Medium: “9 Python Built-in Decorators That Optimize Your Code Significantly”.

Перед началом установите следующие библиотеки:

  • Requests: Для отправки HTTP-запросов на Medium;
  • lxml: Для парсинга HTML-контента;
  • Pandas: Для сохранения данных в файл CSV.

Установите их с помощью следующих команд:


pip install requests
pip install lxml 
pip install pandas

Важность использования заголовков и прокси-серверов

Medium использует техники обнаружения ботов для предотвращения неавторизованного скрапинга. Правильно настроенные заголовки и прокси имеют решающее значение для избежания обнаружения ботами.

Заголовки имитируют запрос, как если бы он поступал из настоящего браузера. В них включена информация, такая как тип браузера и поведение кэширования.


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',
}

Прокси маскируют IP-адрес, а если его периодически менять это уменьшает вероятность блокировки запросов к Medium. Пример использования с авторизацией по IP-адресу:


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

response = requests.get(
 'Https URL',
    headers=headers,
    proxies=proxies
)

Отправка запроса на Medium

Ниже представлено как настроить заголовки и отправить запрос на URL статьи:


import requests

# Заголовки для имитации запроса от реального браузера
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 ссылка'
response = requests.get(url, headers=headers)

Извлечение данных

Получив содержимое страницы, можно провести его парсинг и извлечь релевантную информацию.

Парсинг HTML-контента

Для парсинга HTML-ответа и извлечения конкретных элементов будет использоваться библиотека lxml. Вот как это можно сделать:


from lxml.html import fromstring

parser = fromstring(response.text)

# Извлечение данных
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]

Теперь мы создадим словарь для хранения всех извлеченных данных. Это облегчит дальнейшее сохранение в CSV-файл.


# Сохранение данных в словарь
article_data = {
    'Title': title,
    'Author': author,
    'Publication': publication_name,
    'Date': publication_date,
    'Followers': auth_followers,
    'Subtitle': sub_title,
    'Content': content,
}

print(article_data)

Сохранение данных в файл CSV

Далее сохраним данные в файл CSV для дальнейшего анализа или архивирования.


import pandas as pd

# Преобразование словаря в DataFrame и сохранение в CSV
df = pd.DataFrame([article_data])
df.to_csv('medium_article_data.csv', index=False)
print("Data saved to medium_article_data.csv")

Финальный код

Полный код для скрапинга данных статей с Medium выглядит так:


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

# Заголовки для имитации реального браузера
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'
}

# Отправка запроса
url = 'https cсылка'
response = requests.get(url, headers=headers, proxies=proxies)

# Парсинг страницы
parser = fromstring(response.text)

# Извлечение данных
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]

# Сохранение данных
article_data = {
    'Title': title,
    'Author': author,
    'Publication': publication_name,
    'Date': publication_date,
    'Followers': auth_followers,
    'Subtitle': sub_title,
    'Content': content,
}

# Сохранение в CSV
df = pd.DataFrame([article_data])
df.to_csv('medium_article_data.csv', index=False)
print("Data saved to medium_article_data.csv")

Скрапинг контента с Medium должен проводиться ответственно. Чрезмерная нагрузка запросами на серверы может повлиять на работу сервиса, а скрапинг данных без разрешения может нарушать условия использования сайта. Всегда проверяйте файл robots.txt и условия перед скрапингом любого веб-сайта.

Комментарии:

0 комментариев