├── example.jpg
├── .gitignore
├── Pipfile
├── LICENSE
├── utils.py
├── README.md
├── template-map.html
└── make.py
/example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jcontini/facebook-friends-map/HEAD/example.jpg
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .*
2 | db
3 | friends-map.html
4 | test.py
5 | *.json
6 | *.log
7 | *.csv
8 | *.lock
9 | *.geojson
10 | *.ipynb
11 | .env
12 |
--------------------------------------------------------------------------------
/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 | name = "pypi"
3 | url = "https://pypi.org/simple"
4 | verify_ssl = true
5 |
6 | [dev-packages]
7 | pylint = "*"
8 |
9 | [packages]
10 | requests = "*"
11 | selenium = "*"
12 | geojson = "*"
13 | sqlite-utils = "*"
14 | webdriver_manager = "*"
15 | lxml = "*"
16 |
17 | [requires]
18 | python_version = "3"
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Joe Contini
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 |
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # coding: utf-8
3 | import os, json
4 | from sqlite_utils import Database
5 | from selenium import webdriver
6 |
7 | from webdriver_manager.firefox import GeckoDriverManager
8 | # driver = webdriver.Firefox(executable_path=GeckoDriverManager().install())
9 |
10 | # --- Paths ---
11 | db_folder = 'db/'
12 | json_folder = db_folder + 'json/'
13 |
14 | if not os.path.exists(json_folder):
15 | os.makedirs(json_folder)
16 |
17 | if not os.path.exists(db_folder):
18 | os.makedirs(db_folder)
19 |
20 | # --- Database ---
21 | db_file = 'data.db'
22 | db_path = db_folder + db_file
23 |
24 | db = Database(db_path)
25 |
26 | def db_setup():
27 | db["friend_list"].create({
28 | 'id':int,
29 | }, pk="id")
30 |
31 | db["profiles"].create({
32 | 'id':int,
33 | }, pk="id")
34 |
35 | db["locations"].create({
36 | "location":str
37 | }, pk="location")
38 |
39 | print('>> Database initialized (%s)' % db_path)
40 |
41 | def db_read(table):
42 | data = []
43 | for row in db[table].rows:
44 | data.append(row)
45 | return data
46 |
47 | def db_write(table,data):
48 | db_table = db[table]
49 | db_table.insert(data, alter=True)
50 |
51 | def db_update(table,id,data):
52 | db[table].update(id, data, alter=True)
53 |
54 | def db_to_json():
55 | tables = db.table_names()
56 | for table in tables:
57 | data = []
58 | for row in db[table].rows:
59 | data.append(row)
60 | json_path = json_folder + table + '.json'
61 | with open(json_path, 'w+', encoding="utf-8") as f:
62 | json.dump(data, f, indent=2)
63 | print('%s extracted to %s' % (table,json_path))
64 |
65 | # Initialize database if not yet created
66 | if len(db.table_names()) == 0:
67 | db_setup()
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Facebook Friend Mapper
2 |
3 | 
4 |
5 | Create a map of your facebook friends! Useful for when you're passing through a city and can't remember all the people you want to grab coffee with.
6 |
7 | ## First: A Warning
8 | When using this tool, Facebook can see that you're using an automated tool, which violates their terms. There is a risk that Facebook may decide to put a temporary or permanent ban on your account (though I haven't heard of this happening to anyone yet). I am not responsible for this or any other outcomes that may occur as a result of the use of this software.
9 |
10 | ## What this is
11 | This tool will only extract the data that your friends have already explicitly made it available to you. If the amount or content of the data freaks you (like it did to me!), then it's a good reminder for us all to check our profiles/privacy settings to make sure that we only share what we want others to be able to see.
12 |
13 | It works like this:
14 | 1. Open your friends list page (on m.facebook.com) and save to `db/friend_list.html`
15 | 2. Download your friend's profiles (on mbasic.facebook.com) to `db/profiles/`
16 | 3. Parse profiles for 'Current City' or 'Address' and add to location list.
17 | 4. Find the lat/long for each location (using Mapbox API) and save to `db/points.geojson`.
18 | 5. Creates `friends-map.html`, a self-contained, moveable, searchable map of your friends all over the world!
19 |
20 | All data is saved locally in `db/data.db` as a sqlite database.
21 |
22 | ## Installation
23 | Prerequisites:
24 | - Make sure that `python 3` and `pipenv` are installed.
25 | - Create a free [Mapbox API key](https://docs.mapbox.com/help/glossary/access-token). You'll need this so the tool can geocode city names into coordinates to use on the map.
26 |
27 | Then:
28 | 1. Clone this repository
29 | 2. `cd` into the cloned folder
30 | 3. Run `pipenv install` to install dependencies
31 |
32 | ## Using the tool
33 | 1. Run `pipenv shell` to activate the virtual environment. This is optional if you already have the required packages installed in your environment.
34 | 2. Run `python make.py`. On the first run, it'll ask for your Facebook username/password and Mapbox API Key. It saves these to the local `.env` file for use in subsequent runs (eg if you add more friends).
35 | 3. The tool will then index your friend list, download friend's profiles, geocode coordinates, and create the map. You can optionally use any of these flags to perform only certain actions:
36 |
37 | - `--list` Sign in, download friends list HTML
38 | - `--index` Extract friend list HTML to database
39 | - `--download` Download profile for each friend in index
40 | - `--parse` Extract profiles HTML to database
41 | - `--map` Geocode addresses & make the map!
42 | - `--json` Export sqlite database to JSON files (db/json/)
43 |
44 | If something breaks, just run the script again. It's built to pick up where it left off at all stages.
45 | Please file an issue if you run into any problems. Enjoy!
--------------------------------------------------------------------------------
/template-map.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |