Repository navigation
Expand file tree
/
Copy pathparser.py
More file actions
118 lines (90 loc) · 4.84 KB
/
Copy pathparser.py
File metadata and controls
118 lines (90 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import time
import pandas as pd
import requests
from bs4 import BeautifulSoup
# Базовый URL для парсинга новостей
BASE_URL = "https://lenta.ru/parts/news/"
HOST = "https://lenta.ru"
# Заголовки, чтобы сайт не заблокировал запрос
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
def parse_lenta_news(pages_count=2, max_items=15):
news_list = []
for page in range(1, pages_count + 1):
# Формируем URL для каждой страницы
url = f"{BASE_URL}{page}/" if page > 1 else BASE_URL
print(f"Парсинг страницы: {url}")
try:
response = requests.get(url, headers=HEADERS, timeout=10)
if response.status_code != 200:
print(f"Ошибка доступа к странице: {response.status_code}")
continue
soup = BeautifulSoup(response.text, "html.parser")
# Находим контейнеры новостей
articles = soup.find_all(["a", "div", "article"], class_=["card-mini", "card-full-news", "_parts-page"])
# Если не нашли, ищем по общим элементам списков новостей
if not articles:
articles = soup.select(".parts-page__item, .rubric-page__item, [class*='card-mini']")
for article in articles:
if len(news_list) >= max_items:
break
# Определяем тег ссылки
link_tag = article if article.name == "a" else article.find("a")
if not link_tag:
continue
# Извлекаем веб-ссылку
link = link_tag.get("href")
if not link:
continue
if not link.startswith("http"):
link = HOST + link
# Извлекаем заголовок (проверяем разные классы текстов)
title_tag = article.find(["span", "h3", "div"], class_=["card-mini__title", "card-full-news__title", "titles__title"])
if not title_tag:
title_tag = link_tag # Иногда текст заголовка лежит прямо внутри ссылки
title = title_tag.text.strip() if title_tag else "Без названия"
# Пропускаем технические пустые элементы
if title == "Без названия" or not title:
continue
# Извлекаем время публикации
time_tag = article.find(["time", "span"], class_=["card-mini__date", "card-mini__info", "card-full-news__info"])
if not time_tag:
time_tag = article.find("time")
pub_date = (
time_tag.text.strip()
if time_tag
else "Дата не указана"
)
news_list.append(
{
"Дата публикации": pub_date,
"Заголовок": title,
"Ссылка": link,
}
)
if len(news_list) >= max_items:
break
# Небольшая пауза между запросами
time.sleep(1.5)
except Exception as e:
print(f"Произошла ошибка при парсинге страницы {page}: {e}")
# Переводим в DataFrame и сохраняем
df = pd.DataFrame(news_list)
return df
# Запуск парсера
if __name__ == "__main__":
# Собираем ровно 15 позиций с 2 страниц
result_df = parse_lenta_news(pages_count=2, max_items=15)
# Сохраняем в результирующий файл Excel
file_name = "lenta_news_parsed.xlsx"
result_df.to_excel(file_name, index=False)
print(f"\n Парсинг успешно завершен!")
print(f"Собрано позиций: {len(result_df)}")
print(f"Файл сохранен как: {file_name}")
# Выведем результат в консоль для демонстрации
print("\n Пример собранных данных:")
if not result_df.empty:
print(result_df.head())
else:
print("Данные не найдены. Проверьте структуру страницы.")