Мне для анализа данных нужно очень много колонок. Я использую библиотеку cianparser. Задача заключается в том чтобы спарсить объявления по продаже. Но, по какой-то причине, именно то, что мне нужно (находится в списке processed_data) абсолютно не хочет парсится. Пробовала вывести ключи: смотрю, а их там тупо нет, хотя
with_extra_data = True, по идее, должно собирать то что после
if with_extra_data:, но нет.
ключи:
{'author': 'Абсолют Недвижимость', 'author_type': 'developer', 'url': 'https://www.cian.ru/sale/flat/307207783/', 'location': 'Москва', 'deal_type': 'sale', 'accommodation_type': 'flat', 'floor': 14, 'floors_count': 19, 'rooms_count': 1, 'total_meters': 37.6, 'price_per_month': -1, 'commissions': 0, 'price': 9743081, 'district': '', 'street': '', 'house_number': '', 'underground': '', 'residential_complex': 'Город-парк Первый Московский'}
сам код (это еще не все, там ниже будет):
import csv
import cianparser
import os
import time
import random
import requests
import logging
# Настройка логирования
logging.basicConfig(filename='parsing_errors.log', level=logging.ERROR,
format='%(asctime)s:%(levelname)s:%(message)s')
def save_data_to_csv(data, file_name, mode='a'):
if not data:
return
fieldnames = data[0].keys()
file_exists = os.path.isfile(file_name)
with open(file_name, mode, newline='', encoding='utf-8') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
if not file_exists or mode == 'w':
writer.writeheader()
writer.writerows(data)
def get_random_proxy():
proxy_list = [
'117.250.3.58:8080',
'115.96.208.124:8080',
'152.67.0.109:80',
'45.87.68.2:15321',
'68.178.170.59:80',
'20.235.104.105:3729',
'195.201.34.206:80'
]
proxy = random.choice(proxy_list)
return {"http": f"http://{proxy}", "https": f"http://{proxy}"}
csv_name = 'moscow_4.csv'
def collect_real_estate_data(locations, deal_type="sale", rooms=(1), start_page=1, end_page=2,
file_name=csv_name, with_extra_data=True):
all_data = []
user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Gecko/20100101 Firefox/85.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.1 Safari/605.1.15",
]
for location in locations:
parser = cianparser.CianParser(location=location)
print(f"Сбор данных для {location}...")
for page in range(start_page, end_page + 1):
user_agent = random.choice(user_agents)
proxy = get_random_proxy()
session = requests.Session()
session.proxies.update(proxy)
session.headers.update({"User-Agent": user_agent, "Referer": "https://cian.ru"})
retries = 3 # Количество попыток
for attempt in range(retries):
try:
data = parser.get_flats(deal_type=deal_type, rooms=rooms,
additional_settings={"start_page": page, "end_page": page})
break # Если данные успешно получены, выход из цикла
except requests.exceptions.RequestException as e:
print(f"Ошибка запроса страницы {page} для {location}: {e}. Попытка {attempt + 1}/{retries}")
time.sleep(5 + random.uniform(0, 5)) # Пауза перед повтором
if attempt == retries - 1:
logging.error(f"Не удалось получить данные с {page}-й страницы для {location}: {e}")
continue
processed_data = []
for flat in data:
processed_flat = {
"author": flat.get("author", "Не указано"), # Автор
"author_type": flat.get("author_type", "Не указано"), # Тип автора
"url": flat.get("url", "Не указано"),
"price": flat.get("price", "Не указано"), # Цена (для продажи)
"location": flat.get("location", "Не указано"), # Город
"district": flat.get("district", "Не указано"), # Район
"street": flat.get("street", "Не указано"), # Улица
"underground": flat.get("underground", "Не указано"), # Метро
"total_meters": flat.get("total_meters", "Не указано"), # Общая площадь
"rooms_count": flat.get("rooms_count", "Не указано"), # Количество комнат
"floor": flat.get("floor", "Не указано"), # Этаж
"floors_count": flat.get("floors_count", "Не указано"), # Общее количество этажей
"residential_complex": flat.get("residential_complex", "Не указано"), # Название жилого комплекса
}
if with_extra_data:
# все то что так упорно не парсится
processed_flat["object_type"] = flat.get("object_type", "Не указано") # Тип жилья (вторичка/новостройка)
processed_flat["class"] = flat.get("class", "Не указано")
processed_flat["finish_type"] = flat.get("finish_type", "Не указано") # Отделка
processed_flat["heating_type"] = flat.get("heating_type", "Не указано")
processed_flat["house_material_type"] = flat.get("house_material_type", "Не указано") # Тип дома
processed_flat["metro_foot_minute"] = flat.get("metro_foot_minute", "Не указано") # Сколько минут до метро пешком
processed_flat["living_meters"] = flat.get("living_meters", "Не указано") # Жилая площадь
processed_flat["kitchen_meters"] = flat.get("kitchen_meters", "Не указано") # Площадь кухни
processed_flat["ceiling_height"] = flat.get("ceiling_height", "Не указано") # Высота потолка
processed_flat["year_construction"] = flat.get("year_construction", "Не указано") # Год постройки здания
processed_flat["min_house_year"] = flat.get("min_house_year", "Не указано") # Год постройки дома от
processed_flat["parking_type"] = flat.get("parking_type", "Не указано") # Тип парковки
processed_flat["builder"] = flat.get("builder", "Не указано") # Застройщик
processed_flat["have_loggia"] = flat.get("have_loggia", "Не указано") # Наличие лоджии
processed_flat["min_balconies"] = flat.get("min_balconies", "Не указано") # Минимальное количество балконов
processed_flat["max_house_year"] = flat.get("max_house_year", "Не указано") # Год постройки дома до
print(flat)
processed_data.append(processed_flat)
all_data.extend(processed_data)
if len(all_data) >= 100:
save_data_to_csv(all_data[:100], file_name)
all_data = all_data[100:]
time.sleep(random.uniform(2, 4)) # Увеличиваем паузу
if all_data:
save_data_to_csv(all_data, file_name)
all_data = []
print(f"Данные для {location} успешно собраны и сохранены в файл {file_name}")
locations = ["Москва"]
collect_real_estate_data(locations=locations, deal_type="sale", rooms=(1), start_page=1, end_page=50,
file_name=csv_name, with_extra_data=True)
Это был первый вариант кода, а вот второй, в котором если просто поставить with_extra_data=True то он прекрасно парсит часть данных(но не все) которых не хватает. Но object_type при этом все равно, сколько бы он не проходился по объявлениям записывает просто -1, то есть значения нет.
ключи:
{'author': 'VESPER', 'author_type': 'developer', 'url': 'https://www.cian.ru/sale/flat/307211222/', 'location': 'Москва', 'deal_type': 'sale', 'accommodation_type': 'flat', 'floor': 8, 'floors_count': 9, 'rooms_count': 1, 'total_meters': 57.6, 'price': 117936000, 'year_of_construction': '2023', <b>'object_type': -1</b>, 'house_material_type': 'Монолитный', 'heating_type': -1, 'finish_type': 'Без отделки, чистовая с мебелью', 'living_meters': -1, 'kitchen_meters': -1, 'phone': '+74951387184', 'district': 'Тверской', 'street': '1-я Тверская-Ямская ', 'house_number': '2', 'underground': 'Маяковская', 'residential_complex': 'Vesper Tverskaya'}
ну и сам второй вариант кода:
import cianparser
def print_all_keys(data):
for flat in data:
print(flat)
# Создаем экземпляр парсера
parser = cianparser.CianParser(location="Москва")
# Получаем данные
data = parser.get_flats(deal_type="sale", rooms=(1), additional_settings={"start_page": 1, "end_page": 1}, with_extra_data=True, with_saving_csv=True)
# Выводим все ключи
print_all_keys(data)
P.S. Может быть проблемы с соединением? Или не заходит глубже по объявлениям или я как-то неправильно использую сами признаки и методы.