def do_login(self): log('Signing in') email = self.browser.find_element_by_id("loginEmail") passwd = self.browser.find_element_by_id('loginPassword') button = self.browser.find_element_by_id('login') email.send_keys(USERNAME) passwd.send_keys(PASSWORD) # button.click() keys = webdriver.common.keys.Keys() passwd.send_keys(keys.ENTER) counter = 0 log('Waiting max. 30 seconds') while not self.browser.find_elements_by_id("loggedinContainer"): time.sleep(1) counter += 1 log(counter) if counter > 30: log('Login failed.') make_screenshot(self.browser) return False else: log('Logged in successfully.') return True
def save_winning_bid_and_log_history(bid, bidder): timestring = int(time.time()) CURSOR.execute("insert into winningbid values (%s, %s, '%s', %s);" % (AUCTION_ID, timestring, bidder, bid)) DBCONN.commit() winning_bids = _get_winning_bids(AUCTION_ID) lowest_bid = sorted(winning_bids)[0] highest_bid = sorted(winning_bids)[-1] log("Lowest bid: %s | Highest bid: %s" % (lowest_bid, highest_bid))
def get_remaining_secs(self): seconds_left = '' while not seconds_left.isdigit(): countdownbox = self.browser.find_element_by_class_name("countdownbox") counter = countdownbox.text splitted_remaining_time = counter.split() if not splitted_remaining_time or splitted_remaining_time == [u'Gesloten'] or splitted_remaining_time[:10] == u"Een moment": log('Auction has ended.') make_screenshot(self.browser) return 0 if len(splitted_remaining_time) == 3: # includes hour remaining_hours = int(splitted_remaining_time[0].split("uur")[0]) elif len(splitted_remaining_time) == 2: # excludes hour remaining_hours = 0 else: # something is wrong log("DEBUG: Could not parse splitted_remaining_time '%s', auction is probably ending." % splitted_remaining_time) try: remaining_mins = int(splitted_remaining_time[-2].split("min")[0]) remaining_secs = int(splitted_remaining_time[-1].split("sec")[0]) seconds_left = remaining_secs seconds_left += (remaining_mins * 60) seconds_left += ((remaining_hours * 60) * 60) seconds_left = int(seconds_left) return seconds_left except ValueError: log("Caught ValueError") log(counter) raise
def get_latest_bidder(self): bids = wait_for_element(self.browser.find_element_by_xpath, '//div[@id="bidWrapper"]/div[@id="bids"]') splitted_bids = bids.text.split("\n") # List is now in format: # [u'1' <-- number of bid in list, # u'\u20ac 17', <-- EUR <amount> # u'15:11:04 Odettaah', <-- time and bidder # ... and this for every bid # So, pick the third item of the list, split it by space and fetch the last part (and join it by spaces). try: last_bidder = ' '.join(splitted_bids[2].split()[1:]) except: log("FAILING ON: %s" % splitted_bids) raise return last_bidder
def get_remaining_secs(self): seconds_left = '' while not seconds_left.isdigit(): try: # it can take a few moments for the auction time to dynamically load. Before that, it's empty auction_time = "" while auction_time == "": auction_time = self.browser.find_element_by_class_name('auction-time').text.lower() hours = 0 mins = 0 if not 'sec' in auction_time: log('Auction has probably ended. Time string was: "%s"' % auction_time) make_screenshot(self.browser) return 0 if 'uur' in auction_time: hours, _, auction_time = auction_time.partition("uur") if 'min' in auction_time: mins, _, auction_time = auction_time.partition("min") secs, _, auction_time = auction_time.partition("sec") seconds_left = int(secs) seconds_left += (int(mins) * 60) seconds_left += ((int(hours) * 60) * 60) return seconds_left except Exception as e: log("EXCEPTION ! DEBUG: '%s'" % e) log('Returning 11 seconds') traceback.print_exc() ravenclient.captureException() return 11
def do_place_bid(self, price): log("ACTION is %s" % self.action) if self.action != "bid": log("We are doing a dry run. Not bidding! Creating screenshot instead.") make_screenshot(self.browser) return if int(price) > int(self.max_price): log("FAILSAFE (this should not happen): not placing bid of %s, it's higher than %s" % (price, self.max_price)) else: log("Placing bid of '%s' euro" % price ) ub = self.browser.find_element_by_id('userBid') # first clear the input field! log('DEBUG: Clearing input field') ub.clear() log('DEBUG: Sending %s to input field' % price) ub.send_keys(price) # log('DEBUG: Sending ENTER to input field') # keys = webdriver.common.keys.Keys() # ub.send_keys(keys.ENTER) log("DEBUG: Clicking Bid button") bb = self.browser.find_element_by_id('bidButton') bb.click() time.sleep(0.1) log('DEBUG: Clicking YES') click_element_when_available(self.browser.find_element_by_class_name, "yesButton") time.sleep(0.1) log('DEBUG: Clicking OK') click_element_when_available(self.browser.find_element_by_class_name, "yesButtonCentered") log('Placed bid for %s EUR' % price) time.sleep(0.2)
def do_login(self): if self._is_logged_in(): log ("Already signed in") return True log('Signing in') click_element_when_available(self.browser.find_element_by_link_text, "Inloggen") time.sleep(1) email = [f for f in self.browser.find_elements_by_xpath("//input[@ng-model='email']") if f.is_displayed()][0] passwd = [f for f in self.browser.find_elements_by_xpath("//input[@ng-model='password']") if f.is_displayed()][0] button = [f for f in self.browser.find_elements_by_xpath("//input[@value='Login']") if f.is_displayed()][0] email.send_keys(USERNAME) passwd.send_keys(PASSWORD) button.click() counter = 0 log('Waiting max. 10 seconds') while not self._is_logged_in(): time.sleep(1) counter += 1 log(counter) if counter > 10: log('Login failed.') make_screenshot(self.browser) return False else: log('Logged in successfully.') return True
def do_place_bid(self, price): log("ACTION is %s" % self.action) if self.action != "bid": log("We are doing a dry run. Not bidding!") return if int(price) > int(self.max_price): raise RuntimeError("FAILSAFE (this should not happen): not placing bid of %s, it's higher than %s" % (price, self.max_price)) else: log("Placing bid of '%s' euro" % price) ub = self.browser.find_element_by_xpath("//input[@name='bidAmount']") # first clear the input field! log('DEBUG: Clearing input field') ub.clear() log('DEBUG: Sending %s to input field' % price) ub.send_keys(price) click_element_when_available(self.browser.find_element_by_link_text, "Bied mee!") # click_element_when_available(self.browser.find_elements_by_link_text, "Plaats bod", max_tries=5) time.sleep(0.2) try: self.browser.find_element_by_link_text("Plaats bod").click() except (ElementNotVisibleException, NoSuchElementException): # This can happen when auto-confirm is checked. log("Could not confirm, this is probably OK.") log('Placed bid for %s EUR' % price) time.sleep(0.2) # Try to close all dialogs: log('DEBUG: Closing any dialogs') for dialog in self.browser.find_elements_by_class_name('DialogClose'): log("Encountered dialog with text: '%s'" % dialog.text) try: dialog.click() log('Closed a dialog window.') except ElementNotVisibleException: log("Could not close invisible dialog") except: log('Failed to close a dialog.') log('DEBUG: Done closing any dialogs')
def brute_force_bid(site, max_price): """ Try to win the auction with the lowest bid, under max_price. Automatically over-bids other bidders. Always increments the current bid with one. Returns True if we won Returns False if we lost Always assumes that we won, we need to CHECK if we may have lost. """ log("Starting brute force bid with a max price of %s" % max_price) my_last_bid = 0 _current_bid = None while site.get_remaining_secs() > 0: __current_bid_last_time = _current_bid _current_bid = site.get_current_bid() log("DEBUG: Still in brute force bid mode. Current bid: %d | my last bid: %d" % (_current_bid, my_last_bid)) if _current_bid != __current_bid_last_time: _latest_bidder = site.get_latest_bidder() _remaining_secs = site.get_remaining_secs() log( "User '%s' just raised the bid to '%s' on %s seconds left." % (_latest_bidder, _current_bid, _remaining_secs) ) if _current_bid > my_last_bid and _current_bid < max_price: my_last_bid = _current_bid + 1 if my_last_bid <= max_price: log("Placing bid of %s" % my_last_bid) site.place_bid(my_last_bid) else: log("Current bid is higher than or equal to my max price") return False # time.sleep(0.1) # First, create a screenshot make_screenshot(site.browser) # We assume that we have won! But # Let's check if we have lost # Wait a few seconds log("Checking if we've lost") time.sleep(3) winning_bidder = site.get_latest_bidder() last_bid = site.get_current_bid() log("Winning bidder: '%s'" % winning_bidder) log("Winning bid: '%s'" % last_bid) # Double confirm that we have lost, cause it means that we will begin bidding again. if winning_bidder not in (VV_NAME, TV_NAME) and last_bid != my_last_bid: # Too bad, it sure looks like we lost log("Too bad, we lost") return False # Wait... we have won! log("It's possible that we've won.") return True
def begin(url): try: if "vakantieveilingen.nl" in url: log("Using VakantieVeilingen engine") Site = VakantieVeilingen elif "ticketveiling.nl" in url: log("Using TicketVeiling engine") Site = TicketVeiling else: print "Cannot detect URL" sys.exit(1) SITE = None # So we can check if var has been initialized below browser = start_browser(url, browser=USE_BROWSER) SITE = Site(browser=browser, max_price=max_price, action=ACTION) log("Remaining seconds: %s" % SITE.get_remaining_secs()) if SITE.get_remaining_secs() is not None and SITE.get_remaining_secs() > 200: wait_secs = SITE.get_remaining_secs() - 200 datetime_of_next_action = datetime.datetime.now() + datetime.timedelta(seconds=wait_secs) log( "Remaining seconds: More than 120 secs: '%s'. Scheduling a restart in '%s' seconds" % (SITE.get_remaining_secs(), wait_secs) ) log("This would be around %s" % datetime_of_next_action) scheduler.enter(wait_secs, 0, begin, (url,)) browser.quit() elif SITE.get_remaining_secs() is not None and SITE.get_remaining_secs() > 0: # Only login when the current bid is below our max price. if SITE.get_current_bid() < max_price: log( "Current bid (%s) is lower than our max price (%s); logging in" % (SITE.get_current_bid(), max_price) ) login = True else: log( "Not logging in; current bid (%s) is higher than, or equal to, our max price (%s)." % (SITE.get_current_bid(), max_price) ) login = False if login and not SITE.do_login(): scheduler.enter(0, 1, begin, (url,)) else: # Close cookie dialog that might have re-appeared after signing in close_cookie_dialogs(browser) while SITE.get_remaining_secs() > 0: global _current_bid global _latest_bidder global _remaining_secs # Used to check if current bid has changed prev_bid = _current_bid _remaining_secs = SITE.get_remaining_secs() _current_bid = SITE.get_current_bid() _latest_bidder = SITE.get_latest_bidder() if prev_bid != _current_bid and _current_bid != 0 and prev_bid is not None: sys.stdout.write("\n") sys.stdout.flush() log( "User '%s' just raised the bid to '%s' on %s seconds left." % (_latest_bidder, _current_bid, _remaining_secs) ) if _remaining_secs < 6 and _current_bid < max_price: we_won = brute_force_bid(SITE, max_price) if we_won: log("Exiting!") browser.quit() sys.exit(0) time.sleep(0.5) else: # The auction seems to be ended time.sleep(5) _current_bid = SITE.get_current_bid() _latest_bidder = SITE.get_latest_bidder() log("Auction has ended, winning bid is '%s' by '%s'." % (_current_bid, _latest_bidder)) save_winning_bid_and_log_history(bid=_current_bid, bidder=_latest_bidder) browser.quit() scheduler.enter(5, 1, begin, (url,)) elif SITE.get_remaining_secs() in (None, 0): log("Auction seems to be closed. Scheduling restart in 60 secs.") scheduler.enter(60, 1, begin, (url,)) else: log("This should not happen.") except WebDriverException as e: # log("Caught WebDriverException, the browser probably crashed. Forcing browser quit and rescheduling restart in 10 seconds.") # log("The exception was: '%s'" % e) # traceback.print_exc() log("Caught WebDriverException. Trying a refresh.") if SITE is None: log("Nope, SITE is None - capturing exception") if RAVEN_ENABLED: ravenclient.captureException() log("Scheduling a restart") scheduler.enter(15, 1, begin, (url,)) return try: SITE.browser.refresh() except: if RAVEN_ENABLED: ravenclient.captureException() log("That went wrong. Restarting browser") SITE.browser.quit() scheduler.enter(15, 1, begin, (url,)) except Exception as e: log( "Caught unexpected exception: '%s'. Forcing browser quit and rescheduling restart in 60 seconds." % e.message ) log("The exception was: '%s'" % e) traceback.print_exc() if RAVEN_ENABLED: ravenclient.captureException() try: SITE.browser.quit() except: pass scheduler.enter(60, 1, begin, (url,))
CURSOR.execute( "create table if not exists auction (" "id integer primary key autoincrement not null, " "url text);" ) CURSOR.execute( "create table if not exists winningbid (" "auction integer, " "datetime integer, " "name text, " "amount integer, " # "winning integer, " "foreign key(auction) references auctions(id));" ) CURSOR.execute("select id from auction where url = '%s'" % URL) result = CURSOR.fetchone() if not result: CURSOR.execute("insert into auction values (NULL, '%s');" % URL) DBCONN.commit() CURSOR.execute("select id from auction where url = '%s'" % URL) result = CURSOR.fetchone() AUCTION_ID = result[0] winning_bids = _get_winning_bids(AUCTION_ID) scheduler.enter(0, 1, begin, (URL,)) log("Starting scheduler") scheduler.run() log("Scheduler finished")