YandexDirect

17 января 2019

Python. Что такое парсер сайтов на примере krisha.kz

Начал изучение языка программирования Python, как мне кажется перспективный язык и больше всего подкупила простота кода и визуальная красота. Не буду вдаваться в детали языка, каждый желающий может найти много статей по синтаксису, приведу сам код парсера. Данный скрипт опубликован только в целях изучения языка Python. Приведу также ссылку на видеоуроки , код был взят оттуда и переработан под сайт krisha.kz




import requests
from bs4 import BeautifulSoup
from time import sleep
from selenium import webdriver
import csv

#функция для получения html
def get_html(url):
    r = requests.get(url)
    return r.text

#функция подсчета количества страниц
#используем библиотеку BeautifulSoup для поиска html тегов на странице
#
def get_total_pages(html):
    soup = BeautifulSoup(html, 'lxml') # определяем объект soup
    try:
        divs = soup.find('nav', class_='paginator-public') # находим на странице первый объект nav с именем класса paginator-public
        pages = divs.find_all('a', class_='paginator-page-btn')[-2].get('href') # находим на странице все теги "a" с именем класса paginator-page-btn, из них выбираем элемент с индексом [-2] это будет последняя страница
        total_pages = pages.split('=')[1].split('&')[0] # из полученной ссылки делаем сплит и выбираем значение между знаком "=" и "&"
        return int(total_pages) #возвращаем полученное значение
    except:
        return 2    

#функция для записи csv файла 
def write_csv(data):
    with open('krisha.csv', 'a', encoding='utf-8') as f:
        writer = csv.writer(f)
        writer.writerow((data['title'],
                         data['price'],
                         data['etaj'],
                         data['square'],
                         data['address'],
                         data['description'],
                         data['url'],
                         data['telephone']))
#функция для получения телефонов
#так как на сайте скрыты телефоны, необходимо использовать дополнительный пакет selenium
#для имитации нажатия на ссылку с телефоном, для этого запускается браузер chrome в режиме
#"headless" т.е. без отображения окна
def get_phone(url):
    options = webdriver.ChromeOptions()
    options.add_argument('headless') 
    options.add_argument('window-size=1200x600')
    #driver = webdriver.Chrome('C:\\python37\\chromedriver_win32\\chromedriver.exe') # or Firefox() or smth else
    driver = webdriver.Chrome(options=options) # определяем объект типа webdriver
    driver.get(url) # передаем ему на вход url
    link = driver.find_element_by_id('tm-telephone-body') # переменной link присваиваем ссылку, которая нам покажет телефон
    link.click() # кликаем на ссылку
    sleep(1) # делаем паузу в 1 секунду
    tel = driver.find_element_by_class_name('offer__contacts-phones').text.strip() # присваиваем переменной tel показанные номера телефонов
    driver.quit() # не забываем закрывать невидимый браузер
    return tel # возвращаем телефон

# функция получения данных с сайта, используем библиотеку BeautifulSoup, она позволяет выполнять поиск по html тегам
# 
def get_page_data(html):
    soup = BeautifulSoup(html, 'lxml') # определяем объект soup
    divs = soup.find('section', class_='a-list') # находим тег section с именем класса a-list
    ads = divs.find_all('div', class_='a-card__inc') # в найденном объекте ищем все div с классом a-card__inc
    # запускаем цикл по всем найденным полям, которые нас интересуют
    # т.к. ссылка состоит 3-комнатная квартира, 79.4 м², 5/5 эт. я решил ее разделить на поля квартира, площадь, этаж
    # далее выбираем цену, адрес и описание
    #
    for ad in ads:
        try:
            div = ad.find('a', class_='a-card__title').text
            kv = div.split(",")[0] 
        except:
            kv = ''
        try:
            div = ad.find('a', class_='a-card__title').text
            square = div.split(",")[1]
        except:
            square  = ''
        try:
            div = ad.find('a', class_='a-card__title').text
            etaj = div.split(",")[2]
        except:
            etaj  = ''            

        try:
            price = ad.find('div', class_='a-card__price').text.strip()
        except:
            price = ''
        
        try:
            address = ad.find('div', class_='a-card__subtitle').text.strip()
        except:
            address = ''
        try:
            descr = ad.find('div', class_='a-card__text-preview').text.strip()
        except:
            descr = ''
        try:
            div = ad.find('div', class_='a-card__header-left')
            url = "https://krisha.kz" + div.find('a').get('href')
            #tel = ''
        except:
            url = ''
            #tel = ''

        tel1 = get_phone(url) # тут вызываем функцию выборки телефонов
        # определяем кортеж из наших полей и передаем его функции write_csv    
        data = {'title':kv,
                'price':price,
                'etaj':etaj,
                'square':square,
                'address':address,
                'description':descr,
                'url':url,
                'telephone':tel1}
        write_csv(data)
            
# основная функция 
# базовый url для Астаны имеет вид https://krisha.kz/prodazha/kvartiry/astana/
# к нему добавляется запрос query_part и еще дальше идет блок со страницами page_part
# 
def main():
    #url = 'https://krisha.kz/prodazha/kvartiry/astana/?das[live.rooms]=1'
    base_url = 'https://krisha.kz/prodazha/kvartiry/astana/'
    page_part = '&page='
    query_part = '?das[live.rooms]=1'
    total_pages = get_total_pages(get_html(url))
    # 
    for i in range(1, total_pages):
        url_gen = base_url + query_part + page_part + str(i)
        html = get_html(url_gen)
        get_page_data(html)

    # html = get_html('https://krisha.kz/prodazha/kvartiry/astana/?das[live.rooms]=1')
    # get_page_data(html)

#блок main
if __name__ == '__main__':
    main()

полученный в результате работы скрипта csv выглядит так, здесь я намерено убрал часть телефонных номеров:


1-комнатная квартира,16 500 000 ₸, 19/21 эт., 70 м²,"р-н Байконур, Кенесары","монолитный дом, 2014 г.п., состояние: хорошее, санузел раздельный, частично меблирована, Все необходимое рядом: магазины, супермаркеты, аптеки, школы и дошкольные учреждения, остановки общественного транспорта. Район с хорошей инфраструктурой. В квартире очень приятный микроклимат. Вкладывая де…",https://krisha.kz/a/show/48283479,+7 ... 8924
1-комнатная квартира,12 750 000 ₸, 6/10 эт., 43 м²,"Алматинский р-н, Переулок Сартау 16","жил. комплекс Сарытау, монолитный дом, 2016 г.п., состояние: евроремонт, потолки 2.7м., санузел совмещенный, телефон: есть возможность подключения, интернет оптика, частично меблирована, ЖК «Сарытау» состоит из одного 10-этажного дома, выполненного по оригинальному проекту, и расположен в тих…",https://krisha.kz/a/show/47455009,+7 ... 3397
1-комнатная квартира,11 800 000 ₸, 11/16 эт., 46 м²,"р-н Байконур, Бейсекбаева","жил. комплекс Гранитный, монолитный дом, 2014 г.п., состояние: евроремонт, потолки 3м., санузел совмещенный, частично меблирована, Продается 1-комнатная квартира в ЖК ""Гранитный"" по ул. Бейсекбаева, Иманова с ремонтом! Район БТИ. Удобная транспортная развязка. Квартира теплая, уютная. Продажа…",https://krisha.kz/a/show/47783199,"+7 ... 3377
+7 ... 9696"
1-комнатная квартира,7 800 000 ₸, 13/13 эт., 23.6 м²,"Алматинский р-н, Сатпаева 20а — Момышулы","жил. комплекс 12 месяцев, 2018 г.п., состояние: евроремонт, жил. площадь 15 кв.м., кухня 5 кв.м., санузел совмещенный, Продам 1 комн-студию по Сатпаева-Момышулы напротив Ресторана Туран, 5минут до Байтерек. Квартира абсолютно новая, новый евроремонт качественно делали для себя, сантехника вся н…",https://krisha.kz/a/show/47352917,"+7 ... 1805
+7 ... 9123"
1-комнатная квартира,20 500 000 ₸, 4/8 эт., 50.6 м²,"Есильский р-н, Алихана Бокейханова — проспект Мангилик Ел","жил. комплекс Vivat Promenade, монолитный дом, 2018 г.п., состояние: евроремонт, потолки 3м., санузел совмещенный, телефон: отдельный, частично меблирована, Продается одна комнатная квартира в новом доме 2018 года. Жилой комплекс «Vivat Promenade» находится возле международного выставочн…",https://krisha.kz/a/show/48169299,"+7 ... 3377
+7 ... 9696"
1-комнатная квартира,12 500 000 ₸, 12 эт., 42 м²,"Есильский р-н, Чингиза Айтматова 36/8 — Кайыма Мухамедханова","жил. комплекс Памир, монолитный дом, 2018 г.п., состояние: евроремонт, санузел раздельный, телефон: есть возможность подключения, интернет через TV кабель, пустая, Жилой комплекс Памир новостройка на левобережье Астаны, южнее Кургальджинского шоссе, на левом берегу р. Ишим, за ТРЦ «Хан Шаты…",https://krisha.kz/a/show/46923223,+7 ... 3840


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

Отправить комментарий

Общее·количество·просмотров·страницы