-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathmain.py
More file actions
221 lines (182 loc) · 6.97 KB
/
Copy pathmain.py
File metadata and controls
221 lines (182 loc) · 6.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
from abc import ABC, abstractmethod
from helium import start_chrome, kill_browser
from bs4 import BeautifulSoup
from datetime import datetime
import smtplib
import validators
from time import sleep
from threading import Thread
import re
import requests
import os
import json
class PriceTracker(ABC):
"""
Base class for Price Trackers.
"""
with open("credentials.json") as f:
fc = f.read()
parser = json.loads(fc)
email = parser["email"]
password = parser["password"]
removals = re.compile(r"₹|,|[$]")
def __init__(self, product_name: str, product_url: str, desired_price: int) -> None:
"""
Constructor.
"""
if not validators.url(product_url):
raise Exception("Invalid URL!")
self.product_url = product_url
self.set_price = desired_price
self.product_name = product_name
self.price = None
@abstractmethod
def get_price(self):
"""
Fetches the latest price of the product.
"""
pass
@staticmethod
def send_mail(your_email:str, your_password:str, subject: str, body: str):
"""
Sends mail for the given price.
"""
server = smtplib.SMTP('smtp.mail.yahoo.com', 587)
server.ehlo()
server.starttls()
server.login(your_email, your_password)
server.sendmail(your_email,
your_email, f"Subject: {subject}\n\n{body}")
server.quit()
print("Mail sent")
@abstractmethod
def write_to_file(self):
"""
Write content to a text file.
"""
pass
def track_price(self):
"""
Tracks price for a given product against the set price.
"""
while True:
self.get_price()
if self.price == None:
print("Unable to fetch the latest price!")
os._exit(1)
if self.set_price >= self.price:
print("Price low for", self.product_name)
self.write_to_file()
self.send_mail(self.email, self.password, f"Price down for {self.product_name}",f"Dear sir,\nThe price for `{self.product_name}` is now {self.price} which is less than or equal to what you desired, {self.set_price}! Visit {self.product_url} for more info.")
os._exit(0)
else:
self.write_to_file()
sleep(60)
class AmazonPriceTracker(PriceTracker):
"""
Helps poor people by notifying them when the price for their favorite product on Amazon is less than what they desired.
"""
def get_price(self):
"""
Fetches price for given product on Amazon.
"""
driver = start_chrome(self.product_url)
html = driver.page_source.replace(" ", "")
kill_browser()
soup = BeautifulSoup(html, "html5lib")
price = soup.find("span", {"id": "priceblock_ourprice"})
if price == None:
price = soup.find("span", {"id": "priceblock_dealprice"}).string
price = (re.sub(self.removals, "", price)).replace("\\xa", "")
self.price = int(float(price))
def write_to_file(self):
"""
Writes datetime and price to a file.
"""
now = datetime.now().strftime("%d-%m-%y %H:%M")
content = f"{now} --> Amazon --> {self.price}\n"
print(content)
with open(f"{self.product_name}.prices", "a") as f:
f.write(content)
def run(self):
self.track_price()
class FlipkartPriceTracker(PriceTracker):
"""
Helps poor people by notifying them when the price of their favorite product on Flipkart is less than what they desired.
"""
def get_price(self):
"""
Fetches price for given product on Flipkart.
"""
r = requests.get(self.product_url)
soup = BeautifulSoup(r.content, "html5lib")
price = soup.find("div", {"class": "_30jeq3 _16Jk6d"}).string
price = re.sub(self.removals, "", price)
self.price = int(price)
def write_to_file(self):
"""
Writes datetime and price to a file.
"""
now = datetime.now().strftime("%d-%m-%y %H:%M")
content = f"{now} --> Flipkart --> {self.price}\n"
print(content)
with open(f"{self.product_name}.prices", "a") as f:
f.write(content)
def run(self):
self.track_price()
class MultipleStorePriceTracker():
"""
Tracks prices for two stores at a time (Amazon and Flipkart) and notifies when either of them is less than the desired price.
"""
def __init__(self, product_name:str, amazon_url:str, flipkart_url:str, desired_price:int) -> None:
self.product = product_name
self.fkturl = flipkart_url
self.azurl = amazon_url
self.set_price = desired_price
def track_multiple(self):
fktt = FlipkartPriceTracker(self.product, self.fkturl, self.set_price)
azt = AmazonPriceTracker(self.product, self.azurl, self.set_price)
t1 = Thread(target=fktt.run)
t2 = Thread(target=azt.run)
t1.start()
t2.start()
def check_internet():
try:
requests.get("https://google.com")
except Exception:
print("Make sure you're connected to the internet!")
quit()
if __name__ == "__main__":
check_internet()
print("Welcome to the Ecommerce Price Tracker! A tool which you can use to track prices for a given product on Amazon and Flipkart.\n")
track_opt = input("Where to track prices?\n 1. Amazon \n 2. Flipkart \n 3. Both\n")
if track_opt == "1":
try:
product_name = input("Enter product name: ")
product_url = input("Enter the product url: ")
desired_price = int(input("Enter the desired price (you'll be notified when this price is lower than the product price): "))
azt = AmazonPriceTracker(product_name, product_url, desired_price)
azt.run()
except Exception as e:
print(e)
elif track_opt == "2":
try:
product_name = input("Enter product name: ")
product_url = input("Enter the product url: ")
desired_price = int(input("Enter the desired price (you'll be notified when this price is lower than the product price): "))
fkt = FlipkartPriceTracker(product_name, product_url, desired_price)
fkt.run()
except Exception as e:
print(e)
elif track_opt == "3":
try:
product_name = input("Enter product name: ")
azurl = input("Enter the product url on Amazon: ")
fkturl = input("Enter the product url on Flipkart: ")
desired_price = int(input("Enter the desired price (you'll be notified when this price is lower than the product price): "))
mspt = MultipleStorePriceTracker(product_name, azurl, fkturl, desired_price)
mspt.track_multiple()
except Exception as e:
print(e)
else:
print("Invalid input!")