import datetime import requests from bs4 import BeautifulSoup import pandas as pd class NewsParser: def __init__(self): # Можно использовать один session для всех запросов self.requests_session = requests.Session() def parse_news(self, last_days=1): """ Парсит новости с Lenta.ru за указанное число последних дней. :param last_days: количество последних дней, за которые нужно собрать новости. :return: pd.DataFrame с колонками [dates, topics, titles, content]. """ dates = [] topics = [] titles = [] contents = [] # Перебираем дни от 0 до last_days-1 for day in range(last_days): num_pages = 1 # Формируем дату в нужном формате: 'YYYY/MM/DD' date_str = (datetime.datetime.today() - datetime.timedelta(days=day)).strftime('%Y/%m/%d') while True: url = f'https://lenta.ru/{date_str}/page/{num_pages}/' response = self.requests_session.get(url) if response.status_code != 200: break soup = BeautifulSoup(response.text, 'lxml') news_list = soup.find_all('a', {"class": "card-full-news _archive"}, href=True) # Если на странице нет новостей, выходим из цикла пагинации if len(news_list) == 0: break for news in news_list: dates.append(date_str) # Заголовок title_el = news.find('h3', {"class": "card-full-news__title"}) if title_el: titles.append(title_el.get_text(strip=True)) else: titles.append('None') # Рубрика/тема topic_el = news.find('span', {"class": "card-full-news__info-item card-full-news__rubric"}) if topic_el: topics.append(topic_el.get_text(strip=True)) else: topics.append('None') # Текст статьи news_url = 'https://lenta.ru' + news['href'] article_req = self.requests_session.get(news_url) article_soup = BeautifulSoup(article_req.text, 'lxml') paragraphs = article_soup.find_all('p', class_='topic-body__content-text') # Склеиваем все абзацы в одну строку news_content = ' '.join([p.get_text(strip=True) for p in paragraphs]) contents.append(news_content) num_pages += 1 # Формируем DataFrame df = pd.DataFrame({ 'dates': dates, 'topics': topics, 'titles': titles, 'content': contents }) # Преобразуем колонки с датами к формату datetime df['dates'] = pd.to_datetime(df['dates'], errors='coerce') return df if __name__ == "__main__": # Пример использования parser = NewsParser() news_df = parser.parse_news() # Сбор новостей за последние 2 дня print(news_df.head())