├── .gitignore ├── mail.png ├── readme.md ├── requirements.txt ├── run.py └── turkey_airlines_codes.json /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .idea -------------------------------------------------------------------------------- /mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Abdulkadirbulbul/ucuza-bilet/bb49036f4ea6515dffc685758742b5186be628e2/mail.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Ucuza Uçuş Bileti [TR] 3 | 4 | Bu Python uygulaması, sizin istediğiniz eşik fiyatın altına düşen uçuşları size mail olarak gönderir. 5 | Verileri https://www.ucuzabilet.com/ sitesinden çekmektedir ve belirli aralıklarda bu işlemi tekrar ettirebilirsiniz. 6 | 7 | ![Ucuza_Bilet](mail.png) 8 | 9 | ## Kullanım 10 | 11 | 1. **Kütüphanelerin Yüklenmesi:** 12 | - Projeyi çalıştırmadan önce gerekli kütüphaneleri yükleyin. 13 | ```bash 14 | pip install -r requirements.txt 15 | ``` 16 | 17 | 2. **E-posta Ayarları:** 18 | - `send_mail` fonksiyonunda e-posta gönderme işlemi yapılmaktadır. Bu kısmı kendi e-posta bilgilerinizle güncelleyin. 19 | - **Burada dikkat edilmesi gereken nokta gönderici Google hesabınıza gidip 2 adımlı doğrulamayı aktif edip arama yerine uygulama anahtarı yazıp şifre almanız gerekir. 16 haneli bu şifreyi burada kullanabilrisiniz. Mail hesabınızın şifresini yazmanız hata verecektir.** 20 | - Güvenlik nedeniyle e-posta ve şifrenizi doğrudan kod içinde tutmaktan kaçının. Gerekirse çevresel değişkenler veya başka bir güvenli yöntem kullanın. 21 | 22 | 3. **Uçuş Bilgisi Alma:** 23 | - `ucuzabilet_fiyatlari_al` fonksiyonunda hangi tarihler arasındaki uçuşları almak istediğinizi belirtin. 24 | - `nereden`, `nereye`, `b_tarih`, `bit_tarih`, `istenilen_max_fiyat` gibi değişkenleri girmeniz gerekir. 25 | 26 | 27 | 28 | ## Projenin Çalıştırılması 29 | 30 | 1. Konsol ekranında programı çalıştırın. 31 | ```bash 32 | python run.py 33 | 2. Kodunuzu ücretsiz bir python editörde 7/24 ücretsiz çalıştırın. Bunun için > https://www.pythonanywhere.com/ ziyaret edebilirsiniz. 34 | 35 | ## Bize Ulaşın 36 | 37 | [![Instagram](https://skillicons.dev/icons?i=instagram)](https://www.instagram.com/kadirbulbulcom/) 38 | [![LinkedIn](https://skillicons.dev/icons?i=linkedin)](https://www.linkedin.com/in/abdulkadirbulbul/) 39 | 40 | 41 | # Cheap Fly Tickets [EN] 42 | 43 | This Python application e-mails you flights that fall below your desired threshold price. 44 | It pulls the data from https://www.ucuzabilet.com/ and you can repeat this process at certain intervals. 45 | 46 | ![Ucuza_Bilet](mail.png) 47 | 48 | 49 | ## Use 50 | 51 | 1. **Installing Libraries:** 52 | - Install the necessary libraries before running the project. 53 | ```bash 54 | pip install -r requirements.txt 55 | ``` 56 | 57 | 2. **Email Settings:** 58 | - Sending e-mail is done in the `send_mail` function. Update this section with your own email information. 59 | - **The point to note here is that you must go to your sender's Google account, activate 2-step verification, type the application key in the search field and get the password. You can use this 16-digit password here. Typing your email account password will give an error.** 60 | - For security reasons, avoid keeping your email and password directly in the code. Use environmental variables or another safe method if necessary. 61 | 62 | 3. **Getting Flight Information:** 63 | - In the `cheapabilet_fiyatlari_al` function, specify the flights between which dates you want to buy. 64 | - You need to enter variables such as `from`, `where to`, `b_date`, `bit_date`, `desired_max_price`. 65 | 66 | 67 | 68 | ## Running the Project 69 | 70 | 1. Run the program on the console screen. 71 | ```bash 72 | python run.py 73 | 2. Run your code in a free python editor 24/7 for free. For this, you can visit > https://www.pythonanywhere.com/. 74 | 75 | ## Contact Us 76 | 77 | [![Instagram](https://skillicons.dev/icons?i=instagram)](https://www.instagram.com/kadirbulbulcom/) 78 | [![LinkedIn](https://skillicons.dev/icons?i=linkedin)](https://www.linkedin.com/in/abdulkadirbulbul/) 79 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4==4.12.3 2 | certifi==2023.11.17 3 | charset-normalizer==3.3.2 4 | DateTime==5.4 5 | idna==3.6 6 | python-decouple==3.8 7 | pytz==2023.3.post1 8 | requests==2.31.0 9 | secure-smtplib==0.1.1 10 | soupsieve==2.5 11 | urllib3==2.1.0 12 | zope.interface==6.1 13 | -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from datetime import datetime, timedelta 3 | from bs4 import BeautifulSoup 4 | import smtplib 5 | import os 6 | from dotenv import load_dotenv 7 | 8 | load_dotenv() 9 | 10 | chat_id=os.getenv("TELEGRAM_MESSAGE_ID") 11 | api_key=os.getenv("TELEGRAM_API_KEY") 12 | gonderici_mail = os.getenv("SENDER_MAIL") 13 | gonderici_mail_uygulama_anahtari = os.getenv("SENDER_MAIL_APP_KEY") 14 | alici_mail = os.getenv("RECIPIENT_MAIL") 15 | url = f"https://api.telegram.org/bot{api_key}/sendMessage" 16 | 17 | def send_telegram_message(api_key, chat_id, flight_data): 18 | 19 | message = createMessage(flight_data) 20 | 21 | # Telegram mesaj uzunluğu sınırlaması (4096 karakter) 22 | max_length = 4096 23 | 24 | # Mesajı uygun bir uzunluğa böl 25 | while len(message) > max_length: 26 | partial_message = message[:max_length] 27 | 28 | # Kalan kısmı al 29 | message = message[max_length:] 30 | 31 | # Mesajı gönder 32 | send_partial_message(api_key, chat_id, partial_message) 33 | 34 | # Son kısmı gönder 35 | send_partial_message(api_key, chat_id, message) 36 | 37 | def send_partial_message(api_key, chat_id, partial_message): 38 | data = {'chat_id': chat_id, 'text': partial_message} 39 | response = requests.post(url, data=data) 40 | 41 | if response.status_code == 200: 42 | print("Mesaj başarıyla gönderildi.") 43 | else: 44 | print(f"Mesaj gönderme hatası: {response.status_code}, {response.text}") 45 | 46 | 47 | def createMessage(flight_data): 48 | message = "Ucuz Uçuş Bulundu:\n\n" 49 | for flight in flight_data: 50 | message += f"Havayolu: {flight[0]}\n" 51 | message += f"Uçuş Numarası: {flight[1]}\n" 52 | message += f"Kalkış Saati: {flight[2]}\n" 53 | message += f"Süre: {flight[3]}\n" 54 | message += f"Fiyat: {flight[4]}\n" 55 | message += f"Tarih: {flight[5]}\n\n" 56 | return message 57 | 58 | def send_mail(flight_data): 59 | content = createMessage(flight_data) 60 | try: 61 | mail = smtplib.SMTP('smtp.gmail.com', 587) 62 | mail.ehlo() 63 | mail.starttls() 64 | sender = gonderici_mail 65 | recipient = alici_mail 66 | mail.login("upworkali2289@gmail.com", "vbgl uygg foex wzkw") 67 | subject = 'Ucuz Uçuş Bulundu' 68 | header = f'To: {recipient}\nFrom: {sender}\nSubject: {subject}\n' 69 | content = header + content 70 | mail.sendmail(sender, recipient, content.encode('utf-8')) 71 | mail.close() 72 | print("E-posta başarıyla gönderildi!") 73 | except Exception as e: 74 | print(f"Hata: {e}") 75 | 76 | def ucuzabilet_fiyatlari_al(nereden, nereye, baslangic_tarihi, gun_farki): 77 | gun_farki = int(gun_farki) 78 | tum_fiyatlar = [] 79 | while gun_farki > -1: 80 | baslangic_tarihi_str = str(baslangic_tarihi)[0:10] 81 | base_url = "https://www.ucuzabilet.com/ic-hat-arama-sonuc" 82 | params = { 83 | "from": nereden, 84 | "to": nereye, 85 | "toIsCity": 1, 86 | "ddate": baslangic_tarihi_str, 87 | "adult": 1, 88 | "directflightsonly": "on" 89 | } 90 | 91 | response = requests.get(base_url, params=params) 92 | soup = BeautifulSoup(response.content, "html.parser") 93 | try: 94 | tbody = soup.find("tbody").find_all("tr", {"data-direction": "flights"}) 95 | for tr in tbody: 96 | airlines = tr.find("div", {"class": "airline"}).text 97 | flight_number = tr.find("div", {"class": "flight-number"}).text.strip() 98 | flight_time = tr.find("b", {"class": "flight-time"}).text.strip() 99 | flight_duration = tr.find("span", {"class": "flight-duration"}).text.strip() 100 | price = tr.find("div", {"class": "btn-center"}).find("i", {"class": "integers"}).text.strip() + "TL" 101 | tum_fiyatlar.append( 102 | [airlines, flight_number, flight_time, flight_duration, price, baslangic_tarihi_str] 103 | ) 104 | except: 105 | print("Uçuş bulunamadı.") 106 | baslangic_tarihi += timedelta(days=1) 107 | gun_farki -= 1 108 | 109 | return tum_fiyatlar 110 | 111 | if __name__ == "__main__": 112 | nereden = input("Nereden: ") 113 | nereye = input("Nereye: ") 114 | try: 115 | b_tarih = input("Başlangıç Tarihi: Örnek > 01.01.2024 ") 116 | bit_tarih = input("Bitiş Tarihi: Örnek > 20.01.2024 ") 117 | baslangic_tarihi = datetime.strptime(b_tarih, "%d.%m.%Y") 118 | bitis_tarihi = datetime.strptime(bit_tarih, "%d.%m.%Y") 119 | except: 120 | print("Tarihleri yanlış girdiniz.") 121 | exit() 122 | istenilen_max_fiyat = int(input("Max Fiyat: Örnek 1300 > ")) 123 | 124 | gun_farki = (bitis_tarihi - baslangic_tarihi).days 125 | 126 | fiyatlar = ucuzabilet_fiyatlari_al(nereden, nereye, baslangic_tarihi, gun_farki) 127 | result = [] 128 | if fiyatlar: 129 | print("Uygun Uçuş fiyatları Bulundu:") 130 | for fiyat in fiyatlar: 131 | if int(fiyat[4][:-2]) < istenilen_max_fiyat: 132 | result.append(fiyat) 133 | print(result) 134 | if len(result) > 0: 135 | # send_mail(result) 136 | send_telegram_message(api_key, chat_id, result) 137 | else: 138 | print("Uygun uçuş bulunamadı.") 139 | -------------------------------------------------------------------------------- /turkey_airlines_codes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Rank": 1, 4 | "Airport": "Istanbul Airport", 5 | "Location": "Istanbul", 6 | "Code": "IST" 7 | }, 8 | { 9 | "Rank": 2, 10 | "Airport": "Sabiha Gökçen International Airport", 11 | "Location": "Istanbul", 12 | "Code": "SAW" 13 | }, 14 | { 15 | "Rank": 3, 16 | "Airport": "Antalya Airport", 17 | "Location": "Antalya", 18 | "Code": "AYT" 19 | }, 20 | { 21 | "Rank": 4, 22 | "Airport": "Esenboğa International Airport", 23 | "Location": "Ankara", 24 | "Code": "ESB" 25 | }, 26 | { 27 | "Rank": 5, 28 | "Airport": "Adnan Menderes Airport", 29 | "Location": "Izmir", 30 | "Code": "ADB" 31 | }, 32 | { 33 | "Rank": 6, 34 | "Airport": "Adana Şakirpaşa Airport", 35 | "Location": "Adana", 36 | "Code": "ADA" 37 | }, 38 | { 39 | "Rank": 7, 40 | "Airport": "Trabzon Airport", 41 | "Location": "Trabzon", 42 | "Code": "TZX" 43 | }, 44 | { 45 | "Rank": 8, 46 | "Airport": "Dalaman Airport", 47 | "Location": "Muğla / Dalaman", 48 | "Code": "DLM" 49 | }, 50 | { 51 | "Rank": 9, 52 | "Airport": "Milas-Bodrum Airport", 53 | "Location": "Muğla / Bodrum", 54 | "Code": "BJV" 55 | }, 56 | { 57 | "Rank": 10, 58 | "Airport": "Oğuzeli Airport", 59 | "Location": "Gaziantep / Oğuzeli", 60 | "Code": "GZT" 61 | }, 62 | { 63 | "Rank": 11, 64 | "Airport": "Kayseri Erkilet Airport", 65 | "Location": "Kayseri", 66 | "Code": "ASR" 67 | }, 68 | { 69 | "Rank": 12, 70 | "Airport": "Diyarbakır Airport", 71 | "Location": "Diyarbakır", 72 | "Code": "DIY" 73 | }, 74 | { 75 | "Rank": 13, 76 | "Airport": "Van Ferit Melen Airport", 77 | "Location": "Van", 78 | "Code": "VAN" 79 | }, 80 | { 81 | "Rank": 14, 82 | "Airport": "Erzurum Airport", 83 | "Location": "Erzurum", 84 | "Code": "ERZ" 85 | }, 86 | { 87 | "Rank": 15, 88 | "Airport": "Hatay Airport", 89 | "Location": "Hatay/Antakya", 90 | "Code": "HTY" 91 | }, 92 | { 93 | "Rank": 16, 94 | "Airport": "Konya Airport", 95 | "Location": "Konya", 96 | "Code": "KYA" 97 | }, 98 | { 99 | "Rank": 17, 100 | "Airport": "Ordu Giresun Airport", 101 | "Location": "Ordu", 102 | "Code": "OGU" 103 | }, 104 | { 105 | "Rank": 18, 106 | "Airport": "Samsun-Çarşamba Airport", 107 | "Location": "Samsun/Çarşamba", 108 | "Code": "SZF" 109 | }, 110 | { 111 | "Rank": 19, 112 | "Airport": "Elazığ Airport", 113 | "Location": "Elazığ", 114 | "Code": "EZS" 115 | }, 116 | { 117 | "Rank": 20, 118 | "Airport": "Malatya Erhaç Airport", 119 | "Location": "Malatya", 120 | "Code": "MLX" 121 | }, 122 | { 123 | "Rank": 21, 124 | "Airport": "Şanlıurfa GAP Airport", 125 | "Location": "Şanlıurfa", 126 | "Code": "GNY" 127 | }, 128 | { 129 | "Rank": 22, 130 | "Airport": "Gazipaşa Airport", 131 | "Location": "Antalya/Alanya", 132 | "Code": "GZP" 133 | }, 134 | { 135 | "Rank": 23, 136 | "Airport": "Denizli Çardak Airport", 137 | "Location": "Denizli/Çardak", 138 | "Code": "DNZ" 139 | }, 140 | { 141 | "Rank": 24, 142 | "Airport": "Mardin Airport", 143 | "Location": "Mardin", 144 | "Code": "MQM" 145 | }, 146 | { 147 | "Rank": 25, 148 | "Airport": "Kars Airport", 149 | "Location": "Kars", 150 | "Code": "KSY" 151 | }, 152 | { 153 | "Rank": 26, 154 | "Airport": "Sivas Airport", 155 | "Location": "Sivas", 156 | "Code": "VAS" 157 | }, 158 | { 159 | "Rank": 27, 160 | "Airport": "Batman Airport", 161 | "Location": "Batman", 162 | "Code": "BAL" 163 | }, 164 | { 165 | "Rank": 28, 166 | "Airport": "Erzincan Airport", 167 | "Location": "Erzincan", 168 | "Code": "ERC" 169 | }, 170 | { 171 | "Rank": 29, 172 | "Airport": "Muş Airport", 173 | "Location": "Muş", 174 | "Code": "MSR" 175 | }, 176 | { 177 | "Rank": 30, 178 | "Airport": "Balıkesir Koca Seyit Airport", 179 | "Location": "Balıkesir/Edremit", 180 | "Code": "EDO" 181 | }, 182 | { 183 | "Rank": 31, 184 | "Airport": "Şırnak Airport", 185 | "Location": "Şırnak", 186 | "Code": "NKT" 187 | }, 188 | { 189 | "Rank": 32, 190 | "Airport": "Kahramanmaraş Airport", 191 | "Location": "Kahramanmaraş", 192 | "Code": "KCM" 193 | }, 194 | { 195 | "Rank": 33, 196 | "Airport": "Ağrı Airport", 197 | "Location": "Ağrı", 198 | "Code": "AJI" 199 | }, 200 | { 201 | "Rank": 34, 202 | "Airport": "Adıyaman Airport", 203 | "Location": "Adıyaman", 204 | "Code": "ADF" 205 | }, 206 | { 207 | "Rank": 35, 208 | "Airport": "Bursa Yenişehir Airport", 209 | "Location": "Bursa/Yenişehir", 210 | "Code": "YEI" 211 | }, 212 | { 213 | "Rank": 36, 214 | "Airport": "Iğdır Airport", 215 | "Location": "Iğdır", 216 | "Code": "IGD" 217 | }, 218 | { 219 | "Rank": 37, 220 | "Airport": "Amasya Merzifon Airport", 221 | "Location": "Amasya / Merzifon", 222 | "Code": "MZH" 223 | }, 224 | { 225 | "Rank": 38, 226 | "Airport": "Çanakkale Airport", 227 | "Location": "Çanakkale", 228 | "Code": "CKZ" 229 | }, 230 | { 231 | "Rank": 39, 232 | "Airport": "Isparta Süleyman Demirel Airport", 233 | "Location": "Isparta", 234 | "Code": "ISE" 235 | }, 236 | { 237 | "Rank": 40, 238 | "Airport": "Bingöl Airport", 239 | "Location": "Bingöl", 240 | "Code": "BGG" 241 | }, 242 | { 243 | "Rank": 41, 244 | "Airport": "Hakkari Yüksekova Airport", 245 | "Location": "Hakkari", 246 | "Code": "YKO" 247 | }, 248 | { 249 | "Rank": 42, 250 | "Airport": "Sinop Airport", 251 | "Location": "Sinop", 252 | "Code": "SIC" 253 | }, 254 | { 255 | "Rank": 43, 256 | "Airport": "Nevşehir Kapadokya Airport", 257 | "Location": "Nevşehir", 258 | "Code": "NAV" 259 | }, 260 | { 261 | "Rank": 44, 262 | "Airport": "Tekirdağ Çorlu Airport", 263 | "Location": "Tekirdağ/Çorlu", 264 | "Code": "TEQ" 265 | }, 266 | { 267 | "Rank": 45, 268 | "Airport": "Zafer Airport", 269 | "Location": "Kütahya", 270 | "Code": "KZR" 271 | }, 272 | { 273 | "Rank": 46, 274 | "Airport": "Kastamonu Airport", 275 | "Location": "Kastamonu", 276 | "Code": "KFS" 277 | }, 278 | { 279 | "Rank": 47, 280 | "Airport": "Eskişehir Anadolu Airport", 281 | "Location": "Eskişehir", 282 | "Code": "AOE" 283 | }, 284 | { 285 | "Rank": 48, 286 | "Airport": "Kocaeli Cengiz Topel Airport", 287 | "Location": "Kocaeli", 288 | "Code": "KCO" 289 | }, 290 | { 291 | "Rank": 49, 292 | "Airport": "Zonguldak Airport", 293 | "Location": "Zonguldak", 294 | "Code": "ONQ" 295 | }, 296 | { 297 | "Rank": 50, 298 | "Airport": "Siirt Airport", 299 | "Location": "Siirt", 300 | "Code": "SXZ" 301 | }, 302 | { 303 | "Rank": 51, 304 | "Airport": "Tokat Airport", 305 | "Location": "Tokat", 306 | "Code": "TJK" 307 | }, 308 | { 309 | "Rank": 52, 310 | "Airport": "Uşak Airport", 311 | "Location": "Uşak", 312 | "Code": "USQ" 313 | }, 314 | { 315 | "Rank": 53, 316 | "Airport": "Balıkesir Airport", 317 | "Location": "Balıkesir", 318 | "Code": "BZI" 319 | }, 320 | { 321 | "Rank": 54, 322 | "Airport": "Gökçeada Airport", 323 | "Location": "Çanakkale/Gökçeada", 324 | "Code": "GKD" 325 | } 326 | ] --------------------------------------------------------------------------------