├── .gitignore ├── LICENSE ├── MemeDensity ├── __init__.py └── command_line.py ├── README.md ├── setup.py └── workflow.gif /.gitignore: -------------------------------------------------------------------------------- 1 | #### joe made this: http://goel.io/joe 2 | #### python #### 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *,cover 49 | .hypothesis/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # dotenv 82 | .env 83 | 84 | # virtualenv 85 | .venv/ 86 | venv/ 87 | ENV/ 88 | 89 | # Spyder project settings 90 | .spyderproject 91 | 92 | # Rope project settings 93 | .ropeproject 94 | 95 | # Trash 96 | .DS_Store 97 | 98 | #log 99 | ghostdriver.log 100 | 101 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Lakshay Kalbhor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MemeDensity/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kalbhor/MemeDensity/268b1d06b034fa8cc0782647dce6ac9c64ff0dde/MemeDensity/__init__.py -------------------------------------------------------------------------------- /MemeDensity/command_line.py: -------------------------------------------------------------------------------- 1 | 2 | ASCII = """ 3 | __ __ _____ _ _ 4 | | \/ | | __ \ (_) | 5 | | \ / | ___ _ __ ___ ___| | | | ___ _ __ ___ _| |_ _ _ 6 | | |\/| |/ _ \ '_ ` _ \ / _ \ | | |/ _ \ '_ \/ __| | __| | | | 7 | | | | | __/ | | | | | __/ |__| | __/ | | \__ \ | |_| |_| | 8 | |_| |_|\___|_| |_| |_|\___|_____/ \___|_| |_|___/_|\__|\__, | 9 | __/ | 10 | |___/ 11 | """ 12 | 13 | DESC = """ 14 | - Tells you approximately how many memes are currently in your facebook 15 | newsfeed. Provides % memes in newsfeed. 16 | 17 | - Provides memes in newsfeed urls 18 | """ 19 | 20 | import os 21 | import argparse 22 | import requests 23 | import six 24 | from selenium import webdriver 25 | from selenium.webdriver.common.keys import Keys 26 | from time import sleep 27 | from getpass import getpass 28 | from argparse import RawTextHelpFormatter 29 | 30 | if six.PY2: 31 | input = raw_input 32 | else: 33 | pass 34 | 35 | def _login_fb(): 36 | 37 | email = input('> Email or Phone: ') 38 | password = getpass('> Password: ') 39 | 40 | return email,password 41 | 42 | def _xkcd(): 43 | 44 | r = requests.get('http://xkcd.com/info.0.json').json() 45 | return r['img'] 46 | 47 | def _execute_script(email, password, count): 48 | 49 | 50 | print("\nLoading..\nCheck out today's xkcd comic till then : %s \n\n" %(_xkcd())) 51 | 52 | driver = webdriver.PhantomJS() 53 | driver.get('https://www.facebook.com') 54 | 55 | email_ID = driver.find_element_by_id('email') 56 | pass_ID = driver.find_element_by_id('pass') 57 | 58 | 59 | email_ID.send_keys(email) 60 | pass_ID.send_keys(password) 61 | pass_ID.send_keys(Keys.ENTER) 62 | sleep(5) 63 | 64 | for i in range(0,count): 65 | driver.execute_script("window.scrollBy(0, document.body.scrollHeight);") 66 | sleep(1) 67 | 68 | sleep(5) 69 | 70 | driver_tags = driver.execute_script('return document.getElementsByClassName("scaledImageFitWidth img")') 71 | 72 | driver_img_list = { 73 | 'src' : [x.get_attribute('src') for x in driver_tags], 74 | 'alt' : [x.get_attribute('alt') for x in driver_tags], 75 | } 76 | 77 | driver.quit() 78 | 79 | return driver_img_list 80 | 81 | 82 | def _check_memes(driver_img_list, verbose): 83 | 84 | alt_list = driver_img_list['alt'] 85 | if len(alt_list) == 0: 86 | print("Error getting newsfeed. Possibly username or password was incorrect") 87 | return 88 | 89 | output = "\n{} memes in your newsfeed.\n{} total images in your newsfeed.\n{}% memes in newsfeed.\n" 90 | count = 0 91 | 92 | for key,alt in enumerate(alt_list): 93 | if "text" in alt or "meme" in alt : 94 | count += 1 95 | if verbose: 96 | print(driver_img_list['src'][key]) 97 | 98 | print(output.format(count,len(alt_list),round(count*100/len(alt_list),2))) 99 | 100 | 101 | def main(): 102 | 103 | print('\n') 104 | 105 | parser = argparse.ArgumentParser( 106 | description='\n{}\n{}\n'.format(ASCII,DESC), formatter_class=RawTextHelpFormatter) 107 | parser.add_argument('-C', '--count', action='store', dest='count', 108 | help='How many times to scroll newsfeed (default = 5)') 109 | parser.add_argument('-L', '--login', action='store_true', 110 | help='Input login credentials') 111 | parser.add_argument('-v', '--verbose', action='store_true', 112 | help='Shows meme urls') 113 | args = parser.parse_args() 114 | 115 | count = int(args.count or '5') 116 | login_bool = args.login 117 | verbose_bool = args.verbose 118 | 119 | if login_bool: 120 | email,password = _login_fb() 121 | else: 122 | try: 123 | email=os.environ['fb_email'] 124 | password=os.environ['fb_pass'] 125 | except KeyError: 126 | print("Couldn't find fb_email and fb_pass in environment variables") 127 | email,password = _login_fb() 128 | 129 | driver_img_list = _execute_script(email, password, count) 130 | _check_memes(driver_img_list, verbose_bool) 131 | 132 | 133 | if __name__ == '__main__': 134 | 135 | main() 136 | 137 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

M E M E   D E N S I T Y

2 | 3 | #### Tells you the approximate amount of memes in your facebook newsfeed. 4 | 5 | ![alt tag](workflow.gif) 6 | 7 | ## Preface 8 | Since April 2016, Facebook has been automatically adding alt tags to all images with keywords representing the content of the images: 9 | 10 | ```html 11 | Image may contain: golf, grass, outdoor and nature 14 | ``` 15 | 16 | They are labeling the images using a [Deep ConvNet](https://medium.com/@ageitgey/machine-learning-is-fun-part-3-deep-learning-and-convolutional-neural-networks-f40359318721#.2zrawvage) built by Facebook's [FAIR team](https://research.fb.com/category/facebook-ai-research-fair/) team. 17 | 18 | On one hand, this is really great. It improves accessibility for blind users who depend on screen readers which are only capable of processing text. But raises privacy concerns too. 19 | ###### Thank you [ageitgey](https://github.com/ageitgey/show-facebook-computer-vision-tags) for originally finding out about this. 20 | 21 | ##### Anyhow, this script uses this addition by Facebook to it's advantage. MemeDensity reads alt tags of the images in your newsfeed and lets you know the quantity of memes on your feed. 22 | 23 | ##### Since Facebook doesn't directly allow fetching the newsfeed from its API, this script uses Selenium and PhantomJS to simulate a surf through the newsfeed. 24 | 25 | ## Dependencies 26 | 27 | ##### PhantomJS or any other webdriver. 28 | 29 | #### MacOS 30 | ```sh 31 | brew install phantomjs 32 | ``` 33 | #### Linux 34 | ```sh 35 | sudo apt-get install phantomjs 36 | ``` 37 | #### Windows 38 | [Download and set in environment variables](http://phantomjs.org/) 39 | 40 | ## Installing 41 | 42 | #### From Source: 43 | Check out the latest [release](https://github.com/kalbhor/MemeDensity/releases) 44 | ##### or 45 | ```sh 46 | $ git clone https://github.com/kalbhor/MemeDensity 47 | $ cd MemeDensity 48 | $ python setup.py install 49 | ``` 50 | 51 | #### From PyPI: 52 | ```sh 53 | $ pip install memedensity 54 | ``` 55 |
56 | 57 | If you'll be using a different webdriver (Not PhantomJS), simply edit [MemeDensity/command_line.py](https://github.com/kalbhor/MemeDensity/blob/master/MemeDensity/command_line.py) and add your webdriver 58 | ```py 59 | driver = webdriver.PhantomJS() 60 | ``` 61 | ## Options 62 | ``` 63 | optional arguments: 64 | -h, --help show this help message and exit 65 | -C, --count How many times to scroll newsfeed (default = 5) 66 | -L, --login Input login credentials 67 | -v, --verbose Shows meme urls 68 | ``` 69 | 70 | ## Usage 71 | ```sh 72 | $ memedensity 73 | ``` 74 | ## Contributing 75 | Currently this project is in its infancy and issues are bound to arise. If the script throws an exception, please make sure to check your running processes to see whether the webdriver has been closed or not. 76 | To contribute, [post issues](https://github.com/kalbhor/MemeDensity/issues) without hesitation and [open pull requests](https://github.com/kalbhor/MemeDensity/pulls) to add/improve features. 77 | 78 | ## License 79 | #### [MIT](https://github.com/kalbhor/MemeDensity/blob/master/LICENSE) 80 | 81 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup(name='memedensity', 4 | version='0.0.2', 5 | description='Tells you the amount of memes in your facebook feed', 6 | url='https://github.com/lakshaykalbhor/MemeDensity', 7 | author='Lakshay Kalbhor', 8 | author_email='lakshaykalbhor@gmail.com', 9 | license='MIT', 10 | packages =['MemeDensity'], 11 | install_requires=[ 12 | 'requests', 13 | 'argparse', 14 | 'selenium', 15 | ], 16 | entry_points={ 17 | 'console_scripts': ['memedensity=MemeDensity.command_line:main'], 18 | } 19 | ) -------------------------------------------------------------------------------- /workflow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kalbhor/MemeDensity/268b1d06b034fa8cc0782647dce6ac9c64ff0dde/workflow.gif --------------------------------------------------------------------------------