Compare commits

...

18 Commits

Author SHA1 Message Date
dependabot[bot] ed96dd7e6a
Bump urllib3 from 1.25.2 to 1.25.8 (#162) 3 years ago
Sean Leavey b93f528f99
Ensure protocol is provided in mobile URLs (fixes #160) (#161) 3 years ago
dependabot[bot] ddf358bed2
Bump pygments from 2.4.2 to 2.7.4 (#158) 3 years ago
dependabot[bot] 262c7f84c6
Bump lxml from 4.6.2 to 4.6.3 (#159) 3 years ago
Ian Hunter a92fd3eb35
Update Required Python version (#157) 3 years ago
Wesley Kerfoot d64ed5a3db
Update README.md 3 years ago
Wesley Kerfoot 39b2437f1d
Update README.md 3 years ago
dependabot[bot] 72eb1bdcde
Bump bleach from 3.1.4 to 3.3.0 (#155) 3 years ago
Wesley Kerfoot 86403534b9
bump versions of cattrs and attrs (#151) 3 years ago
dependabot[bot] 11c21f6d2c
Bump lxml from 4.4.0 to 4.6.2 (#150) 3 years ago
tklam a5ed694a46
Add "Hide from profile" (#145) 3 years ago
Wesley Kerfoot ede08a42a9 bump version 4 years ago
Thomas c1af411453
WebDriverException not defined (#139) 4 years ago
Wesley Kerfoot 7d24450b0f
add FUNDING.yml (#137) 4 years ago
Wesley Kerfoot 1a846f1dac bump version 4 years ago
Wesley Kerfoot a182eaaaa3
fixes https://github.com/weskerfoot/DeleteFB/issues/135 (#136) 4 years ago
Wesley Kerfoot 50162ba996
fix unliking (#134) 4 years ago
Wesley Kerfoot 9747f0a00d bump version 4 years ago
  1. 2
      FUNDING.yml
  2. 8
      README.md
  3. 1
      deletefb/tools/chrome_driver.py
  4. 21
      deletefb/tools/common.py
  5. 42
      deletefb/tools/likes.py
  6. 2
      deletefb/tools/wall.py
  7. 12
      requirements.txt
  8. 6
      setup.py

2
FUNDING.yml

@ -0,0 +1,2 @@
github: [weskerfoot]
custom: "39qHYvjVcMCNFr3RPAVetci9mKjzYGTQPz"

8
README.md

@ -1,3 +1,7 @@
WARNING:
This currently only works for English language Facebook accounts, due to the lack of a usable API.
Also, year by year deletion is currently broken. Feel free to fork or make pull requests.
## Why?
I needed a simple and reliable way to delete Facebook posts. There are
@ -18,7 +22,7 @@ Personally, I did this so I would feel less attached to my Facebook profile
(and hence feel the need to use it less).
## Dependencies
- This tool requires at least Python 3.6 in order to run.
- This tool requires at least Python 3.7 in order to run.
- A recent copy of Chrome or Chromium installed and available in your `$PATH`
## Installation
@ -57,7 +61,7 @@ optional arguments:
```
* Make sure that you have a recent version of Python 3.x installed (preferably
3.6 or greater)
3.7 or greater)
* Make sure that you have Google Chrome installed and that it is up to date
* The tool will attempt to automatically install chromedriver for Selenium. See [here](https://sites.google.com/a/chromium.org/chromedriver/home) for an explanation of what the chromedriver does. You may have to manually install it if auto-install fails.
* On Linux, it will be called something like `chromium-chromedriver` or just

1
deletefb/tools/chrome_driver.py

@ -2,6 +2,7 @@ from ..exceptions import UnknownOSException, ChromeError
from .common import NO_CHROME_DRIVER
from clint.textui import puts, colored
from selenium import webdriver
from selenium.common.exceptions import WebDriverException
from shutil import which
from subprocess import check_output
from urllib.request import urlretrieve

21
deletefb/tools/common.py

@ -20,13 +20,20 @@ SELENIUM_EXCEPTIONS = (
TimeoutException
)
def click_button(driver, el):
"""
Click a button using Javascript
"""
driver.execute_script("arguments[0].click();", el)
def scroll_until_element_exists(driver, xpath_expr):
while True:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
try:
element = driver.find_element_by_xpath(xpath_expr)
except SELENIUM_EXCEPTIONS:
continue
break
def scroll_to(driver, el):
"""
@ -37,7 +44,6 @@ def scroll_to(driver, el):
except SELENIUM_EXCEPTIONS:
return
def logger(name):
"""
Args:
@ -57,12 +63,11 @@ def logger(name):
logging.config.dictConfig(config["logging"])
return logging.getLogger(name)
def wait_xpath(driver, expr):
def wait_xpath(driver, expr, timeout=20):
"""
Takes an XPath expression, and waits at most 20 seconds until it exists
Takes an XPath expression, and waits at most `timeout` seconds until it exists
"""
wait = WebDriverWait(driver, 20)
wait = WebDriverWait(driver, timeout)
try:
wait.until(EC.presence_of_element_located((By.XPATH, expr)))
except SELENIUM_EXCEPTIONS:
@ -73,7 +78,9 @@ def force_mobile(url):
Force a url to use the mobile site.
"""
parsed = urlparse.urlparse(url)
return urlparse.urlunparse((parsed.scheme,
# Ensure a protocol is given (needed by selenium).
scheme = parsed.scheme or "https"
return urlparse.urlunparse((scheme,
"mobile.facebook.com",
parsed.path,
parsed.params,

42
deletefb/tools/likes.py

@ -1,6 +1,6 @@
from .archive import archiver
from ..types import Page
from .common import SELENIUM_EXCEPTIONS, logger, click_button
from .common import SELENIUM_EXCEPTIONS, logger, click_button, wait_xpath, force_mobile, scroll_to, scroll_until_element_exists
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
@ -18,17 +18,25 @@ def load_likes(driver, profile_url):
None
"""
driver.get("{0}/likes_all".format(profile_url))
likes_link_xpath = "//div[normalize-space(text())='Likes']/../..//a[contains(@href, 'app_section')]"
wait = WebDriverWait(driver, 20)
all_likes_link_xpath = "//div[normalize-space(text())='All Likes']/../../../..//a[contains(@href, 'app_collection')]"
try:
wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".PageLikeButton"))
)
except SELENIUM_EXCEPTIONS:
LOG.exception("Traceback of load_likes")
return
driver.get(force_mobile("{0}/about".format(profile_url)))
scroll_until_element_exists(driver, "//div[text()='Likes']")
likes_link_el = driver.find_element_by_xpath(likes_link_xpath)
driver.get(likes_link_el.get_attribute("href"))
wait_xpath(driver, all_likes_link_xpath)
all_likes_link_el = driver.find_element_by_xpath(all_likes_link_xpath)
all_likes_link = all_likes_link_el.get_attribute("href")
driver.get(all_likes_link)
def get_page_links(driver):
"""
@ -39,8 +47,7 @@ def get_page_links(driver):
Returns:
List of URLs to pages
"""
pages = driver.find_elements_by_xpath("//li//div/div/a[contains(@class, 'lfloat')]")
pages = driver.find_elements_by_xpath("//header/..//a")
return [page.get_attribute("href").replace("www", "mobile") for page in pages]
def unlike_page(driver, url, archive=None):
@ -60,7 +67,7 @@ def unlike_page(driver, url, archive=None):
print("Unliking {0}".format(url))
wait = WebDriverWait(driver, 20)
wait = WebDriverWait(driver, 5)
try:
wait.until(
@ -70,19 +77,14 @@ def unlike_page(driver, url, archive=None):
# Something went wrong with this page, so skip it
return
button = driver.find_element_by_xpath("//*[text()='Liked']")
# Click the "Liked" button to open up "Unlike"
click_button(driver, button)
driver.find_element_by_xpath("//*[text()='Liked']/../../../..").click()
wait.until(
EC.presence_of_element_located((By.XPATH, "//*[text()='Unlike']"))
)
# There should be an "Unlike" button now, click it
unlike_button = driver.find_element_by_xpath("//*[text()='Unlike']/..")
click_button(driver, unlike_button)
driver.find_element_by_xpath("//*[text()='Unlike']/..").click()
if archive:
archive(Page(name=url))

2
deletefb/tools/wall.py

@ -45,7 +45,7 @@ def delete_posts(driver,
# Tries to be pretty resilient against DOM re-organizations
timestamp_exp = "//article//*/header//*/div/a[contains(@href, 'story_fbid')]//text()/.."
button_types = ["Delete post", "Remove Tag", "Hide from timeline"]
button_types = ["Delete post", "Remove tag", "Hide from timeline", "Hide from profile"]
while True:
try:

12
requirements.txt

@ -1,20 +1,20 @@
appdirs==1.4.3
args==0.1.0
attrs==19.1.0
attrs==20.3.0
bitarray==0.9.3
bleach==3.1.4
cattrs-3.8==0.9.1
bleach==3.3.0
cattrs==1.1.2
certifi==2018.11.29
chardet==3.0.4
clint==0.5.1
docutils==0.14
idna==2.8
lxml==4.4.0
lxml==4.6.3
pendulum==2.0.5
pkginfo==1.5.0.1
progressbar==2.5
pybloom-live==3.0.0
Pygments==2.4.2
Pygments==2.7.4
python-dateutil==2.8.0
pytzdata==2019.2
readme-renderer==24.0
@ -28,5 +28,5 @@ tldextract==2.2.0
tqdm==4.32.2
twine==1.13.0
typing==3.7.4
urllib3==1.25.2
urllib3==1.25.8
webencodings==0.5.1

6
setup.py

@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
setuptools.setup(
name="delete-facebook-posts",
version="1.1.13",
version="1.1.17",
author="Wesley Kerfoot",
author_email="wes@wesk.tech",
description="A Selenium Script to Delete Facebook Posts",
@ -24,8 +24,8 @@ setuptools.setup(
"selenium-requests",
"requests",
"pybloom-live",
"attrs",
"cattrs-3.8",
"attrs>=20.3.0",
"cattrs>=1.1.2",
"lxml",
"pendulum",
"clint",

Loading…
Cancel
Save