From 22e30f300d1619769dde4ce70c8b288e6aad9af4 Mon Sep 17 00:00:00 2001 From: Michael Gecht Date: Tue, 21 May 2019 08:50:57 +0200 Subject: [PATCH 1/3] Wrap selector logic in try..except statement This catches all errors that are thrown, when any `find_element_by_*` method fails for some reason. If this happens, we just fall through and wait for a page refresh and then try again. --- deletefb/deletefb.py | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/deletefb/deletefb.py b/deletefb/deletefb.py index 231adf6..30e8f52 100755 --- a/deletefb/deletefb.py +++ b/deletefb/deletefb.py @@ -103,27 +103,30 @@ def delete_posts(user_email_address, driver.get(user_profile_url) for _ in range(MAX_POSTS): - post_button_sel = "_4xev" - timeline_element = driver.find_element_by_class_name(post_button_sel) - actions = ActionChains(driver) - actions.move_to_element(timeline_element).click().perform() + try: + post_button_sel = "_4xev" + timeline_element = driver.find_element_by_class_name(post_button_sel) + actions = ActionChains(driver) + actions.move_to_element(timeline_element).click().perform() - menu = driver.find_element_by_css_selector("#globalContainer > div.uiContextualLayerPositioner.uiLayer > div") - actions.move_to_element(menu).perform() + menu = driver.find_element_by_css_selector("#globalContainer > div.uiContextualLayerPositioner.uiLayer > div") + actions.move_to_element(menu).perform() - try: - delete_button = menu.find_element_by_xpath("//a[@data-feed-option-name=\"FeedDeleteOption\"]") + try: + delete_button = menu.find_element_by_xpath("//a[@data-feed-option-name=\"FeedDeleteOption\"]") - # FIXME Using a bare except here to avoid having to handle all possible exceptions - except: - delete_button = menu.find_element_by_xpath("//a[@data-feed-option-name=\"HIDE_FROM_TIMELINE\"]") + # FIXME Using a bare except here to avoid having to handle all possible exceptions + except: + delete_button = menu.find_element_by_xpath("//a[@data-feed-option-name=\"HIDE_FROM_TIMELINE\"]") - actions.move_to_element(delete_button).click().perform() + actions.move_to_element(delete_button).click().perform() - confirmation_button = driver.find_element_by_class_name("layerConfirm") + confirmation_button = driver.find_element_by_class_name("layerConfirm") - # Facebook would not let me get focus on this button without some custom JS - driver.execute_script("arguments[0].click();", confirmation_button) + # Facebook would not let me get focus on this button without some custom JS + driver.execute_script("arguments[0].click();", confirmation_button) + except: + pass # Required to sleep the thread for a bit after using JS to click this button time.sleep(5) From ab6450f33a1a2b8649e8ad5dac22be23e294706b Mon Sep 17 00:00:00 2001 From: Michael Gecht Date: Tue, 21 May 2019 14:14:50 +0200 Subject: [PATCH 2/3] Add explicit exceptions --- deletefb/deletefb.py | 47 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/deletefb/deletefb.py b/deletefb/deletefb.py index 30e8f52..42ab985 100755 --- a/deletefb/deletefb.py +++ b/deletefb/deletefb.py @@ -6,7 +6,7 @@ import time from seleniumrequests import Chrome from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.chrome.options import Options - +from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException MAX_POSTS = 5000 @@ -103,30 +103,31 @@ def delete_posts(user_email_address, driver.get(user_profile_url) for _ in range(MAX_POSTS): - try: - post_button_sel = "_4xev" - timeline_element = driver.find_element_by_class_name(post_button_sel) - actions = ActionChains(driver) - actions.move_to_element(timeline_element).click().perform() - - menu = driver.find_element_by_css_selector("#globalContainer > div.uiContextualLayerPositioner.uiLayer > div") - actions.move_to_element(menu).perform() + post_button_sel = "_4xev" + while True: try: - delete_button = menu.find_element_by_xpath("//a[@data-feed-option-name=\"FeedDeleteOption\"]") - - # FIXME Using a bare except here to avoid having to handle all possible exceptions - except: - delete_button = menu.find_element_by_xpath("//a[@data-feed-option-name=\"HIDE_FROM_TIMELINE\"]") - - actions.move_to_element(delete_button).click().perform() - - confirmation_button = driver.find_element_by_class_name("layerConfirm") - - # Facebook would not let me get focus on this button without some custom JS - driver.execute_script("arguments[0].click();", confirmation_button) - except: - pass + timeline_element = driver.find_element_by_class_name(post_button_sel) + actions = ActionChains(driver) + actions.move_to_element(timeline_element).click().perform() + + menu = driver.find_element_by_css_selector("#globalContainer > div.uiContextualLayerPositioner.uiLayer > div") + actions.move_to_element(menu).perform() + + try: + delete_button = menu.find_element_by_xpath("//a[@data-feed-option-name=\"FeedDeleteOption\"]") + except (NoSuchElementException, StaleElementReferenceException): + delete_button = menu.find_element_by_xpath("//a[@data-feed-option-name=\"HIDE_FROM_TIMELINE\"]") + + actions.move_to_element(delete_button).click().perform() + confirmation_button = driver.find_element_by_class_name("layerConfirm") + + # Facebook would not let me get focus on this button without some custom JS + driver.execute_script("arguments[0].click();", confirmation_button) + except (NoSuchElementException, StaleElementReferenceException): + continue + else: + break # Required to sleep the thread for a bit after using JS to click this button time.sleep(5) From 9f832e6fbd091384f033f0e466ea4ecdf364a9b5 Mon Sep 17 00:00:00 2001 From: Michael Gecht Date: Tue, 21 May 2019 15:30:28 +0200 Subject: [PATCH 3/3] Refactor selenium exceptions into constant --- deletefb/deletefb.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deletefb/deletefb.py b/deletefb/deletefb.py index 42ab985..2e16b28 100755 --- a/deletefb/deletefb.py +++ b/deletefb/deletefb.py @@ -9,6 +9,7 @@ from selenium.webdriver.chrome.options import Options from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException MAX_POSTS = 5000 +SELENIUM_EXCEPTIONS = (NoSuchElementException, StaleElementReferenceException) def run_delete(): parser = argparse.ArgumentParser() @@ -116,7 +117,7 @@ def delete_posts(user_email_address, try: delete_button = menu.find_element_by_xpath("//a[@data-feed-option-name=\"FeedDeleteOption\"]") - except (NoSuchElementException, StaleElementReferenceException): + except SELENIUM_EXCEPTIONS: delete_button = menu.find_element_by_xpath("//a[@data-feed-option-name=\"HIDE_FROM_TIMELINE\"]") actions.move_to_element(delete_button).click().perform() @@ -124,7 +125,7 @@ def delete_posts(user_email_address, # Facebook would not let me get focus on this button without some custom JS driver.execute_script("arguments[0].click();", confirmation_button) - except (NoSuchElementException, StaleElementReferenceException): + except SELENIUM_EXCEPTIONS: continue else: break