Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
13569 amit.gupta 1
'''
2
Created on Jan 15, 2015
3
 
4
@author: amit
5
'''
13576 amit.gupta 6
from BeautifulSoup import BeautifulSoup
13569 amit.gupta 7
from bson.binary import Binary
8
from dtr import main
13576 amit.gupta 9
from dtr.dao import AffiliateInfo, Order, SubOrder
13569 amit.gupta 10
from dtr.main import getBrowserObject, ScrapeException, getStore, ParseException
11
from pymongo import MongoClient
12
import datetime
13
import json
14
import pymongo
15
import re
16
import urllib
13603 amit.gupta 17
import traceback
18
 
13576 amit.gupta 19
from pprint import pprint
13569 amit.gupta 20
USERNAME='saholic1@gmail.com'
21
PASSWORD='spice@2020'
22
AFFILIATE_URL='http://affiliate.snapdeal.com'
23
POST_URL='https://api-p03.hasoffers.com/v3/Affiliate_Report.json'
24
ORDER_TRACK_URL='https://m.snapdeal.com/orderSummary'
25
CONFIG_URL='http://affiliate.snapdeal.com/publisher/js/config.php'
26
 
27
 
28
class Store(main.Store):
29
 
30
    '''
31
    This is to map order statuses of our system to order statuses of snapdeal.
32
    And our statuses will change accordingly.
33
 
34
    '''
35
    OrderStatusMap = {
36
                      main.Store.ORDER_PLACED : ['In Progress','N/A'],
37
                      main.Store.ORDER_DELIVERED : ['Delivered'],
38
                      main.Store.ORDER_SHIPPED : ['In Transit'],
39
                      main.Store.ORDER_CANCELLED : ['Closed For Vendor Reallocation']
40
 
41
                      }
42
    def __init__(self,store_id):
13576 amit.gupta 43
        client = MongoClient('mongodb://localhost:27017/')
13582 amit.gupta 44
        self.db = client.Dtr
13569 amit.gupta 45
        super(Store, self).__init__(store_id)
46
 
47
    def getName(self):
48
        return "snapdeal"
49
 
50
    def scrapeAffiliate(self, startDate=None, endDate=None):
51
        br = getBrowserObject()
52
        br.open(AFFILIATE_URL)
53
        br.select_form(nr=0)
54
        br.form['data[User][password]'] = PASSWORD 
55
        br.form['data[User][email]'] = USERNAME
56
        br.submit()
57
        response = br.open(CONFIG_URL)
58
 
59
        token =  re.findall('"session_token":"(.*?)"', ungzipResponse(response, br), re.IGNORECASE)[0]
60
 
61
        allOffers = self._getAllOffers(br, token)
62
 
63
        allPyOffers = [self.covertToObj(offer).__dict__ for offer in allOffers]
64
        self._saveToAffiliate(allPyOffers)
65
 
66
 
13576 amit.gupta 67
    def parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl):
13582 amit.gupta 68
        try:
69
            br = getBrowserObject()
70
            url = ORDER_TRACK_URL + re.findall('.*(\?.*?)$', orderSuccessUrl,re.IGNORECASE)[0]
71
            response = br.open(url)
72
            page = ungzipResponse(response, br)
73
            #page=page.decode("utf-8")
74
            soup = BeautifulSoup(page,convertEntities=BeautifulSoup.HTML_ENTITIES)
75
            #orderHead = soup.find(name, attrs, recursive, text)
76
            sections = soup.findAll("section")
77
 
78
            #print sections
79
 
80
            order = sections[1]
81
            orderTrs = order.findAll("tr")
82
 
83
            placedOn = str(orderTrs[0].findAll("td")[1].text)
84
 
85
            #Pop two section elements
86
            sections.pop(0) 
87
            sections.pop(0)
88
            subOrders = sections
89
 
90
 
91
            merchantSubOrders = []
92
 
93
            merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)
94
            merchantOrder.merchantOderId = re.findall(r'\d+', str(soup.find("div", {"class":"deals_heading"})))[1]
95
            for orderTr in orderTrs:
96
                orderTrString = str(orderTr)
97
                if "Total Amount" in orderTrString:
98
                    merchantOrder.totalAmount = re.findall(r'\d+', orderTrString)[0]
99
                elif "Delivery Charges" in orderTrString:
100
                    merchantOrder.deliveryCharges = re.findall(r'\d+', orderTrString)[0]
101
                elif "Discount Applied" in orderTrString:
102
                    merchantOrder.discountApplied = re.findall(r'\d+', orderTrString)[0]
103
                elif "Paid Amount" in orderTrString:
104
                    merchantOrder.paidAmount = re.findall(r'\d+', orderTrString)[0]
105
 
106
            for subOrderElement in subOrders:
107
                productUrl = str(subOrderElement.find("a")['href'])
108
                subTable = subOrderElement.find("table", {"class":"lrPad"})
109
                subTrs = subTable.findAll("tr")
110
                unitPrice=None
111
                offerDiscount = None
112
                deliveryCharges = None
113
                amountPaid = None
114
                for subTr in subTrs:
115
                    subTrString = str(subTr)
116
                    if "Unit Price" in subTrString:
117
                        unitPrice = re.findall(r'\d+', subTrString)[0]
118
                    if "Quantity" in subTrString:
119
                        qty = re.findall(r'\d+', subTrString)[0]
120
                    elif "Offer Discount" in subTrString:
121
                        offerDiscount =   re.findall(r'\d+', subTrString)[0]
122
                    elif "Delivery Charges" in subTrString:
123
                        deliveryCharges =   re.findall(r'\d+', subTrString)[0]
124
                    elif "Subtotal" in subTrString:
13603 amit.gupta 125
                        if int(qty) > 0:
126
                            amountPaid =   str(int(re.findall(r'\d+', subTrString)[0])/int(qty))
127
                        else:
128
                            amountPaid =   "0"
13582 amit.gupta 129
 
130
                divs = subOrderElement.findAll("div", {"class": "blk lrPad subordrs"})
131
                if len(divs)<=0:
132
                    raise ParseException("subOrder", "Could not Parse suborders for Snapdeal")
133
 
134
                for div in divs:
135
                    productTitle = str(subOrderElement.find("a").text)
136
                    productUrl = "http://m.snapdeal.com/" + productUrl 
137
                    subOrder = SubOrder(productTitle, productUrl, placedOn, amountPaid)
138
 
139
                    subOrder.amountPaid = amountPaid
140
                    subOrder.deliveryCharges = deliveryCharges
141
                    subOrder.offerDiscount = offerDiscount
142
                    subOrder.unitPrice = unitPrice
143
                    subOrder.productCode = re.findall(r'\d+$', productUrl)[0]
13569 amit.gupta 144
 
13582 amit.gupta 145
                    trackAnchor = div.find("a")   
146
                    if trackAnchor is not None:
147
                        subOrder.tracingkUrl = str(trackAnchor['href'])
148
 
149
                    divStr = str(div)
150
                    divStr = divStr.replace("\n","").replace("\t", "")
151
 
152
                    for line in divStr.split("<br />"):
153
                        if "Suborder ID" in line:
154
                            subOrder.merchantSubOrderId = re.findall(r'\d+', line)[0]   
155
                        elif "Status" in line:
156
                            subOrder.detailedStatus = re.findall('>(.*?)</span>', line, re.IGNORECASE)[0]
157
                        elif "Est. Shipping Date" in line:
158
                            subOrder.estimatedShippingDate = line.split(":")[1].strip()
159
                        elif "Est. Delivery Date" in line:
160
                            subOrder.estimatedDeliveryDate = line.split(":")[1].strip()
161
                        elif "Courier Name" in line:
162
                            subOrder.courierName = line.split(":")[1].strip()
163
                        elif "Tracking No" in line:
164
                            subOrder.trackingNumber = line.split(":")[1].strip()
165
 
166
                merchantSubOrders.append(subOrder)   
13569 amit.gupta 167
 
13582 amit.gupta 168
            merchantOrder.subOrders = merchantSubOrders
169
            #print merchantOrder
170
 
171
            self._saveToOrder(todict(merchantOrder))
172
            return True
173
        except:
174
            print "Error occurred"
13603 amit.gupta 175
            traceback.print_exc()
13569 amit.gupta 176
 
13582 amit.gupta 177
        return False
13569 amit.gupta 178
        #soup = BeautifulSoup(rawHtml,convertEntities=BeautifulSoup.HTML_ENTITIES)
179
        #soup.find(name, attrs, recursive, text)
180
 
13576 amit.gupta 181
 
182
 
183
    def _getStatusFromDetailedStatus(self, detailedStatus):
184
        for key, value in Store.OrderStatusMap.iteritems():
185
            if detailedStatus in value:
186
                return key
187
        raise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)
13569 amit.gupta 188
 
189
    def scrapeStoreOrders(self,):
13576 amit.gupta 190
        orders = self._getActiveOrders()
191
        br = getBrowserObject()
192
        for order in orders:
193
            url = ORDER_TRACK_URL + re.findall('.*(\?.*?)$', order['orderSuccessUrl'],re.IGNORECASE)[0]
194
            response = br.open(url)
195
            page = ungzipResponse(response, br)
196
            #page=page.decode("utf-8")
197
            soup = BeautifulSoup(page,convertEntities=BeautifulSoup.HTML_ENTITIES)
198
            sections = soup.findAll("section")
199
            sections.pop(0)
200
            sections.pop(0)
201
 
202
            subOrders = sections
203
            bulk = self.db.merchantOrder.initialize_ordered_bulk_op()
204
            for subOrderElement in subOrders:
205
                closed = True
206
                divs = subOrderElement.findAll("div", {"class": "blk lrPad subordrs"})
207
                if len(divs)<=0:
208
                    raise ParseException("subOrder", "Could not Parse suborders for Snapdeal")
209
 
210
                for div in divs:
211
                    trackAnchor = div.find("a")   
212
                    if trackAnchor is not None:
213
                        tracingkUrl = str(trackAnchor['href'])
214
 
215
                    divStr = str(div)
216
                    divStr = divStr.replace("\n","").replace("\t", "")
217
                    updateMap = {}
218
                    for line in divStr.split("<br />"):
219
                        if "Suborder ID" in line:
220
                            merchantSubOrderId = re.findall(r'\d+', line)[0]   
221
                            findMap = {"id": order['id'], "subOrders.merchantSubOrderId": merchantSubOrderId}
222
                        elif "Status" in line:
223
                            detailedStatus = re.findall('>(.*?)</span>', line, re.IGNORECASE)[0]
224
                            detailedStatus = re.findall('>(.*?)</span>', line, re.IGNORECASE)[0]
225
                            updateMap["subOrders.$.detailedStatus"] = detailedStatus
226
                            status = self._getStatusFromDetailedStatus(detailedStatus) 
227
                            if closed:
228
                                closed = status in [Store.ORDER_PLACED, Store.ORDER_CANCELLED]
229
                        elif "Est. Shipping Date" in line:
230
                            estimatedShippingDate = line.split(":")[1].strip()
231
                            updateMap["subOrders.$.estimatedShippingDate"] = estimatedShippingDate
232
                        elif "Est. Delivery Date" in line:
233
                            estimatedDeliveryDate = line.split(":")[1].strip()
234
                            updateMap["subOrders.$.estimatedDeliveryDate"] = estimatedDeliveryDate
235
                        elif "Courier Name" in line:
236
                            courierName = line.split(":")[1].strip()
237
                            updateMap["subOrders.$.courierName"] = courierName
238
                        elif "Tracking No" in line:
239
                            trackingNumber = line.split(":")[1].strip()
240
                            updateMap["subOrders.$.trackingNumber"] = trackingNumber
241
 
242
                    updateMap["subOrders.$.closed"] = closed
243
                    bulk.find(findMap).update({'$set' : updateMap})
244
            result = bulk.execute()
245
            pprint(result)        
246
 
13569 amit.gupta 247
    """
248
    This will insert records with changes only 
249
    """
13576 amit.gupta 250
 
251
    def _getActiveOrders(self):
252
        collection = self.db.merchantOrder
253
        stores = collection.find({"closed": False, "storeId" : self.store_id}, {"orderSuccessUrl":1, "id":1})
254
        return [store for store in stores]
255
 
256
 
257
 
13569 amit.gupta 258
    def _saveToAffiliate(self, offers):
13576 amit.gupta 259
        collection = self.db.snapdealOrderAffiliateInfo
13569 amit.gupta 260
        try:
261
            collection.insert(offers,continue_on_error=True)
262
        except pymongo.errors.DuplicateKeyError as e:
263
            print e.details
264
 
13576 amit.gupta 265
    def _saveToOrder(self, order):
266
        collection = self.db.merchantOrder
267
        try:
268
            order = collection.insert(order)
269
            #merchantOder 
270
        except Exception as e:
13603 amit.gupta 271
            traceback.print_exc()
13569 amit.gupta 272
 
273
    def _getAllOffers(self, br, token):
274
        allOffers = []
275
        nextPage = 1  
276
        while True:
277
            data = getPostData(token, nextPage)
278
            response = br.open(POST_URL, data)
279
            rmap = json.loads(ungzipResponse(response, br))
280
            if rmap is not None:
281
                rmap = rmap['response']
282
                if rmap is not None and len(rmap['errors'])==0:
283
                    allOffers += rmap['data']['data']
284
                    print allOffers
285
            nextPage += 1
286
            if rmap['data']['pageCount']<nextPage:
287
                break
288
 
289
        return allOffers
290
 
291
    def covertToObj(self,offer):
292
        offerData = offer['Stat']
293
        offer1 = AffiliateInfo(offerData['affiliate_info1'], self.store_id, offerData['conversion_status'], offerData['ad_id'], 
294
                              offerData['datetime'], offerData['payout'], offer['Offer']['name'], offerData['ip'], offerData['conversion_sale_amount'])
295
        return offer1
296
def getPostData(token, page = 1, limit= 20, startDate=None, endDate=None):
297
    endDate=datetime.date.today() + datetime.timedelta(days=1)
298
    startDate=endDate - datetime.timedelta(days=31)
299
 
300
    parameters = (
301
        ("page",str(page)),
302
        ("limit",str(limit)),
303
        ("fields[]","Stat.offer_id"),
304
        ("fields[]","Stat.datetime"),
305
        ("fields[]","Offer.name"),
306
        ("fields[]","Stat.conversion_status"),
307
        ("fields[]","Stat.conversion_sale_amount"),
308
        ("fields[]","Stat.payout"),
309
        ("fields[]","Stat.ip"),
310
        ("fields[]","Stat.ad_id"),
311
        ("fields[]","Stat.affiliate_info1"),
312
        ("sort[Stat.datetime]","desc"),
313
        ("filters[Stat.date][conditional]","BETWEEN"),
314
        ("filters[Stat.date][values][]",startDate.strftime('%Y-%m-%d')),
315
        ("filters[Stat.date][values][]",endDate.strftime('%Y-%m-%d')),
316
        ("data_start",startDate.strftime('%Y-%m-%d')),
317
        ("data_end",endDate.strftime('%Y-%m-%d')),
318
        ("Method","getConversions"),
319
        ("NetworkId","jasper"),
320
        ("SessionToken",token),
321
    )
322
    #Encode the parameters
323
    return urllib.urlencode(parameters)
324
 
325
def main():
326
    store = getStore(3)
13576 amit.gupta 327
    store.scrapeStoreOrders()
13569 amit.gupta 328
 
13576 amit.gupta 329
    #store.parseOrderRawHtml(12345, "subtagId", 122323,  "html", 'https://m.snapdeal.com/purchaseMobileComplete?code=1f4166d13ea799b65aa9dea68b3e9e70&order=4509499363')
13569 amit.gupta 330
 
331
def ungzipResponse(r,b):
332
    headers = r.info()
333
    if headers['Content-Encoding']=='gzip':
334
        import gzip
335
        print "********************"
336
        print "Deflating gzip response"
337
        print "********************"
338
        gz = gzip.GzipFile(fileobj=r, mode='rb')
339
        html = gz.read()
340
        gz.close()
341
        return html
342
 
343
if __name__ == '__main__':
344
    main()
13576 amit.gupta 345
 
346
def todict(obj, classkey=None):
347
    if isinstance(obj, dict):
348
        data = {}
349
        for (k, v) in obj.items():
350
            data[k] = todict(v, classkey)
351
        return data
352
    elif hasattr(obj, "_ast"):
353
        return todict(obj._ast())
354
    elif hasattr(obj, "__iter__"):
355
        return [todict(v, classkey) for v in obj]
356
    elif hasattr(obj, "__dict__"):
357
        data = dict([(key, todict(value, classkey)) 
358
            for key, value in obj.__dict__.iteritems() 
359
            if not callable(value) and not key.startswith('_')])
360
        if classkey is not None and hasattr(obj, "__class__"):
361
            data[classkey] = obj.__class__.__name__
362
        return data
363
    else:
364
        return obj