Rev 14321 | Rev 14465 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
# coding=utf-8'''Created on Jan 15, 2015@author: amit'''from base64 import encodefrom bs4 import BeautifulSoupfrom datetime import datetimefrom dtr.dao import Order, SubOrderfrom dtr.main import getStore, Store as MStore, ParseExceptionfrom dtr.sources.flipkart import todictfrom paramiko import sftpfrom paramiko.client import SSHClientfrom paramiko.sftp_client import SFTPClientimport os.pathimport paramikoimport reimport timeimport tracebackORDER_REDIRECT_URL = 'https://www.amazon.in/gp/css/summary/edit.html?orderID=%s'ORDER_SUCCESS_URL = 'https://www.amazon.in/gp/buy/spc/handlers/static-submit-decoupled.html'THANKYOU_URL = 'https://www.amazon.in/gp/buy/thankyou/handlers/display.html'class Store(MStore):orderStatusRegexMap = { MStore.ORDER_PLACED : ['ordered from', 'not yet dispatched','dispatching now', 'preparing for dispatch'],MStore.ORDER_SHIPPED : ['dispatched on','dispatched', 'on the way', 'out for delivery', 'Out for delivery'],MStore.ORDER_CANCELLED : ['return complete', 'refunded', 'cancelled'],MStore.ORDER_DELIVERED : ['delivered']}def __init__(self,store_id):super(Store, self).__init__(store_id)def getName(self):return "flipkart"def parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl, insert=False):resp = {}if ORDER_SUCCESS_URL in orderSuccessUrl or THANKYOU_URL in orderSuccessUrl:try:soup = BeautifulSoup(rawHtml)orderUrl = soup.find('div', {"id":"thank-you-box-wrapper"}).div.findAll('div', recursive=False)[1].a['href']merchantOrderId = re.findall(r'.*&oid=(.*)&?.*?', orderUrl)[0]order = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl, False)order.orderSuccessUrl = ORDER_REDIRECT_URL % (merchantOrderId)order.merchantOrderId = merchantOrderIdorder.requireDetail = Trueorder.closed = Noneif self._saveToOrder(todict(order)):resp['result'] = 'ORDER_CREATED'resp["url"] = ORDER_REDIRECT_URL % (merchantOrderId)resp["htmlRequired"] = Trueresp['orderId'] = orderIdelse:resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'return respexcept:resp["result"] = 'ORDER_NOT_CREATED'return respelse:try:merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)merchantOrder.orderTrackingUrl = orderSuccessUrlsoup = BeautifulSoup(rawHtml,from_encoding="utf-8")table = soup.body.findAll("table", recursive=False)[1]#print tabletables = table.tr.td.findAll("table", recursive=False)for tr in tables[2].findAll("tr"):boldElement = tr.td.bif "Order Placed" in str(boldElement):merchantOrder.placedOn = boldElement.next_sibling.strip()if "order number" in str(boldElement):merchantOrder.merchantOrderId = boldElement.next_sibling.strip()if "Order Total" in str(boldElement):merchantOrder.paidAmount = int(float(boldElement.find('span').contents[-1].replace(',','')))anchors = table.tr.td.findAll("a", recursive=False)paymentAnchor = anchors.pop(-1)count = 0subOrders = []merchantOrder.subOrders = subOrdersfor anchor in anchors:count += 1tab = anchor.next_siblingstatus = MStore.ORDER_PLACEDsubStr = "Delivery #" + str(count) + ":"if subStr in tab.find("b").text:detailedStatus = tab.find("b").text.replace(subStr, '').strip()tab = tab.next_sibling.next_siblingtrs = tab.find("table").find('tbody').findAll("tr", recursive = False)estimatedDelivery = trs[0].td.find("b").next_sibling.strip()orderItemTrs = trs[1].findAll("td", recursive=False)[1].table.tbody.findAll("tr", recursive = False)i = -1for orderItemTr in orderItemTrs:i += 1if i%2 == 0:continuequantity = int(re.findall(r'\d+', orderItemTr.td.contents[0])[0])productUrl = orderItemTr.td.contents[1].a["href"]productTitle = orderItemTr.td.contents[1].a.textunitPrice = int(float(orderItemTr.findAll('td')[1].span.text.replace('Rs. ','').replace(',','')))subOrder = SubOrder(productTitle, productUrl, merchantOrder.placedOn, unitPrice*quantity, status, quantity)subOrder.merchantSubOrderId = orderItemTr.find("input")["name"]subOrder.estimatedDeliveryDate = estimatedDeliverysubOrder.productCode = productUrl.split('/')[5]subOrder.detailedStatus = detailedStatus(cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, unitPrice*quantity)cashbackStatus = Store.CB_PENDINGif cashbackAmount <= 0:cashbackStatus = Store.CB_NAsubOrder.cashBackStatus = cashbackStatussubOrder.cashBackAmount = cashbackAmountif percentage > 0:subOrder.cashBackPercentage = percentagesubOrders.append(subOrder)priceList = paymentAnchor.next_sibling.next_sibling.next_sibling.table.table.tbody.tbody.tbody.findAll('tr', recursive=False)totalAmount = 0grandAmount = 0for price in priceList:labelTd = price.tdif 'Subtotal:' in labelTd.text:totalAmount += int(float(labelTd.next_sibling.next_sibling.find('span').contents[-1].replace(',','')))elif 'Grand Total:' in labelTd.text:grandAmount += int(float(labelTd.next_sibling.next_sibling.find('span').contents[-1].replace(',','')))if grandAmount < totalAmount:diff = totalAmount - grandAmountfor subOrder in merchantOrder.subOrders:subOrder.amountPaid -= int(diff*(1-subOrder.amountPaid/totalAmount))self._updateToOrder(todict(merchantOrder))resp['result'] = 'ORDER_CREATED'return respexcept:print "Error occurred"traceback.print_exc()resp['result'] = 'ORDER_NOT_CREATED'return resp#This should be exposed from api for specific sourcesdef scrapeStoreOrders(self):passdef getTrackingUrls(self, userId):missingOrderUrls = []missingOrders = self._getMissingOrders({'userId':userId})for missingOrder in missingOrders:missingOrderUrls.append(ORDER_REDIRECT_URL%(missingOrder['merchantOrderId']))orders = self._getActiveOrders({'userId':userId})count = len(orders)print "count", countif count > 0:return missingOrderUrls + ['https://www.amazon.in/gp/css/order-history', 'https://www.amazon.in/gp/css/order-history/?orderFilter=cancelled', 'https://www.amazon.in/gp/css/order-history?orderFilter=cancelled&startIndex=10']else:return missingOrderUrlsdef trackOrdersForUser(self, userId, url, rawHtml):directory = "/tmp/User" + str(userId)if not os.path.exists(directory):os.makedirs(directory)filename = directory + "/" + str(datetime.now())print "filename---", filenamef = open(filename,'w')f.write(rawHtml) # python will convert \n to os.linesepf.close() # you can omit in most cases as the destructor will call iftry:searchMap = {'userId':userId}collectionMap = {'merchantOrderId':1}activeOrders = self._getActiveOrders(searchMap, collectionMap)datetimeNow = datetime.now()timestamp = int(time.mktime(datetimeNow.timetuple()))print "url----------------", urlif url == 'https://www.amazon.in/gp/css/order-history' or 'https://www.amazon.in/gp/css/order-history/?orderFilter=cancelled' in url:soup = BeautifulSoup(rawHtml)allOrders = soup.find(id="ordersContainer").findAll('div', {'class':'a-box-group a-spacing-base order'})bulk = self.db.merchantOrder.initialize_ordered_bulk_op()for activeOrder in activeOrders:for orderEle in allOrders:orderdiv = orderEle.find('div', {'class':'a-box a-color-offset-background order-info'}).find('div', {'class':'a-fixed-right-grid-col actions a-col-right'})merchantOrderId = orderdiv.find('span', {'class':'a-color-secondary value'}).text.strip()if merchantOrderId==activeOrder['merchantOrderId']:closed = Trueshipments = orderEle.findAll('div',{'class':re.compile('.*?a-box.*?')}, recursive=False)shipments.pop(0)for shipment in shipments:shipdiv = shipment.find('div', {'class':'a-box-inner'})sdivs = shipment.div.div.findAll('div', recursive=False)orderStatus = sdivs[0].span.text.strip()status = self._getStatusFromDetailedStatus(orderStatus)if status == MStore.ORDER_DELIVERED:deliveredOn = sdivs[0].findAll('span')[-1].text.strip()deliveredOn = deliveredOn.split(":")[1].strip()deliveryestimatespan = sdivs[0].find('span', {'class':'a-color-success'})deliveryEstimate = Noneif deliveryestimatespan is not None:deliveryEstimate = deliveryestimatespan.find('span', {'class':'a-text-bold'}).text.strip()productDivs = shipdiv.find('div', {'class':re.compile('.*?a-spacing-top-medium.*?')}).find('div', {'class':'a-row'}).findAll('div', recursive=False)trackingUrl = Nonefor buttonDiv in shipdiv.findAll('span', {'class':'a-button-inner'}):if buttonDiv.find('a').text.strip()=='Track package':trackingUrl = buttonDiv.find('a')['href'].strip()if not trackingUrl.startswith("http"):trackingUrl = "https://www.amazon.in/" + trackingUrlbreakfor prodDiv in productDivs:prodDiv.find('div', {'class':'a-fixed-left-grid-inner'})productTitle = prodDiv.find('div', {'class':'a-fixed-left-grid-inner'}).find("div", {'class':'a-row'}).find('a').text.strip()imgUrl = prodDiv.find("img")["src"]for subOrder in activeOrder['subOrders']:if subOrder['productTitle'] == productTitle:findMap = {"orderId": activeOrder['orderId'], "subOrders.merchantSubOrderId": subOrder.get("merchantSubOrderId")}updateMap = {}closedStatus = FalseupdateMap['subOrders.$.imgUrl'] = imgUrlupdateMap['subOrders.$.lastTracked'] = timestampupdateMap['subOrders.$.detailedStatus'] = orderStatuscashbackStatus = subOrder.get("cashBackStatus")updateMap['subOrders.$.status'] = statusif status==MStore.ORDER_DELIVERED:updateMap['subOrders.$.deliveredOn'] = deliveredOnclosedStatus = TrueupdateMap['subOrders.$.closed'] = Trueif cashbackStatus == Store.CB_PENDING:updateMap['subOrders.$.cashbackStatus'] = Store.CB_APPROVEDif status==MStore.ORDER_CANCELLED:closedStatus = TrueupdateMap['subOrders.$.closed'] = Trueif cashbackStatus == Store.CB_PENDING:updateMap['subOrders.$.cashBackStatus'] = Store.CB_CANCELLEDif status==MStore.ORDER_SHIPPED:updateMap['subOrders.$.estimatedDeliveryDate'] = deliveryEstimateif trackingUrl is not None:updateMap['subOrders.$.trackingUrl'] = trackingUrlif not closedStatus:closed = Falsebulk.find(findMap).update({'$set' : updateMap})breakbulk.find({'orderId': activeOrder['orderId']}).update({'$set':{'closed': closed}})bulk.execute()return 'PARSED_SUCCESS'else:merchantOrderId = re.findall(r'https://www.amazon.in/gp/css/summary/edit.html\?orderID=(.*)?', url, re.IGNORECASE)[0]merchantOrder = self.db.merchantOrder.find_one({"merchantOrderId":merchantOrderId})self.parseOrderRawHtml(merchantOrder['orderId'], merchantOrder['subTagId'], merchantOrder['userId'], rawHtml, url, False)['result']return 'PARSED_SUCCESS'passreturn 'PARSED_SUCCESS_NO_ORDERS'except:traceback.print_exc()return 'PARSED_FAILED'def _getStatusFromDetailedStatus(self, detailedStatus):if "ordered from" in detailedStatus.lower():return MStore.ORDER_PLACEDfor key, value in self.orderStatusRegexMap.iteritems():if detailedStatus.lower() in value:return keyprint "Detailed Status need to be mapped"print "Found new order status", detailedStatusraise ParseException("_getStatusFromDetailedStatus", "Found new order status" + detailedStatus)def main():store = getStore(1)#store.parseOrderRawHtml(1, 'saad', '2123221', readSSh('/tmp/User8/2015-03-02 12:51:59.545557'), 'https://www.amazon.in/gp/css/summary/edit.html?orderID=12212')store.trackOrdersForUser(8,'https://www.amazon.in/gp/css/order-history', readSSh('/tmp/User2/2015-03-03 00:29:40.165513'))def readSSh(fileName):try:str1 = open(fileName).read()return str1except:ssh_client = SSHClient()str1 = ""ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())ssh_client.connect('104.200.25.40', 22, 'root', 'ecip$dtrMay2014')sftp_client = ssh_client.open_sftp()try:if not os.path.exists(os.path.dirname(fileName)):os.makedirs(os.path.dirname(fileName))sftp_client.get(fileName, fileName)try:str1 = open(fileName).read()return str1finally:passexcept:"could not read"return str1if __name__ == '__main__':main()