def get_parcel_tracking(self, _id): # 13 is the magic length of colissimo tracking ids if len(_id) != 13: raise ParcelNotFound( u"Colissimo ID's must have 13 print character") data = self.browser.get_tracking_info(_id) p = Parcel(_id) label = data['message'] if data['error']: raise ParcelNotFound(label + u" (id = %s@%s)" % (_id, self.name)) p.info = label # TODO, need to know the delivery message if u"remis au gardien ou" in label or u"Votre colis est livré" in label: p.status = p.STATUS_ARRIVED elif u"pas encore pris en charge par La Poste" in label: p.status = p.STATUS_PLANNED else: p.status = p.STATUS_IN_TRANSIT ev = Event(0) ev.activity = label ev.date = date(*reversed([int(x) for x in data['date'].split("/")])) p.history = [ev] return p
def get_info(self, _id): if u'errors' in self.doc: raise ParcelNotFound("No such ID: %s" % _id) elif u'results' in self.doc: result = self.doc[u'results'][0] p = Parcel(_id) p.history = [self.build_event(e) for e in result[u'checkpoints']] p.status = self.STATUSES.get(result[u'delivery'][u'code'], Parcel.STATUS_UNKNOWN) p.info = p.history[0].activity return p else: raise ParcelNotFound("Unexpected reply from server")
def get_info(self, _id): result_id = self.doc.xpath('//th[@class="mm_sendungsnummer"]') if not result_id: raise ParcelNotFound("No such ID: %s" % _id) result_id = result_id[0].text if result_id != _id: raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id)) p = Parcel(_id) events = self.doc.xpath( '//div[@class="accordion-inner"]/table/tbody/tr') p.history = [self.build_event(i, tr) for i, tr in enumerate(events)] p.status, p.info = self.guess_status(p.history[-1]) return p
def get_tracking_info(self, _id): self.tracking_url.stay_or_go(_id=_id) events = list(self.page.iter_infos()) if len(events) == 0: error = self.page.get_error() raise ParcelNotFound(u"Parcel not found: {}".format(error)) return events
def get_info(self, _id): result_id = self.doc.get("TrackingStatusJSON", {}).get("shipmentInfo", {}).get("parcelNumber", None) if not result_id: raise ParcelNotFound("No such ID: %s" % _id) if not _id.startswith(result_id): raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id)) p = Parcel(_id) events = self.doc.get("TrackingStatusJSON", {}).get("statusInfos", []) p.history = [self.build_event(i, data) for i, data in enumerate(events)] p.status = self.guess_status( self.doc.get("TrackingStatusJSON", {}). get("shipmentInfo", {}). get("deliveryStatus")) p.info = p.history[-1].activity return p
def get_info(self, _id): result_id = self.doc.xpath( '//table[@id="shipment-details-table"]//tr[position()=1]/td[@id="td-bold"]' ) if not result_id: raise ParcelNotFound("No such ID: %s" % _id) result_id = result_id[0].text if result_id != _id: raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id)) p = Parcel(_id) events = self.doc.xpath('//div[@id="shipment-event-table-cell"]') p.history = [self.build_event(i, div) for i, div in enumerate(events)] most_recent = p.history[0] p.status, p.info = self.guess_status(p.history) p.info = most_recent.activity return p
def get_info(self, _id): result_id = self.doc.xpath('//th[@class="mm_sendungsnummer"]') if not result_id: raise ParcelNotFound("No such ID: %s" % _id) result_id = result_id[0].text if result_id != _id: raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id)) p = Parcel(_id) events = self.doc.xpath('//div[@class="accordion-inner"]/table/tbody/tr') p.history = [self.build_event(i, tr) for i, tr in enumerate(events)] status_msgs = self.doc.xpath('//tr[@class="mm_mailing_process "]//img[contains(@src, "ACTIVE")]/@alt') if len(status_msgs) > 0: p.status = self.STATUSES.get(status_msgs[-1], Parcel.STATUS_UNKNOWN) else: p.status = Parcel.STATUS_UNKNOWN p.info = p.history[-1].activity return p
def get_info(self, _id): shipments = self.doc["shipments"] if not shipments: raise ParcelNotFound("No such ID: %s" % _id) shipment = shipments[0] result_id = shipment["trackingCode"] if result_id != _id: raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id)) p = Parcel(_id) if shipment["estimatedDeliveryTime"]: p.arrival = parse_date(shipment["estimatedDeliveryTime"], ignoretz=True) events = shipment["events"] p.history = [ self.build_event(i, data) for i, data in enumerate(events) ] most_recent = p.history[0] p.status, p.info = self.guess_status(p.history) p.info = most_recent.activity return p
def iter_events(self, merchant, code, name): data = dict(codeEnseigne=merchant, nomClient=name, typeRecherche='EXP', valeur=code) # Ref: https://www.relaiscolis.com/js/lib/suivi.js req = self.open('/suivi-de-colis/index/tracking/', data=data) resp = None try: resp = req.json() if resp and 'error' in resp: raise ParcelNotFound(resp['error']['msg']) except (ValueError, KeyError): self.raise_for_status(req) raise else: self.raise_for_status(req) def ensure_list(data): if isinstance(data, list): return data return [data] parcel_data = ensure_list(resp['Colis']['Colis'])[-1] events_data = ensure_list(parcel_data['ListEvenements'].get( 'Evenement', [])) final_location = None try: relay = resp['Relais']['Relais'] name = relay['Nom'].strip() city = relay['Commune'].strip() final_location = ' '.join((name, city)) except KeyError: pass for event_data in events_data: event = Event() event.date = parse_date(event_data['Date'].strip()) event.activity = event_data['Libelle'].strip() if final_location and ("Votre colis est disponible" in event.activity): event.location = final_location yield event
def get_parcel_tracking(self, id): """ Get information abouut a parcel. :param id: ID of the parcel :type id: :class:`str` :rtype: :class:`Parcel` :raises: :class:`ParcelNotFound` """ self._browser = None if len(id) == 10 or len(id) == 20: self.BROWSER = DHLExpressBrowser elif len(id) == 12 or len(id) == 16: self.BROWSER = DeutschePostDHLBrowser else: ParcelNotFound("Wrong length for ID: %s" % id) return self.browser.get_tracking_info(id)
def get_parcel_tracking(self, _id): # 13 is the magic length of colissimo tracking ids if len(_id) != 13: raise ParcelNotFound(u"Colissimo ID's must have 13 print character") events = self.browser.get_tracking_info(_id) p = Parcel(_id) p.history = events first = events[0] p.info = first.activity if u"remis au gardien ou" in p.info or u"Votre colis est livré" in p.info: p.status = p.STATUS_ARRIVED elif u"pas encore pris en charge par La Poste" in p.info: p.status = p.STATUS_PLANNED else: p.status = p.STATUS_IN_TRANSIT return p
def get_info(self, _id): raise ParcelNotFound("No such ID: %s" % _id)
def get_parcel_tracking(self, _id): """ Get information about a parcel. :param _id: _id of the parcel :type _id: :class:`str` :rtype: :class:`Parcel` :raises: :class:`ParcelNotFound` """ # Tracking number format: # - 2 chars: optional merchant identifier (eg, AM for Amazon, 85 for cdiscount, ...) # - 10 digits: shipment tracking number # - 2 digits: optional suffix, seems to always be "01" when present but is never sent to the API # # Many merchants seem to give only the 10 digits tracking number so the user needs to # manually select the merchant from a list in that case. merchant = None code = None _id = _id.strip().upper() if len(_id) == 10: code = _id elif len(_id) in (12, 14): merchant = _id[:2] code = _id[2:12] else: raise ParcelNotFound( "Tracking number must be 10, 12 or 14 characters long.") merchant = merchant or self.config['merchant'].get() if not merchant: # No merchant info in the tracking number # we have to ask the user to select it merchants = self.browser.get_merchants() raise BrowserQuestion( Value( 'merchant', label='Merchant prefix (prepend to tracking number): ', tiny=False, choices=merchants, )) self.config['merchant'].set(None) name = self.config['last_name'].get()[:4].ljust(4).upper() events = list(self.browser.iter_events(merchant, code, name)) parcel = Parcel(merchant + code) parcel.arrival = NotAvailable # This is what the legacy tracking website used to show # when there are no events yet parcel.info = "Votre commande est en cours d'acheminement dans notre réseau." parcel.history = events parcel.status = Parcel.STATUS_IN_TRANSIT if not events: parcel.status = Parcel.STATUS_PLANNED return parcel parcel.info = events[0].activity arrived_event = next( (event for event in events if "Votre colis est disponible" in event.activity), None) if arrived_event: parcel.status = Parcel.STATUS_ARRIVED parcel.arrival = arrived_event.date return parcel
def parse(self, el): error = CleanText('//div[has-class("ch-colis-information")]')(el) if "pas d'information" in error: raise ParcelNotFound(error)
def get_tracking_info(self, _id): try: return self.search_page.go(id=_id).get_info(_id) except HTTPNotFound: raise ParcelNotFound("No such ID: %s" % _id)