Subversion Repositories SmartDukaan

Rev

Rev 16076 | Rev 16095 | 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
16019 kshitij.so 5
from dtr.utils.utils import to_java_date, getNlcPoints
15869 kshitij.so 6
import optparse
7
from datetime import datetime
8
import smtplib
9
from email.mime.text import MIMEText
10
from email.mime.multipart import MIMEMultipart
15895 kshitij.so 11
from dtr.utils import ShopCluesScraper
12
import traceback
16019 kshitij.so 13
from dtr.storage.MemCache import MemCache
15869 kshitij.so 14
 
15
con = None
16
parser = optparse.OptionParser()
17
parser.add_option("-m", "--m", dest="mongoHost",
18
                      default="localhost",
19
                      type="string", help="The HOST where the mongo server is running",
20
                      metavar="mongo_host")
21
 
22
(options, args) = parser.parse_args()
23
 
16019 kshitij.so 24
SOURCE_MAP = {'AMAZON':1,'FLIPKART':2,'SNAPDEAL':3,'SAHOLIC':4, 'SHOPCLUES.COM':5}
15869 kshitij.so 25
exceptionList = []
26
bestSellers = []
27
baseUrl = "http://m.shopclues.com/products/getProductList/mobiles:top-selling-mobiles-and-tablets.html/%s/page=%s"
15895 kshitij.so 28
headers = {
29
            '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',
30
            'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',      
31
            'Accept-Language' : 'en-US,en;q=0.8',                     
32
            'Accept-Charset' : 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
16019 kshitij.so 33
            'Connection':'keep-alive'
15895 kshitij.so 34
        }
15869 kshitij.so 35
now = datetime.now()
16019 kshitij.so 36
mc = MemCache(options.mongoHost)
15895 kshitij.so 37
sc = ShopCluesScraper.ShopCluesScraper()
15869 kshitij.so 38
 
39
 
40
class __ProductInfo:
41
 
42
    def __init__(self, identifier, rank, url, available_price, in_stock, codAvailable, source_product_name, thumbnail, coupon):
43
        self.identifier = identifier
44
        self.rank  = rank
45
        self.url = url
46
        self.available_price = available_price
47
        self.in_stock = in_stock
48
        self.codAvailable = codAvailable
49
        self.source_product_name = source_product_name
50
        self.thumbnail = thumbnail
51
        self.coupon = coupon 
52
 
53
def get_mongo_connection(host=options.mongoHost, port=27017):
54
    global con
55
    if con is None:
56
        print "Establishing connection %s host and port %d" %(host,port)
57
        try:
58
            con = pymongo.MongoClient(host, port)
59
        except Exception, e:
60
            print e
61
            return None
62
    return con
63
 
64
def getSoupObject(url):
65
    print "Getting soup object for"
66
    print url
67
    global RETRY_COUNT
68
    RETRY_COUNT = 1 
69
    while RETRY_COUNT < 10:
70
        try:
71
            soup = None
16019 kshitij.so 72
            request = urllib2.Request(url, headers=headers)
15869 kshitij.so 73
            response = urllib2.urlopen(request)   
74
            response_data = response.read()
75
            response.close()
76
            try:
77
                page=response_data.decode("utf-8")
78
                soup = BeautifulSoup(page,convertEntities=BeautifulSoup.HTML_ENTITIES)
79
            except:
16019 kshitij.so 80
                print traceback.print_exc()
15869 kshitij.so 81
                soup = BeautifulSoup(response_data,convertEntities=BeautifulSoup.HTML_ENTITIES)
82
            if soup is None:
83
                raise
84
            return soup
85
        except Exception as e:
16019 kshitij.so 86
            traceback.print_exc()
15869 kshitij.so 87
            print "Retrying"
88
            RETRY_COUNT = RETRY_COUNT + 1
89
 
90
 
91
def scrapeBestSellers():
92
    global bestSellers
93
    bestSellers = []
94
    rank = 0
95
    page = 1
96
    while (True):
97
        url = (baseUrl)%(page,page-1)
98
        soup = getSoupObject(url)
99
        productDivs = soup.findAll('div',{'class':'pd-list-cont'})
100
        if productDivs is None or len(productDivs)==0:
101
            return
102
        for productDiv in productDivs:
103
            rank = rank + 1
104
            info_tag =  productDiv.find('a')
105
            link = info_tag['href']
106
            scin = info_tag['data-id'].strip()
107
            print link
108
            print scin
15895 kshitij.so 109
            productName = productDiv.find('div',{'class':'pdt-name'}).string
110
            try:
111
                productInfo = sc.read(link)
112
            except Exception as e:
113
                traceback.print_exc()
114
                continue
15869 kshitij.so 115
            product = list(get_mongo_connection().Catalog.MasterData.find({'source_id':5,'identifier':scin}))
116
            if len(product) > 0:
16019 kshitij.so 117
                if productInfo['inStock'] ==1:
118
                    get_mongo_connection().Catalog.MasterData.update({'_id':product[0]['_id']},{"$set":{'rank':rank, 'available_price':productInfo['price'], \
15895 kshitij.so 119
                                                                                                            'in_stock':productInfo['inStock'], 'codAvailable':productInfo['isCod'], \
16021 kshitij.so 120
                                                                                                            'coupon':productInfo['coupon'], 'updatedOn':to_java_date(datetime.now()),'priceUpdatedOn':to_java_date(datetime.now())}})
16084 kshitij.so 121
                    get_mongo_connection().Catalog.Deals.update({'_id':product[0]['_id']}, {'$set' : {'rank':rank,'available_price':productInfo['price'] , 'in_stock':productInfo['inStock'],'codAvailable':productInfo['isCod']}})
16019 kshitij.so 122
                else:
123
                    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())}})
124
                    get_mongo_connection().Catalog.Deals.update({'_id':product[0]['_id']}, {'$set' : {'in_stock':0}})
125
 
126
                try:
127
                    recomputeDeal(product[0])
128
                except:
129
                    print "Unable to compute deal for %s"%(product[0]['skuBundleId'])
130
 
15869 kshitij.so 131
            else:
132
                #Lets bundle product by finding similar url pattern
15895 kshitij.so 133
                uri = link.replace('http://m.shopclues.com','').replace(".html","")
134
                try:
135
                    int(uri[uri.rfind('-')+1:])
136
                    uri =  uri[:uri.rfind('-')]
137
                except:
138
                    pass
139
                product = list(get_mongo_connection().Catalog.MasterData.find({'source_id':5,'marketPlaceUrl':{'$regex': uri}}))
140
                toBundle = __ProductInfo(scin, rank, link, productInfo['price'], productInfo['inStock'],productInfo['isCod'], productName, "" ,productInfo['coupon'])
15869 kshitij.so 141
                if len(product) > 0:
15895 kshitij.so 142
                    bundleNewProduct(product[0], toBundle)
16028 kshitij.so 143
                    try:
144
                        recomputeDeal(product[0])
145
                    except:
146
                        print "Unable to compute deal for %s"%(product[0]['skuBundleId'])
15895 kshitij.so 147
                else:
148
                    exceptionList.append(toBundle)
15869 kshitij.so 149
        page = page+1
16019 kshitij.so 150
 
151
def populateNegativeDeals():
152
    negativeDeals = get_mongo_connection().Catalog.NegativeDeals.find().distinct('sku')
153
    mc.set("negative_deals", negativeDeals, 600)
154
 
155
def recomputePoints(item, deal):
156
    try:
157
        nlcPoints = getNlcPoints(item, deal['minNlc'], deal['maxNlc'], deal['available_price'])
158
    except:
159
        traceback.print_exc()
160
        nlcPoints = deal['nlcPoints']
161
    if item['manualDealThresholdPrice'] >= deal['available_price']:
162
        dealPoints = item['dealPoints']
163
    else:
164
        dealPoints = 0
165
    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']}})
166
 
167
 
168
def recomputeDeal(item):
169
    """Lets recompute deal for this bundle"""
170
    print "Recomputing for bundleId %d" %(item.get('skuBundleId'))
171
    skuBundleId = item['skuBundleId']
16026 kshitij.so 172
    item['dealFlag'] = 0
173
    item['dealType'] = 0
174
    item['dealPoints'] = 0
175
    item['manualDealThresholdPrice'] = None
176
    manualDeals = list(get_mongo_connection().Catalog.ManualDeals.find({'startDate':{'$lte':to_java_date(datetime.now())},'endDate':{'$gte':to_java_date(datetime.now())},'source_id':item['source_id'], 'sku':item['_id']}))
177
    if len(manualDeals) > 0:
178
        item['dealFlag'] = 1
179
        item['dealType'] =manualDeals[0]['dealType']
180
        item['dealPoints'] = manualDeals[0]['dealPoints']
181
        item['manualDealThresholdPrice'] = manualDeals[0]['dealThresholdPrice']
16019 kshitij.so 182
    similarItems = list(get_mongo_connection().Catalog.Deals.find({'skuBundleId':skuBundleId}).sort([('available_price',pymongo.ASCENDING)]))
183
    bestPrice = float("inf")
184
    bestOne = None
185
    bestSellerPoints = 0
186
    toUpdate = []
187
    prepaidBestPrice = float("inf")
188
    prepaidBestOne = None
189
    prepaidBestSellerPoints = 0
190
    for similarItem in similarItems:
191
        if similarItem['_id'] == item['_id']:
192
            try:
193
                recomputePoints(item, similarItem)
194
            except:
195
                traceback.print_exc()
196
        if similarItem['codAvailable'] ==1:
197
            if mc.get("negative_deals") is None:
198
                populateNegativeDeals()
199
            if similarItem['in_stock'] == 0 or similarItem['maxprice'] is None or similarItem['maxprice'] < similarItem['available_price'] or similarItem['_id'] in mc.get("negative_deals"):
200
                get_mongo_connection().Catalog.Deals.update({ '_id' : similarItem['_id'] }, {'$set':{'showDeal':0, 'prepaidDeal':0 }})
201
                continue
202
            if similarItem['source_id'] == SOURCE_MAP.get('SHOPCLUES.COM') and similarItem['rank']==0:
203
                get_mongo_connection().Catalog.Deals.update({ '_id' : similarItem['_id'] }, {'$set':{'showDeal':0,'prepaidDeal':0 }})
204
                continue
205
            if similarItem['available_price'] < bestPrice:
206
                bestOne = similarItem
207
                bestPrice = similarItem['available_price']
208
                bestSellerPoints = similarItem['bestSellerPoints']
209
            elif similarItem['available_price'] == bestPrice and bestSellerPoints < similarItem['bestSellerPoints']:
210
                bestOne = similarItem
211
                bestPrice = similarItem['available_price']
212
                bestSellerPoints = similarItem['bestSellerPoints']
213
            else:
214
                pass
215
        else:
216
            if mc.get("negative_deals") is None:
217
                populateNegativeDeals()
218
            if similarItem['in_stock'] == 0 or similarItem['maxprice'] is None or similarItem['maxprice'] < similarItem['available_price'] or similarItem['_id'] in mc.get("negative_deals"):
219
                get_mongo_connection().Catalog.Deals.update({ '_id' : similarItem['_id'] }, {'$set':{'showDeal':0, 'prepaidDeal':0 }})
220
                continue
221
            if similarItem['source_id'] == SOURCE_MAP.get('SHOPCLUES.COM') and similarItem['rank']==0:
222
                get_mongo_connection().Catalog.Deals.update({ '_id' : similarItem['_id'] }, {'$set':{'showDeal':0,'prepaidDeal':0 }})
223
                continue
224
            if similarItem['available_price'] < prepaidBestPrice:
225
                prepaidBestOne = similarItem
226
                prepaidBestPrice = similarItem['available_price']
227
                prepaidBestSellerPoints = similarItem['bestSellerPoints']
228
            elif similarItem['available_price'] == prepaidBestPrice and prepaidBestSellerPoints < similarItem['bestSellerPoints']:
229
                prepaidBestOne = similarItem
230
                prepaidBestPrice = similarItem['available_price']
231
                prepaidBestSellerPoints = similarItem['bestSellerPoints']
232
            else:
233
                pass
16026 kshitij.so 234
    if bestOne is not None or prepaidBestOne is not None:
16019 kshitij.so 235
        for similarItem in similarItems:
236
            toUpdate.append(similarItem['_id'])
16026 kshitij.so 237
        if bestOne is not None:
238
            toUpdate.remove(bestOne['_id'])
239
            get_mongo_connection().Catalog.Deals.update({ '_id' : bestOne['_id'] }, {'$set':{'showDeal':1,'prepaidDeal':0 }})
240
        if prepaidBestOne is not None:
16076 kshitij.so 241
            if bestOne is not None:
242
                if prepaidBestOne['available_price'] < bestOne['available_price']: 
243
                    toUpdate.remove(prepaidBestOne['_id'])
244
                    get_mongo_connection().Catalog.Deals.update({ '_id' : prepaidBestOne['_id'] }, {'$set':{'showDeal':0,'prepaidDeal':1 }})
245
            else:
246
                toUpdate.remove(prepaidBestOne['_id'])
247
                get_mongo_connection().Catalog.Deals.update({ '_id' : prepaidBestOne['_id'] }, {'$set':{'showDeal':0,'prepaidDeal':1 }})
16019 kshitij.so 248
    if len(toUpdate) > 0:
249
        get_mongo_connection().Catalog.Deals.update({ '_id' : { "$in": toUpdate } }, {'$set':{'showDeal':0,'prepaidDeal':0 }},upsert=False, multi=True)
250
 
15869 kshitij.so 251
 
252
def bundleNewProduct(existingProduct, toBundle):
15895 kshitij.so 253
    print "Adding new product"
254
    try:
255
        max_id = list(get_mongo_connection().Catalog.MasterData.find().sort([('_id',pymongo.DESCENDING)]).limit(1))
256
        existingProduct['_id'] = max_id[0]['_id'] + 1
257
        existingProduct['addedOn'] = to_java_date(datetime.now())
258
        existingProduct['available_price'] = toBundle.available_price
259
        existingProduct['updatedOn'] = to_java_date(datetime.now())
260
        existingProduct['codAvailable'] = toBundle.codAvailable
261
        existingProduct['coupon'] = toBundle.coupon
262
        existingProduct['identifier'] = toBundle.identifier
263
        existingProduct['in_stock'] = toBundle.in_stock
264
        existingProduct['marketPlaceUrl'] = toBundle.url
265
        existingProduct['rank'] = toBundle.rank
266
        existingProduct['source_product_name'] = toBundle.source_product_name
267
        existingProduct['url'] = toBundle.url
268
        get_mongo_connection().Catalog.MasterData.insert(existingProduct)
269
        return {1:'Data added successfully.'}
270
    except Exception as e:
271
        print e
272
        return {0:'Unable to add data.'}
15869 kshitij.so 273
 
15895 kshitij.so 274
def exceptionItems():
275
    for item in exceptionList:
276
        print vars(item)
277
 
278
 
15869 kshitij.so 279
def main():
280
    scrapeBestSellers()
15895 kshitij.so 281
    exceptionItems()
15869 kshitij.so 282
 
283
if __name__=='__main__':
284
    main()