Added test_download_video.py, updated README.md and refactored downloader.py

This commit is contained in:
Richard Mwewa
2022-10-01 12:52:24 +02:00
parent 77ca7c46cd
commit db63d09c82
5 changed files with 115 additions and 69 deletions

View File

@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

39
.idea/workspace.xml generated Normal file
View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="63ddae2f-8b6a-4549-a699-2e4098a83de2" name="Changes" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectId" id="2FWrWSRTaC1nc0xKHudztzhniGt" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true"
}
}]]></component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="63ddae2f-8b6a-4549-a699-2e4098a83de2" name="Changes" comment="" />
<created>1664618714345</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1664618714345</updated>
</task>
<servers />
</component>
</project>

View File

@@ -52,7 +52,6 @@ python downloader.py https://www.facebook.com/PageName/videos/VideoID
|---------|:-----------:|
| *-A/--audio* | download audio only (coming soon) |
| *-o/--output* | output filename |
| *-d/--debug* | enable debug mode |
| *-v/--version* | show program's version number and exit |
# Donations

View File

@@ -8,94 +8,90 @@ from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
class FacebookDownloader:
def __init__(self, args):
self.option = webdriver.FirefoxOptions()
self.option.add_argument('--headless')
self.driver = webdriver.Firefox(options=self.option)
self.program_version_number = "2022.1.0.0"
self.downloading_url = "https://getfvid.com"
self.update_check_endpoint = "https://api.github.com/repos/rly0nheart/Facebook-Downloader/releases/latest"
option = webdriver.FirefoxOptions()
option.add_argument('--headless')
driver = webdriver.Firefox(options=option)
program_version_number = "2022.1.0.0"
downloading_url = "https://getfvid.com"
update_check_endpoint = "https://api.github.com/repos/rly0nheart/Facebook-Downloader/releases/latest"
def notice(self):
notice_msg = f"""
Facebook-Downloader {self.program_version_number} Copyright (C) 2022 Richard Mwewa
def notice():
notice_msg = f"""
Facebook-Downloader {program_version_number} Copyright (C) 2022 Richard Mwewa
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
"""
return notice_msg
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
"""
print(notice_msg)
def check_and_get_updates(self):
print(self.notice())
response = requests.get(self.update_check_endpoint).json()
if response['tag_name'] == self.program_version_number:
"""Ignore if the program is up to date"""
pass
def check_and_get_updates():
notice()
response = requests.get(update_check_endpoint).json()
if response['tag_name'] == program_version_number:
"""Ignore if the program is up to date"""
pass
else:
update_prompt = input(f"[?] A new release is available ({response['tag_name']}). Would you like to install it? (y/n) ")
if update_prompt.lower() == "y":
files_to_update = ['downloader.py', 'geckodriver.exe', 'README.md', 'requirements.txt']
for file in tqdm(files_to_update, desc=f'Updating'):
data = requests.get(f'https://raw.githubusercontent.com/rly0nheart/Facebook-Downloader/master/{file}')
with open(file, "wb") as f:
f.write(data.content)
f.close()
print("Updated: Re-run program.")
else:
update_prompt = input(f"[?] A new release is available ({response['tag_name']}). Would you like to install it? (y/n) ")
if update_prompt.lower() == "y":
files_to_update = ['downloader.py', 'geckodriver.exe', 'README.md', 'requirements.txt']
for file in tqdm(files_to_update, desc=f'Updating'):
data = requests.get(f'https://raw.githubusercontent.com/rly0nheart/Facebook-Downloader/master/{file}')
with open(file, "wb") as f:
f.write(data.content)
f.close()
logging.info(f"Updated: Re-run program.")
else:
pass
pass
def download_video(self):
self.check_and_get_updates()
self.driver.get(self.downloading_url) # Opening getfvid.com, a website that downloads facebook videos
url_entry_field = self.driver.find_element(By.NAME, "url") # Find the url entry field
url_entry_field.send_keys(args.url) # write facebook url in the entry field
url_entry_field.send_keys(Keys.ENTER) # press enter
time.sleep(20) # Sleep for at least 20 seconds to wait for the next page to load
self.driver.refresh
"""
HD: "/html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[1]/a"
SD: "/html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[2]/a"
Audio: "/html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[3]/a"
"""
def download_video(url, output):
driver.get(downloading_url) # Opening getfvid.com, a website that downloads facebook videos
url_entry_field = driver.find_element(By.NAME, "url") # Find the url entry field
url_entry_field.send_keys(url) # write facebook url in the entry field
url_entry_field.send_keys(Keys.ENTER) # press enter
print('Please standby (20 seconds)...')
time.sleep(20) # Sleep for at least 20 seconds to wait for the next page to load
driver.refresh
"""
HD: "/html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[1]/a"
SD: "/html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[2]/a"
Audio: "/html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[3]/a"
"""
download_btn = self.driver.find_element(By.XPATH, '/html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[1]/a') # Find the download button (this clicks the first button which returns a video in hd)
download_url = download_btn.get_attribute('href')
with requests.get(download_url, stream=True) as response:
response.raise_for_status()
with open(f'downloads/{args.output}.mp4', 'wb') as file:
for chunk in tqdm(response.iter_content(chunk_size=8192), desc=f'Downloading: {args.output}.mp4'):
file.write(chunk)
print(f'Downloaded: {file.name}')
self.driver.close()
download_btn = driver.find_element(By.XPATH, '/html/body/div[2]/div/div/div[1]/div/div[2]/div/div[3]/p[1]/a') # Find the download button (this clicks the first button which returns a video in hd)
download_url = download_btn.get_attribute('href')
with requests.get(download_url, stream=True) as response:
response.raise_for_status()
with open(f'downloads/{output}.mp4', 'wb') as file:
for chunk in tqdm(response.iter_content(chunk_size=8192), desc=f'Downloading: {output}.mp4'):
file.write(chunk)
print(f'Downloaded: {file.name}')
driver.close()
parser = argparse.ArgumentParser(description='Facebook-Downloader — by Richard Mwewa')
parser.add_argument('url', help='facebook video url (eg. https://www.facebook.com/PageName/videos/VideoID')
parser.add_argument('-A', '--audio', help=argparse.SUPPRESS, action='store_true')
parser.add_argument('-o', '--output', help='output filename')
parser.add_argument('-d', '--debug', help='enable debug mode', action='store_true')
parser.add_argument('-v', '--version', version='2022.1.0.0', action='version')
args = parser.parse_args()
if args.debug:
logging.basicConfig(format='[%(asctime)s] %(message)s', datefmt='%I:%M:%S%p', level=logging.DEBUG)
else:
logging.basicConfig(format='[%(asctime)s] %(message)s', datefmt='%I:%M:%S%p', level=logging.INFO)
url = args.url
output = args.output
if __name__ == "__main__":
try:
FacebookDownloader(args).download_video()
check_and_get_updates()
download_video(url, output)
except KeyboardInterrupt:
logging.warning('Process interrupted with Ctrl+C.')
print('Process interrupted with Ctrl+C.')
except Exception as e:
logging.error(f'An error occured: {e}')
print('An error occured:', e)

6
test_download_video.py Normal file
View File

@@ -0,0 +1,6 @@
from downloader import download_video
def test_download_video():
# I find this video very interesting, enjoy! ;)
url = 'https://www.facebook.com/VICE/videos/663211078474482'
download_video(url, output='test_video_making-a-weed-smoothie')