Subversion Repositories SmartDukaan

Rev

Rev 20364 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
15869 kshitij.so 1
import urllib2
2
from BeautifulSoup import BeautifulSoup
3
import pymongo
4
import re
20364 kshitij.so 5
from dtr.utils.utils import to_java_date, getNlcPoints, DEAL_PRIORITY, getCashBack
15869 kshitij.so 6
import optparse
7
from datetime import datetime
16183 kshitij.so 8
import time
15869 kshitij.so 9
import smtplib
10
from email.mime.text import MIMEText
11
from email.mime.multipart import MIMEMultipart
15895 kshitij.so 12
from dtr.utils import ShopCluesScraper
13
import traceback
16019 kshitij.so 14
from dtr.storage.MemCache import MemCache
16184 kshitij.so 15
import chardet
21135 kshitij.so 16
from shop2020.utils.EmailAttachmentSender import get_attachment_part
17
from shop2020.utils import EmailAttachmentSender
15869 kshitij.so 18
 
19
con = None
20
parser = optparse.OptionParser()
21
parser.add_option("-m", "--m", dest="mongoHost",
22
                      default="localhost",
23
                      type="string", help="The HOST where the mongo server is running",
24
                      metavar="mongo_host")
16102 kshitij.so 25
parser.add_option("-r", "--reset", dest="reset",
26
                   default="False", type="string",
27
                   help="Reset Ranks?")
15869 kshitij.so 28
 
29
(options, args) = parser.parse_args()
30
 
16869 kshitij.so 31
SOURCE_MAP = {'AMAZON':1,'FLIPKART':2,'SNAPDEAL':3,'SAHOLIC':4, 'SHOPCLUES.COM':5,'PAYTM.COM':6}
15869 kshitij.so 32
bestSellers = []
33
baseUrl = "http://m.shopclues.com/products/getProductList/mobiles:top-selling-mobiles-and-tablets.html/%s/page=%s"
15895 kshitij.so 34
headers = {
35
            'User-Agent':'Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Safari/537.36',
36
            'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',      
37
            'Accept-Language' : 'en-US,en;q=0.8',                     
38
            'Accept-Charset' : 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
16019 kshitij.so 39
            'Connection':'keep-alive'
15895 kshitij.so 40
        }
15869 kshitij.so 41
now = datetime.now()
16019 kshitij.so 42
mc = MemCache(options.mongoHost)
16099 kshitij.so 43
sc = ShopCluesScraper.ShopCluesScraper(findThumbnail=True)
15869 kshitij.so 44
 
16095 kshitij.so 45
bundledProducts = []
46
exceptionList = []
15869 kshitij.so 47
 
16095 kshitij.so 48
 
15869 kshitij.so 49
class __ProductInfo:
50
 
51
    def __init__(self, identifier, rank, url, available_price, in_stock, codAvailable, source_product_name, thumbnail, coupon):
52
        self.identifier = identifier
53
        self.rank  = rank
54
        self.url = url
55
        self.available_price = available_price
56
        self.in_stock = in_stock
57
        self.codAvailable = codAvailable
58
        self.source_product_name = source_product_name
59
        self.thumbnail = thumbnail
16095 kshitij.so 60
        self.coupon = coupon
15869 kshitij.so 61
 
16095 kshitij.so 62
class __NewBundled:
63
    def __init__(self, newProduct, oldProduct):
64
        self.newProduct = newProduct
65
        self.oldProduct = oldProduct
66
 
15869 kshitij.so 67
def get_mongo_connection(host=options.mongoHost, port=27017):
68
    global con
69
    if con is None:
70
        print "Establishing connection %s host and port %d" %(host,port)
71
        try:
72
            con = pymongo.MongoClient(host, port)
73
        except Exception, e:
74
            print e
75
            return None
76
    return con
77
 
19189 kshitij.so 78
def getNetPriceForItem(itemId, source_id, category_id ,price):
79
    cash_back_type = 0
80
    cash_back = 0
81
    try:
82
        cashBack = getCashBack(itemId, source_id, category_id, mc, options.mongoHost)
83
        if not cashBack or cashBack.get('cash_back_status')!=1:
84
            cash_back_type = 0
85
            cash_back = 0 
86
 
87
        else:
88
            if cashBack['cash_back_type'] in (1,2):
89
 
90
                if cashBack.get('maxCashBack') is not None:
91
 
92
                    if cashBack.get('cash_back_type') ==1 and (float(cashBack.get('cash_back'))*price)/100 > cashBack.get('maxCashBack'):
93
                        cashBack['cash_back_type'] = 2
94
                        cashBack['cash_back'] = cashBack['maxCashBack']
95
                    elif cashBack.get('cash_back_type') ==2 and cashBack.get('cash_back') > cashBack.get('maxCashBack'):
96
                        cashBack['cash_back'] = cashBack['maxCashBack']
97
                    else:
98
                        pass
99
 
100
 
101
 
102
                cash_back_type = cashBack['cash_back_type']
103
                cash_back = float(cashBack['cash_back'])
104
    except Exception as cashBackEx:
105
        pass
106
 
107
    if cash_back_type ==1:
108
        return (price - float(cash_back)*price/100)
109
    elif cash_back_type ==2:
110
        return (price - cash_back)
111
    else:
112
        return price
113
 
114
 
15869 kshitij.so 115
def getSoupObject(url):
116
    print "Getting soup object for"
117
    print url
118
    global RETRY_COUNT
119
    RETRY_COUNT = 1 
120
    while RETRY_COUNT < 10:
121
        try:
122
            soup = None
16019 kshitij.so 123
            request = urllib2.Request(url, headers=headers)
15869 kshitij.so 124
            response = urllib2.urlopen(request)   
125
            response_data = response.read()
126
            response.close()
127
            try:
128
                page=response_data.decode("utf-8")
129
                soup = BeautifulSoup(page,convertEntities=BeautifulSoup.HTML_ENTITIES)
130
            except:
16019 kshitij.so 131
                print traceback.print_exc()
15869 kshitij.so 132
                soup = BeautifulSoup(response_data,convertEntities=BeautifulSoup.HTML_ENTITIES)
133
            if soup is None:
134
                raise
135
            return soup
136
        except Exception as e:
16019 kshitij.so 137
            traceback.print_exc()
15869 kshitij.so 138
            print "Retrying"
139
            RETRY_COUNT = RETRY_COUNT + 1
140
 
141
 
142
def scrapeBestSellers():
143
    global bestSellers
16095 kshitij.so 144
    global exceptionList
15869 kshitij.so 145
    bestSellers = []
146
    rank = 0
147
    page = 1
148
    while (True):
149
        url = (baseUrl)%(page,page-1)
150
        soup = getSoupObject(url)
151
        productDivs = soup.findAll('div',{'class':'pd-list-cont'})
152
        if productDivs is None or len(productDivs)==0:
153
            return
154
        for productDiv in productDivs:
155
            rank = rank + 1
156
            info_tag =  productDiv.find('a')
157
            link = info_tag['href']
158
            scin = info_tag['data-id'].strip()
159
            print link
160
            print scin
15895 kshitij.so 161
            productName = productDiv.find('div',{'class':'pdt-name'}).string
162
            try:
163
                productInfo = sc.read(link)
164
            except Exception as e:
165
                traceback.print_exc()
166
                continue
15869 kshitij.so 167
            product = list(get_mongo_connection().Catalog.MasterData.find({'source_id':5,'identifier':scin}))
168
            if len(product) > 0:
16505 kshitij.so 169
                if product[0].get('ignorePricing') ==1:
170
                    continue
16019 kshitij.so 171
                if productInfo['inStock'] ==1:
19189 kshitij.so 172
                    netPriceAfterCashBack = getNetPriceForItem(product[0]['_id'], SOURCE_MAP.get('SHOPCLUES.COM'), product[0]['category_id'], productInfo['price'])
16019 kshitij.so 173
                    get_mongo_connection().Catalog.MasterData.update({'_id':product[0]['_id']},{"$set":{'rank':rank, 'available_price':productInfo['price'], \
15895 kshitij.so 174
                                                                                                            'in_stock':productInfo['inStock'], 'codAvailable':productInfo['isCod'], \
16021 kshitij.so 175
                                                                                                            'coupon':productInfo['coupon'], 'updatedOn':to_java_date(datetime.now()),'priceUpdatedOn':to_java_date(datetime.now())}})
19189 kshitij.so 176
                    get_mongo_connection().Catalog.Deals.update({'_id':product[0]['_id']}, {'$set' : {'rank':rank,'available_price':productInfo['price'] , 'in_stock':productInfo['inStock'],'codAvailable':productInfo['isCod'],'netPriceAfterCashBack':netPriceAfterCashBack}})
16019 kshitij.so 177
                else:
19189 kshitij.so 178
                    netPriceAfterCashBack = getNetPriceForItem(product[0]['_id'], SOURCE_MAP.get('SHOPCLUES.COM'), product[0]['category_id'], product[0]['available_price'])
16019 kshitij.so 179
                    get_mongo_connection().Catalog.MasterData.update({'_id':product[0]['_id']}, {'$set' : {'updatedOn':to_java_date(datetime.now()),'in_stock':0,'priceUpdatedOn':to_java_date(datetime.now())}})
19189 kshitij.so 180
                    get_mongo_connection().Catalog.Deals.update({'_id':product[0]['_id']}, {'$set' : {'in_stock':0,'netPriceAfterCashBack':netPriceAfterCashBack}})
16019 kshitij.so 181
 
182
                try:
183
                    recomputeDeal(product[0])
184
                except:
185
                    print "Unable to compute deal for %s"%(product[0]['skuBundleId'])
186
 
15869 kshitij.so 187
            else:
188
                #Lets bundle product by finding similar url pattern
15895 kshitij.so 189
                uri = link.replace('http://m.shopclues.com','').replace(".html","")
190
                try:
191
                    int(uri[uri.rfind('-')+1:])
192
                    uri =  uri[:uri.rfind('-')]
193
                except:
194
                    pass
195
                product = list(get_mongo_connection().Catalog.MasterData.find({'source_id':5,'marketPlaceUrl':{'$regex': uri}}))
16099 kshitij.so 196
                toBundle = __ProductInfo(scin, rank, link, productInfo['price'], productInfo['inStock'],productInfo['isCod'], productName, productInfo['thumbnail'] ,productInfo['coupon'])
15869 kshitij.so 197
                if len(product) > 0:
15895 kshitij.so 198
                    bundleNewProduct(product[0], toBundle)
16028 kshitij.so 199
                    try:
200
                        recomputeDeal(product[0])
201
                    except:
202
                        print "Unable to compute deal for %s"%(product[0]['skuBundleId'])
15895 kshitij.so 203
                else:
204
                    exceptionList.append(toBundle)
15869 kshitij.so 205
        page = page+1
16019 kshitij.so 206
 
207
def populateNegativeDeals():
208
    negativeDeals = get_mongo_connection().Catalog.NegativeDeals.find().distinct('sku')
209
    mc.set("negative_deals", negativeDeals, 600)
210
 
16505 kshitij.so 211
#def recomputePoints(item, deal):
212
#    try:
213
#        if item.get('available_price') == deal['available_price']:
214
#            print "No need to compute points for %d , as price is still same" %(item['_id'])
215
#            raise
216
#        nlcPoints = getNlcPoints(item, deal['minNlc'], deal['maxNlc'], deal['available_price'])
217
#    except:
218
#        print traceback.print_exc()
219
#        nlcPoints = deal['nlcPoints']
220
#        
221
#    
222
#    bundleDealPoints = list(get_mongo_connection().Catalog.DealPoints.find({'skuBundleId':item['skuBundleId'],'startDate':{'$lte':to_java_date(datetime.now())},'endDate':{'$gte':to_java_date(datetime.now())}}))
223
#    if len(bundleDealPoints) > 0:
224
#        item['manualDealThresholdPrice'] = bundleDealPoints[0]['dealThresholdPrice']
225
#        dealPoints = bundleDealPoints[0]['dealPoints']
226
#    else:
227
#        dealPoints = 0
228
#        item['manualDealThresholdPrice'] = None    
229
#    
230
#    get_mongo_connection().Catalog.Deals.update({'_id':deal['_id']},{"$set":{'totalPoints':deal['totalPoints'] - deal['nlcPoints'] + nlcPoints - deal['dealPoints'] +dealPoints , 'nlcPoints': nlcPoints, 'dealPoints': dealPoints, 'manualDealThresholdPrice': item['manualDealThresholdPrice']}})
16019 kshitij.so 231
 
232
 
233
def recomputeDeal(item):
234
    """Lets recompute deal for this bundle"""
235
    print "Recomputing for bundleId %d" %(item.get('skuBundleId'))
236
    skuBundleId = item['skuBundleId']
19189 kshitij.so 237
 
238
    similarItems = list(get_mongo_connection().Catalog.Deals.find({'skuBundleId':skuBundleId}).sort([('netPriceAfterCashBack',pymongo.ASCENDING)]))
16019 kshitij.so 239
    bestPrice = float("inf")
240
    bestOne = None
241
    toUpdate = []
242
    prepaidBestPrice = float("inf")
243
    prepaidBestOne = None
244
    for similarItem in similarItems:
245
        if similarItem['codAvailable'] ==1:
246
            if mc.get("negative_deals") is None:
247
                populateNegativeDeals()
16181 kshitij.so 248
            if similarItem['in_stock'] == 0  or similarItem['_id'] in mc.get("negative_deals"):
16019 kshitij.so 249
                get_mongo_connection().Catalog.Deals.update({ '_id' : similarItem['_id'] }, {'$set':{'showDeal':0, 'prepaidDeal':0 }})
250
                continue
251
            if similarItem['source_id'] == SOURCE_MAP.get('SHOPCLUES.COM') and similarItem['rank']==0:
252
                get_mongo_connection().Catalog.Deals.update({ '_id' : similarItem['_id'] }, {'$set':{'showDeal':0,'prepaidDeal':0 }})
253
                continue
19189 kshitij.so 254
            if similarItem.get('netPriceAfterCashBack') < bestPrice:
16019 kshitij.so 255
                bestOne = similarItem
19189 kshitij.so 256
                bestPrice = similarItem.get('netPriceAfterCashBack')
20347 kshitij.so 257
            elif similarItem.get('netPriceAfterCashBack') == bestPrice:
258
 
259
                try:
260
                    if (DEAL_PRIORITY.index(int(similarItem['source_id'])) > DEAL_PRIORITY.index(int(bestOne['source_id']))):
261
                        continue
262
                except:
263
                    traceback.print_exc()
264
 
16019 kshitij.so 265
                bestOne = similarItem
19189 kshitij.so 266
                bestPrice = similarItem.get('netPriceAfterCashBack')
16019 kshitij.so 267
            else:
268
                pass
269
        else:
270
            if mc.get("negative_deals") is None:
271
                populateNegativeDeals()
16181 kshitij.so 272
            if similarItem['in_stock'] == 0  or similarItem['_id'] in mc.get("negative_deals"):
16019 kshitij.so 273
                get_mongo_connection().Catalog.Deals.update({ '_id' : similarItem['_id'] }, {'$set':{'showDeal':0, 'prepaidDeal':0 }})
274
                continue
275
            if similarItem['source_id'] == SOURCE_MAP.get('SHOPCLUES.COM') and similarItem['rank']==0:
276
                get_mongo_connection().Catalog.Deals.update({ '_id' : similarItem['_id'] }, {'$set':{'showDeal':0,'prepaidDeal':0 }})
277
                continue
19189 kshitij.so 278
            if similarItem.get('netPriceAfterCashBack') < prepaidBestPrice:
16019 kshitij.so 279
                prepaidBestOne = similarItem
19189 kshitij.so 280
                prepaidBestPrice = similarItem.get('netPriceAfterCashBack')
20347 kshitij.so 281
            elif similarItem.get('netPriceAfterCashBack') == prepaidBestPrice:
282
 
283
                try:
20364 kshitij.so 284
                    if (DEAL_PRIORITY.index(int(similarItem['source_id'])) > DEAL_PRIORITY.index(int(prepaidBestOne['source_id']))):
20347 kshitij.so 285
                        continue
286
                except:
287
                    traceback.print_exc()
288
 
16019 kshitij.so 289
                prepaidBestOne = similarItem
19189 kshitij.so 290
                prepaidBestPrice = similarItem.get('netPriceAfterCashBack')
16019 kshitij.so 291
            else:
292
                pass
16026 kshitij.so 293
    if bestOne is not None or prepaidBestOne is not None:
16019 kshitij.so 294
        for similarItem in similarItems:
295
            toUpdate.append(similarItem['_id'])
16026 kshitij.so 296
        if bestOne is not None:
297
            toUpdate.remove(bestOne['_id'])
298
            get_mongo_connection().Catalog.Deals.update({ '_id' : bestOne['_id'] }, {'$set':{'showDeal':1,'prepaidDeal':0 }})
299
        if prepaidBestOne is not None:
16076 kshitij.so 300
            if bestOne is not None:
19189 kshitij.so 301
                if prepaidBestOne.get('netPriceAfterCashBack') < bestOne.get('netPriceAfterCashBack'): 
16076 kshitij.so 302
                    toUpdate.remove(prepaidBestOne['_id'])
303
                    get_mongo_connection().Catalog.Deals.update({ '_id' : prepaidBestOne['_id'] }, {'$set':{'showDeal':0,'prepaidDeal':1 }})
304
            else:
305
                toUpdate.remove(prepaidBestOne['_id'])
306
                get_mongo_connection().Catalog.Deals.update({ '_id' : prepaidBestOne['_id'] }, {'$set':{'showDeal':0,'prepaidDeal':1 }})
16019 kshitij.so 307
    if len(toUpdate) > 0:
308
        get_mongo_connection().Catalog.Deals.update({ '_id' : { "$in": toUpdate } }, {'$set':{'showDeal':0,'prepaidDeal':0 }},upsert=False, multi=True)
309
 
19189 kshitij.so 310
 
311
 
15869 kshitij.so 312
 
313
def bundleNewProduct(existingProduct, toBundle):
16095 kshitij.so 314
    global bundledProducts
315
    global exceptionList
15895 kshitij.so 316
    print "Adding new product"
317
    try:
318
        max_id = list(get_mongo_connection().Catalog.MasterData.find().sort([('_id',pymongo.DESCENDING)]).limit(1))
319
        existingProduct['_id'] = max_id[0]['_id'] + 1
320
        existingProduct['addedOn'] = to_java_date(datetime.now())
321
        existingProduct['available_price'] = toBundle.available_price
322
        existingProduct['updatedOn'] = to_java_date(datetime.now())
323
        existingProduct['codAvailable'] = toBundle.codAvailable
16095 kshitij.so 324
        existingProduct['coupon'] = str(toBundle.coupon)
325
        existingProduct['identifier'] = str(toBundle.identifier)
15895 kshitij.so 326
        existingProduct['in_stock'] = toBundle.in_stock
327
        existingProduct['marketPlaceUrl'] = toBundle.url
328
        existingProduct['rank'] = toBundle.rank
329
        existingProduct['source_product_name'] = toBundle.source_product_name
330
        existingProduct['url'] = toBundle.url
17747 kshitij.so 331
        existingProduct['showVideo'] = 0
332
        existingProduct['shippingCost'] = 0
333
        existingProduct['quantity'] = 1
334
        existingProduct['videoLink'] = ""
19189 kshitij.so 335
        existingProduct['showNetPrice'] = 0
15895 kshitij.so 336
        get_mongo_connection().Catalog.MasterData.insert(existingProduct)
16095 kshitij.so 337
        newBundled = __NewBundled(toBundle, existingProduct)
338
        bundledProducts.append(newBundled)
15895 kshitij.so 339
        return {1:'Data added successfully.'}
340
    except Exception as e:
341
        print e
16095 kshitij.so 342
        exceptionList.append(toBundle)
15895 kshitij.so 343
        return {0:'Unable to add data.'}
15869 kshitij.so 344
 
16095 kshitij.so 345
def sendMail():
346
    message="""<html>
347
            <body>
348
            <h3>ShopClues Best Sellers Auto Bundled</h3>
349
            <table border="1" style="width:100%;">
350
            <thead>
351
            <tr>
352
            <th>Item Id</th>
353
            <th>Identifier</th>
354
            <th>Rank</th>
355
            <th>Product Name</th>
356
            <th>Bundle Id</th>
357
            <th>Bundled with Brand</th>
358
            <th>Bundled with Product Name</th>
359
            <th>Available_price</th>
360
            <th>In Stock</th>
361
            <th>Coupon</th>
362
            <th>COD Available</th>
363
            </tr></thead>
364
            <tbody>"""
365
    for bundledProduct in bundledProducts:
366
        newProduct = bundledProduct.newProduct
367
        oldProduct = bundledProduct.oldProduct
368
        message+="""<tr>
369
        <td style="text-align:center">"""+str(oldProduct.get('_id'))+"""</td>
370
        <td style="text-align:center">"""+oldProduct.get('identifier')+"""</td>
371
        <td style="text-align:center">"""+str(oldProduct.get('rank'))+"""</td>
372
        <td style="text-align:center">"""+(oldProduct.get('source_product_name'))+"""</td>
373
        <td style="text-align:center">"""+str(oldProduct.get('skuBundleId'))+"""</td>
374
        <td style="text-align:center">"""+(oldProduct.get('brand'))+"""</td>
375
        <td style="text-align:center">"""+(oldProduct.get('product_name'))+"""</td>
376
        <td style="text-align:center">"""+str(oldProduct.get('available_price'))+"""</td>
377
        <td style="text-align:center">"""+str(oldProduct.get('in_stock'))+"""</td>
378
        <td style="text-align:center">"""+str(oldProduct.get('coupon'))+"""</td>
379
        <td style="text-align:center">"""+str(oldProduct.get('codAvailable'))+"""</td>
380
        </tr>"""
381
    message+="""</tbody></table><h3>Items not bundled</h3><table border="1" style="width:100%;">
382
    <tr>
383
    <th>Identifier</th>
384
    <th>Rank</th>
385
    <th>Product Name</th>
386
    <th>Url</th>
387
    <th>Available Price</th>
388
    <th>In Stock</th>
389
    <th>COD Available</th>
390
    <th>Coupon</th>
16099 kshitij.so 391
    <th>Thumbnail</th>
16095 kshitij.so 392
    </tr></thead>
393
    <tbody>"""
394
    for exceptionItem in exceptionList:
395
        message+="""<tr>
396
        <td style="text-align:center">"""+str(exceptionItem.identifier)+"""</td>
397
        <td style="text-align:center">"""+str(exceptionItem.rank)+"""</td>
398
        <td style="text-align:center">"""+(exceptionItem.source_product_name)+"""</td>
399
        <td style="text-align:center">"""+(exceptionItem.url)+"""</td>
400
        <td style="text-align:center">"""+str(exceptionItem.available_price)+"""</td>
401
        <td style="text-align:center">"""+str(exceptionItem.in_stock)+"""</td>
402
        <td style="text-align:center">"""+str(exceptionItem.codAvailable)+"""</td>
403
        <td style="text-align:center">"""+str(exceptionItem.coupon)+"""</td>
16102 kshitij.so 404
        <td style="text-align:left">"""+(exceptionItem.thumbnail)+"""</td>
16095 kshitij.so 405
        </tr>"""
406
    message+="""</tbody></table></body></html>"""
407
    print message
16184 kshitij.so 408
    encoding = chardet.detect(message)
409
    try:
410
        message = message.decode(encoding.get('encoding'))
411
    except:
412
        pass
16182 kshitij.so 413
    #recipients = ['kshitij.sood@saholic.com']
21135 kshitij.so 414
    recipients = ['kshitij.sood@saholic.com','ritesh.chauhan@saholic.com','aishwarya.singh@saholic.com']
415
    EmailAttachmentSender.mail_send_grid("dtr@profitmandi.com","apikey", "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", recipients, "Shoplclues Best Sellers",message ,[],[],[])              
16095 kshitij.so 416
 
21135 kshitij.so 417
 
16095 kshitij.so 418
 
16183 kshitij.so 419
def resetRanks():
16103 kshitij.so 420
    get_mongo_connection().Catalog.MasterData.update({'rank':{'$gt':0},'source_id':5},{'$set' : {'rank':0,'updatedOn':to_java_date(now)}}, multi=True)
15895 kshitij.so 421
 
15869 kshitij.so 422
def main():
16103 kshitij.so 423
    if options.reset == 'True':
424
        resetRanks()
15869 kshitij.so 425
    scrapeBestSellers()
16102 kshitij.so 426
    if len(bundledProducts)>0 or len(exceptionList) > 0:
427
        sendMail()
16190 kshitij.so 428
    else:
429
        "print nothing to send"
15869 kshitij.so 430
 
431
if __name__=='__main__':
432
    main()