Выбираю квартиру с помощью парсера на питоне

Понадобилось мне выбрать квартиру и так как каждый день просматривать кучу объявлений на авито мне просто лень, решил я автоматизировать это дело с помощью скрипта на питоне. Квартиры меня интересуют в одном небольшом квадрате города. Также решил в качестве тренировки прикрутить графический интерфейс на kivy. Я далеко не профи в программировании, можно сказать дилетант. В итоге получилось вот что.

Что он умеет —

  • определяет количество страниц с объявлениями в интересующем районе
  • если квартира находится на интересующих меня улицах и домах с нужным количеством этажей сохраняет параметры (номер объявления, параметры квартиры, цену и адрес) в файл с сегодняшнем числом.
  • в консоль выводит тоже самое + ссылку на объявление
  • далее из этого файла можно выбрать квартиры с нужными параметрами (допустим количество комнат)

или на какой-то конкретной улице

также можно убрать улицы или квартиры которые меня точно не интересуют

также составить список квартир по цене, от дешёвых к дорогим

можно добавить комментарии к интересующим квартирам

сохранить это в файл фильтра и потом распечатать

так можно следить за ценой интересующих квартир, так как при первой подаче объявления продавец обычно завышает цену, вот такие файла получаются

Над кодом просьба не ржать, это моя первая программа. А вообще можете ржать, мне пофик.

Импортируем нужные модули

import time
from datetime import datetime
import random

import requests
from bs4 import BeautifulSoup
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

Сначала получаем количество страниц с объявлениями в интересующем районе.

def get_num_page():

    r = requests.get('https://www.avito.ru/barnaul/kvartiry/prodam-ASgBAgICAUSSA8YQ?cd=1&district=170',
                     headers= {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
                        ' AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36'})


    soup = BeautifulSoup(r.text, 'lxml')
    page = soup.find(class_="pagination-root-2oCjZ").find_all(class_="pagination-item-1WyVp")[-2].text
    return int(page)

получаю нужные данные с этих страниц

def content(number, page, file):
    time.sleep(random.randint(5,10))
    r = requests.get('https://www.avito.ru/barnaul/kvartiry/prodam-ASgBAgICAUSSA8YQ?cd=1&district=170&p=' + str(page))
    soup = BeautifulSoup(r.text, 'lxml')
    div = soup.find(class_='snippet-list js-catalog_serp').find_all(class_='item_table-wrapper')

    for i in div:

        try:
            title = i.find('h3').text
        except:
            title = ''
        try:
            url = 'https://www.avito.ru' + i.find('a').get('href')
        except:
            url = ''
        try:
            price = i.find(class_="snippet-price").text
            cena = price.split('₽')[0].split()
            cena = ''.join(cena).strip()
            cena = int(cena)
            price = str(cena) + ' руб ' + price.split('₽')[1].strip()
            # price = ''.join(price)
        except:
            price = ''
        try:
            adres = i.find(class_="item-address__string").text
        except:
            adres = ''

        adres_ = str(adres).lower() 
    # фильтр по улицам и цене
        if 'сухова' not in adres_ and 'чеглецова' not in adres_ and 'смирнова' not in adres_ \
                and 'эмилии' not in adres_ and 'западная' not in adres_ and 'глушкова' not in adres_ \
                and 'путиловская' not in adres_ and 'малахова' not in adres_ and 'тимуровская' not in adres_ \
                and 'дивизии' not in adres_ and 'восточный' not in adres_ and 'западный' not in adres_ \
                and 'лет' not in adres_ and 'чудненко' not in adres_ and 'космонавтов' not in adres_ \
                and 'беляева' not in adres_ and 'титова' not in adres_ and 'кулагина' not in adres_ \
                and '195а' not in adres_ and 'научный' not in adres_ and 100 < cena < 20000000 \
                and 'чихачёва' not in adres_:

            etaj = title.split('/')  # фильтр по этажности
            etaj = etaj[1].split()
            etaj = int(etaj[0])

            if etaj > 3:
                number += 1
                q: str = str(str(number).ljust(6)+':' + title.ljust(35)+':' + price.ljust(15) +':'+ adres.strip().replace(
                    'Алтайский край, Барнаул, ', '').replace('Барнаул, Алтайский край, ', '') + '\n')

                f = open(file +'.txt', 'a', encoding='utf8')

                f.write(q)
                f.close()

Проблемой стало то, что авито быстро понимает что это автоматические запросы и банит нас после нескольких страниц. Парсить без бана удалось с задержкой при открывании страниц от 5 до 10 секунд. Для этого нужна вот эта строчка time.sleep(random.randint(5,10))

Функция для создания нового текстового файла, название файла — текущая дата.

def create_new_file():
    date = datetime.now() #получаем сегодняшнюю дату
    file = str(date)[:11] #отсекаем время
    f = open(file + '.txt', 'w', encoding='utf8') #создаём новый файл  
    f.close()
    return file 

Для того чтобы отсортировать список по цене вызываем функцию select_sort(arr)

def smales_(arr): #получаем список из функции select_sort
    smales = int(arr[0].split(':')[2].split()[0]) #из первого элемента списка (строки) получаем цену  
    index_smales = 0
    for i in range(1,len(arr)):
        a = int(arr[i].split(':')[2].split()[0]) # из текущего элемента списка получаем цену
        if a < smales: # если цена меньше чем наименьшая цена из переменной smales 
            index_smales = i # запоминаем номер элемента списка
            smales = int(arr[i].split(':')[2].split()[0]) # и переписываем наименьшую цену
    return index_smales  # возвращаем индекс элемента списка с наименьшей ценой

def select_sort(arr): # получаем список
    newarr = []       # новый список
    for i in range(len(arr)):
        smales = smales_(arr) # получаем индекс наименьшего элемента
        newarr.append(arr.pop(smales)) # добавляем в конец списка и удаляем 
    return newarr # возвращаем отсортированный список

Скачать полный код парсера.