Untitled
unknown
python
a month ago
10 kB
3
Indexable
Never
from elems import Elems from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException import time from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.firefox.options import Options from selenium import webdriver from selenium.webdriver.firefox.service import Service as FirefoxService from webdriver_manager.firefox import GeckoDriverManager from typing import Optional, Any from exceptions import ERRORS from utilities import get_date_from_days, read_csv import os import csv import pandas as pd from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel, QFileDialog, QLineEdit, QCalendarWidget, QPushButton, QCheckBox, QTabWidget, QMessageBox) from datetime import datetime class BookingBot(Elems): FIELD_NAMES = ["NAME", "PRICE", 'START_DATE', 'END_DATE'] def __init__(self, driver: webdriver.Firefox) -> None: self.driver = driver self.errors = [] self.filename = str(round(time.time(), 0)).replace(".0", "") def open_page(self, url) -> Optional[Any]: self.driver.get(url) def div_control(self): try: self.wait_element(self.CARD_DIV) except NoSuchElementException: self.is_continue = False self.errors.append({"code": 1000, "message": ERRORS.get(1000)}) def get_price(self): try: div = self.driver.find_element(*self.CARD_DIV) return div.find_element(*self.PRICE_SPAN).text except NoSuchElementException: return "Rezervasyon Bulunamadi" def record_to_csv(self, data: list): if not os.path.exists(f"datas/{self.filename}.csv"): with open(f"./datas/{self.filename}.csv", 'w', encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=self.FIELD_NAMES) writer.writeheader() with open(f"./datas/{self.filename}.csv", "a+", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=self.FIELD_NAMES) writer.writerow( {"NAME": data[0], "PRICE": data[1], "START_DATE": data[2], "END_DATE": data[3]}) def wait_element(self, selector, time=10): element = WebDriverWait(self.driver, 10).until( EC.visibility_of_element_located( selector) ) return element def close_driver(self): self.driver.quit() def csv_summary(self, adult_count, child_count, room_count): # CSV dosyasını oku df = pd.read_csv(f"./datas/{self.filename}.csv") # Euro simgesini ve binlik ayracı kaldır df['PRICE'] = df['PRICE'].replace({'€': ' '}, regex=True) df['PRICE'] = df['PRICE'].str.replace( r'(?<=\d)\.(?=\d{3})', '', regex=True) # "Rezervasyon Bulunamadı" olanları temizle ve sayısal değere dönüştür # Geçersiz değerleri NaN ile değiştirir df['PRICE'] = pd.to_numeric(df['PRICE'], errors='coerce') # NaN olanları kaldır df = df.dropna(subset=['PRICE']) # Pozitif fiyatları filtrele filtered_df = df[df['PRICE'] > 0] if filtered_df.empty: print("Filtrelenmiş veri çerçevesi boş. Fiyat verisi içermiyor.") return # Ortalama fiyat, en düşük ve en yüksek fiyatı hesapla average_price = filtered_df['PRICE'].mean() min_price = filtered_df['PRICE'].min() max_price = filtered_df['PRICE'].max() std_dev = filtered_df['PRICE'].std() # En düşük ve en yüksek fiyatlı otel isimlerini bulma min_price_hotel = filtered_df.loc[filtered_df['PRICE'] == min_price, 'NAME'].values max_price_hotel = filtered_df.loc[filtered_df['PRICE'] == max_price, 'NAME'].values if min_price_hotel.size == 0 or max_price_hotel.size == 0: print("En düşük veya en yüksek fiyatlı otel bilgisi bulunamadı.") return # İlk otel adını al (Çoğunlukla tek bir otel olur ama bu, birden fazla otel varsa en iyisidir) min_price_hotel_name = min_price_hotel[0] max_price_hotel_name = max_price_hotel[0] # Summary metni oluştur summary = (f"\nFiltreler:\nSorgu Tarihi: {datetime.today()}\nYetiskin Sayisi: {adult_count}\nCocuk Sayisi: {child_count}\nOda Sayisi: {room_count}\n\n" f"Ortalama Fiyat: {average_price:.2f}\n" f"Standart Sapma: {std_dev:.2f}\n" f"En Dusuk Fiyat: {min_price:.2f} (En Dusuk Fiyatli Otel: { min_price_hotel_name})\n" f"En Yuksek Fiyat: {max_price:.2f} (En Yuksek Fiyatli Otel: {max_price_hotel_name})") # Sonuçları dosyaya yaz with open(f"./datas/{self.filename}.csv", 'a', encoding="utf-8") as file: file.write(summary) def csv_to_excel(self): # CSV dosyasının yolu csv_file = f"./datas/{self.filename}.csv" # CSV dosyasını pandas ile oku df = pd.read_csv(csv_file) # Excel dosyasının yolu excel_file = f"./datas/{self.filename}.xlsx" # CSV'yi Excel'e dönüştür df.to_excel(excel_file, index=False) # CSV dosyasını sil if os.path.exists(csv_file): os.remove(csv_file) else: print(f"{csv_file} bulunamadi.") def run_bot(adult_count, child_count, room_count, start_date, end_date, background): firefox_options = Options() firefox_options.set_preference( "dom.disable_open_during_load", True) # Pop-up'ları engelle firefox_options.set_preference("dom.webnotifications.enabled", False) if background: firefox_options.add_argument("--headless") driver = webdriver.Firefox( service=FirefoxService(GeckoDriverManager().install()), options=firefox_options ) driver.maximize_window() bot = BookingBot(driver=driver) data = read_csv("./new_urls.csv") for name, url in data: url = url.replace("||start_date||", start_date).replace( "||end_date||", end_date).replace( "||adult_count||", adult_count).replace( "||children_count||", child_count).replace( "||room_count||", room_count) bot.open_page(url) time.sleep(1) if bot.errors: price = str(bot.errors) else: price = bot.get_price() bot.record_to_csv([name, price, start_date, end_date]) time.sleep(2) bot.driver.quit() bot.csv_summary(adult_count, child_count, room_count) bot.csv_to_excel() def check_inputs(): adult_count = yetiskin_input.text() child_count = cocuk_input.text() room_count = oda_input.text() start_date = start_calendar.selectedDate().toString("yyyy-MM-dd") end_date = end_calendar.selectedDate().toString("yyyy-MM-dd") background = background_checkbox.isChecked() valid = True if not adult_count or not child_count or not room_count: QMessageBox.warning(window, 'Hata', 'Tüm alanları doldurun!') valid = False if end_date < start_date: QMessageBox.warning( window, 'Hata', 'Çıkış tarihi giriş tarihinden önce olamaz!') valid = False if valid: # run_bot fonksiyonuna takvimden seçilen tarihleri de gönderiyoruz run_bot(adult_count, child_count, room_count, start_date, end_date, background) QMessageBox.information(window, 'Başarılı', 'Bot çalıştırıldı!') QApplication.quit() if __name__ == "__main__": app = QApplication([]) window = QWidget() window.setWindowTitle('Booking') tab_widget = QTabWidget() general_tab = QWidget() general_layout = QVBoxLayout() # Kaç gün sonrası input alanı day_label = QLabel('Kaç gün sonrası: ') day_input = QLineEdit() # Yetişkin sayısı input alanı yetiskin_label = QLabel('Yetişkin sayısı (1-30):') yetiskin_input = QLineEdit() # Çocuk sayısı input alanı cocuk_label = QLabel('Çocuk sayısı (1-10):') cocuk_input = QLineEdit() # Oda sayısı input alanı oda_label = QLabel('Oda sayısı (1-30):') oda_input = QLineEdit() # Genel bilgileri layout'a ekle general_layout.addWidget(yetiskin_label) general_layout.addWidget(yetiskin_input) general_layout.addWidget(cocuk_label) general_layout.addWidget(cocuk_input) general_layout.addWidget(oda_label) general_layout.addWidget(oda_input) general_tab.setLayout(general_layout) # İkinci sekme (Tarih Seçimi) date_tab = QWidget() date_layout = QVBoxLayout() # Başlangıç ve bitiş tarihi için QCalendarWidget start_calendar_label = QLabel('Başlangıç Tarihi Seçin:') start_calendar = QCalendarWidget() start_calendar.setGridVisible(True) end_calendar_label = QLabel('Bitiş Tarihi Seçin:') end_calendar = QCalendarWidget() end_calendar.setGridVisible(True) # Takvim widget'larını layout'a ekle date_layout.addWidget(start_calendar_label) date_layout.addWidget(start_calendar) date_layout.addWidget(end_calendar_label) date_layout.addWidget(end_calendar) date_tab.setLayout(date_layout) # Üçüncü sekme (Diğer Ayarlar) other_tab = QWidget() other_layout = QVBoxLayout() # Arka planda çalıştırma için QCheckBox background_checkbox = QCheckBox("Arka planda çalıştırılsın mı?") # Gönder butonu submit_button = QPushButton('Gönder') submit_button.clicked.connect(check_inputs) # Diğer ayarları layout'a ekle other_layout.addWidget(background_checkbox) other_layout.addWidget(submit_button) other_tab.setLayout(other_layout) # Sekmeleri QTabWidget'e ekle tab_widget.addTab(general_tab, "Genel Bilgiler") tab_widget.addTab(date_tab, "Tarih Seçimi") tab_widget.addTab(other_tab, "Botu Başlat") # Ana layout oluştur ve tab widget'ı ekle layout = QVBoxLayout() layout.addWidget(tab_widget) window.setLayout(layout) window.show() app.exec_()
Leave a Comment