├── MemeDensity
├── __init__.py
└── command_line.py
├── workflow.gif
├── setup.py
├── LICENSE
├── .gitignore
└── README.md
/MemeDensity/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/workflow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kalbhor/MemeDensity/HEAD/workflow.gif
--------------------------------------------------------------------------------
/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 | )
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 | 
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 |
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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------