def __init__(self, driver, params): BaseStep.__init__(self, driver, params) self.url = params.get('marketplace_url') if self.url: return market_place_id = params.get('market_place_id') if not market_place_id: raise StepFailed('Missing market_place_id') market_place = AmzMarketplace.get(market_place_id) if not market_place: raise StepFailed('Failed to get the marketplace by %s ' % market_place_id) params['marketplace_url'] = market_place.website self.url = market_place.website self.market_place_id = market_place_id
def navigate(self): def _check(): return self.find_element(*self._signin_new_acct) create_new_acct = self.find_element(*self._signin_new_acct) if not create_new_acct: raise StepFailed('Cannot find the ' 'create an account button' '') self.click(self._signin_new_acct) return True
def _get_do_checkout(): if self.find_elements(*self._ship_to_this_address): return OrderForNewAddress(self.driver, self._params, self._account) elif self.find_element(*self._order_address_form): return AddressListFormPage(self.driver, self._params, self._account) elif self.find_element(*self._order_div_address): return AddressDivPage(self.driver, self._params, self._account) else: raise StepFailed('Unexpected error')
def process(self): if not self.validate(): raise self.make_step_failed('Invalid params') try: self.top_up() log.warn( 'Succeed to buy gift card %s to %s.' % (self.gift_card.get('top_up_amount'), self.account['email'])) except Exception as ex: log.exception('') raise StepFailed('Failed to bind_card, due to %s' % ex)
def process(self): if not self.validate(): raise self.make_step_failed('Invalid params') try: self.add_card() self.add_address() self.post_add_address() log.warn( 'Succeed to bind card %s to %s.' % (self.card_info.get('card_number'), self.account['email'])) except Exception as ex: log.exception('') raise StepFailed('Failed to bind_card, due to %s' % ex)
def navigate(self): def _check(): return self.find_element(*self._nav_link_your_account) def _do(): self.driver.get(self.url) def _timeout(): raise TimeoutException('Network issue, failed visit address form') if not _check(): raise StepFailed('Cannot visit address form via account home') self.check_and_do(60, _check, _do, _timeout) return True
def _handle_position_page(context): if not context.get('page_item_count', None): raise StepFailed('Failed to get the asin info by %s ' % self.asin) page = _get_asin_page(context['page_item_count']) if not page: return _failure(context) url_dict = dict(market=context['market'].website, qid=self.get_qid(), keywords=context['keywords'], page=page, group_desc=self.group_desc) self.driver.get(url_tmpl.format(**url_dict)) return _check_result(context)
def shipment_step(self): # Select a shipping address self.click(self._order_div_address_shipment) time.sleep(1 + randint(1, 4)) # Choose your shipping options continue_ = None if self.is_visible(self._order_div_address_continue): continue_ = self._order_div_address_continue elif self.is_visible(self._order_div_address_continue_eu): continue_ = self._order_div_address_continue_eu else: raise StepFailed('Unexpected error, ' + 'failed to find continue button in shipment_step') self.click(continue_) time.sleep(1 + randint(1, 4))
def paymentment_step(self): def _common_paymentment_step(css_selector_map): # fill in with gift card/promotion code for gc_promo_code in self.gc_promo_codes: # expand and show gift card/promotion code self.click(css_selector_map['gc_link']) time.sleep(1 + randint(1, 4)) gc_promo = self.wait_valid_element( css_selector_map['gc_promo'], wait_time=10) gc_promo.clear() gc_promo.send_keys(gc_promo_code) time.sleep(1 + randint(1, 4)) self.click(css_selector_map['apply_gc_promo']) time.sleep(1 + randint(1, 4)) # @TODO - make it common _order_address_form_already_redeem = \ (By.CSS_SELECTOR, '#addPromo_AlreadyRedeemed') if self.is_visible(_order_address_form_already_redeem): continue # if self.is_visible(css_selector_map['wrong_gc_promo']): # raise StepFailed('Wrong gc_promo_code %s for %s, %s, %s' % # (gc_promo_code, self.market_place_id, # self.asin, self.email)) self.click(css_selector_map['payment_continue']) if self.is_visible(self._order_div_address_gc_link): return _common_paymentment_step( self._order_div_address_payment_page['clear_page']) if self.is_visible(self._order_div_address_encrypted_gc_link): return _common_paymentment_step( self._order_div_address_payment_page['encrypted_page']) raise StepFailed('Meet unknown payment page')
def go_to_asin_and_click(self): STATE_WRONG = -1 STATE_DONE = 1 STATE_LOOK_FOR_1ST_PAGE = 2 STATE_LOOK_FOR_POS = 3 STATE_LOOK_FOR_BRAND = 4 STATE_SURL = 5 STATE_FOUND = 99 url_tmpl = 'https://{market}/s/ref=sr_pg_{page}?' + \ 'rh=i%3A{group_desc}%2Ck%3A{keywords}&page={page}' + \ '&keywords={keywords}&qid={qid}''' def _if_asin_in_page(context): # asin = context['asin'] variants = context['variants'] if context['asin'] not in variants: variants.append(context['asin']) all_asins_info = self.driver.\ find_elements_by_class_name('s-result-item') all_asins_info = {ai.get_attribute('data-asin'): ai for ai in all_asins_info if not not ai.get_attribute('data-asin')} all_asins_info = all_asins_info.values() for ai in all_asins_info: ai_asin = ai.get_attribute('data-asin') if ai_asin in variants and\ not ai.find_elements_by_tag_name('h5'): return ai, len(all_asins_info) if context['state'] == STATE_LOOK_FOR_BRAND: log.warning(('market: %s, brand: %s, keywords: %s, ' + 'asin: %s does not exist') % (context['market'], context['brand'], context['keywords'], context['asin'])) return None, len(all_asins_info) def _get_asin_page(item_count): ranking, is_rank = self.get_asin_ranking() if not is_rank: return False if item_count == 0: item_count = 15 page = ranking / item_count if ranking % item_count == 0\ else ranking / item_count + 1 return page def _failure(context): sm = context['state_machine'] state = context['state'] failure = sm[state]['failure'] return failure(context) if callable(failure) else failure def _check_result(context): asin_info, page_item_count = _if_asin_in_page(context) context['asin_info'] = asin_info context['page_item_count'] = page_item_count if not asin_info: return _failure(context) sm = context['state_machine'] state = context['state'] return sm[state]['success'] def _handle_1st_page(context): return _check_result(context) def _handle_position_page(context): if not context.get('page_item_count', None): raise StepFailed('Failed to get the asin info by %s ' % self.asin) page = _get_asin_page(context['page_item_count']) if not page: return _failure(context) url_dict = dict(market=context['market'].website, qid=self.get_qid(), keywords=context['keywords'], page=page, group_desc=self.group_desc) self.driver.get(url_tmpl.format(**url_dict)) return _check_result(context) def _handle_brand_page(context): if not context['brand']: return _failure(context) if not context.get('BRAND_NEXT_PAGE'): self.click_brand_url() return _check_result(context) def _get_brand_failure(context): _next_page = (By.ID, 'pagnNextLink') next_page = self.find_element(*_next_page) if not next_page: return STATE_SURL _next_page_span = (By.ID, 'pagnNextString') self.click(_next_page_span) context['BRAND_NEXT_PAGE'] = True return STATE_LOOK_FOR_BRAND def _handle_surl(context): self.driver.get(self.make_url(self.get_qid(), context)) return STATE_DONE def _transit(context, state): context['state'] = state market = AmzMarketplace.get(self.market_place_id) if not market: raise StepFailed('Failed to get the marketplace by %s ' % self.market_place_id) state_machine = {STATE_LOOK_FOR_1ST_PAGE: {'handle': _handle_1st_page, 'success': STATE_FOUND, 'failure': STATE_LOOK_FOR_BRAND}, STATE_LOOK_FOR_POS: {'handle': _handle_position_page, 'success': STATE_FOUND, 'failure': STATE_LOOK_FOR_BRAND}, STATE_LOOK_FOR_BRAND: {'handle': _handle_brand_page, 'success': STATE_FOUND, 'failure': _get_brand_failure}, STATE_SURL: {'handle': _handle_surl, 'success': STATE_DONE, 'failure': STATE_WRONG}} context = {'asin': self.asin, 'variants': self.variants, 'brand': self.brand, 'group_desc': self.group_desc, 'market': market, 'keywords': quote_plus(str(self.keywords)), 'state_machine': state_machine, 'state': STATE_LOOK_FOR_1ST_PAGE} while True: sm = context['state_machine'][context['state']] state = sm['handle'](context) if state == STATE_WRONG: return False if state == STATE_DONE: return True if state == STATE_FOUND: break _transit(context, state) asin_detail = context['asin_info'].\ find_element_by_class_name('s-access-detail-page') if asin_detail.get_attribute('target'): self.driver.get(asin_detail.get_attribute('href')) return True asin_detail.click() return True
def shipment_step(self): raise StepFailed('Need to implemented')
def _common_process(driver, account, params, prepare, process): _log = _gen_log(driver, account, params) if prepare and not prepare(params): return False try: # home home = Home(driver, params) home.navigate() _log('home', account.get('email')) if not home.is_done(): raise StepFailed('Failed to visit home') # signinlog.exception(' signin = SigninWithCaptcha(driver, params, account) signin.navigate() signin.process() _log('signin', '') # if not signin.signin.is_done(): # if signin.is_auth_err(): if signin.is_new_account(): # Maybe we don't meet all status, so is_done can't work. reg = RegisterWithCaptcha(driver, params, account) reg.navigate() reg.process() _log('register', '') if not reg.is_done(): raise FailedToRegNewUser('Failed to register new user') if process: process(driver, account, params) # logout logout = Logout(driver, params) logout.navigate() _log('logout', account.get('email')) return True except (FailedToRegNewUser, MeetSpammedAccount) as e: _log('failed_to_reg_new_user', '%s' % e) # XXX: Need to raise the exception and move the below codes to outside # acct = AmzAccountInfo.get_by_market_email( # params.get('market_place_id'), account.get('email')) # if not acct: # _log('failed_to_reg_new_user_02', # 'account(%s, %s) not found' % (params.get('market_place_id'), # account.get('email'))) # return # acct.soft_delete() # AmzFailAccountLog(account_id=acct.id, # market_place_id=acct.market_place_id, # email=acct.email).add() except (StepFailed, CaptchaException) as e: # from ipdb import set_trace # set_trace() # @TODO need to log error message to DB (AmzSaleFarmPrjTask) _log('exception', '%s' % e) except Exception as e: # from ipdb import set_trace # set_trace() _log('exception', '%s' % e) log.exception('Failed to execute %s:%s, %s, %s' % (driver.name, process.__name__, account, params)) raise e
def make_step_failed(self, msg): return StepFailed('%s, %s' % (self.__class__.__name__, msg))
def _timeout(): raise StepFailed('Timeout, failed to add to cart, %s, %s, %s, %s' % (self.market_place_id, self.asin, self.email, self.keywords))
def _do_add_to_cart_via_more_options(): if self.is_visible(self._asin_more_sellers): self.click(self._asin_more_sellers) else: self.click(self._asin_all_buying_options) time.sleep(3 + randint(1, 6)) if self.is_visible(self._asin_more_sellers_checkbox_new): checkbox = self.wait_valid_element( self._asin_more_sellers_checkbox_new) if not checkbox.is_selected(): self.click(self._asin_more_sellers_checkbox_new) time.sleep(3 + randint(1, 6)) def _get_seller_name(div): seller_name_part = div.find_element( *self._asin_more_sellers_seller_div_seller_col) if not seller_name_part: return '' seller_name = seller_name_part.text if seller_name: return seller_name img = seller_name_part.find_element_by_tag_name('img') if not img: return '' seller_name = img.get_attribute('alt') return seller_name if seller_name else '' def _process_page(): all_divs = self.find_elements( *self._asin_more_sellers_seller_div) for div in all_divs: seller_name = _get_seller_name(div) if self.seller != seller_name: continue # Try to look for the FBA badge try: if div.find_element( *self._asin_more_sellers_seller_div_fba): continue except Exception: pass return self._do_add_to_cart() def _has_more_page(): try: next_btn = self.wait_valid_element( self._asin_more_sellers_next_btn) css_clz = next_btn.get_attribute('class') return css_clz.find('a-disabled') == -1 except Exception: return False def _next_page(): self.click(self._asin_more_sellers_next_btn) time.sleep(3 + randint(1, 6)) while(True): if _process_page(): return True if not _has_more_page(): break log.info('go to next page') _next_page() raise StepFailed('Seller not found, failed to add to cart, ' + '%s, %s, %s, %s' % (self.market_place_id, self.asin, self.email, self.keywords))