diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..8ef9502 --- /dev/null +++ b/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +requests = "*" +numpy = "*" +pandas = "*" + +[dev-packages] + +[requires] +python_version = "3.10" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..8bf1cce --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,139 @@ +{ + "_meta": { + "hash": { + "sha256": "864ee81413d2d76069a372c39e9bffb8bda1c636b2b78e2b99517f7828e10bf9" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.10" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "certifi": { + "hashes": [ + "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d", + "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412" + ], + "markers": "python_full_version >= '3.6.0'", + "version": "==2022.6.15" + }, + "charset-normalizer": { + "hashes": [ + "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", + "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413" + ], + "markers": "python_full_version >= '3.6.0'", + "version": "==2.1.0" + }, + "idna": { + "hashes": [ + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" + ], + "markers": "python_version >= '3.5'", + "version": "==3.3" + }, + "numpy": { + "hashes": [ + "sha256:1408c3527a74a0209c781ac82bde2182b0f0bf54dea6e6a363fe0cc4488a7ce7", + "sha256:173f28921b15d341afadf6c3898a34f20a0569e4ad5435297ba262ee8941e77b", + "sha256:1865fdf51446839ca3fffaab172461f2b781163f6f395f1aed256b1ddc253622", + "sha256:3119daed207e9410eaf57dcf9591fdc68045f60483d94956bee0bfdcba790953", + "sha256:35590b9c33c0f1c9732b3231bb6a72d1e4f77872390c47d50a615686ae7ed3fd", + "sha256:37e5ebebb0eb54c5b4a9b04e6f3018e16b8ef257d26c8945925ba8105008e645", + "sha256:37ece2bd095e9781a7156852e43d18044fd0d742934833335599c583618181b9", + "sha256:3ab67966c8d45d55a2bdf40701536af6443763907086c0a6d1232688e27e5447", + "sha256:47f10ab202fe4d8495ff484b5561c65dd59177949ca07975663f4494f7269e3e", + "sha256:55df0f7483b822855af67e38fb3a526e787adf189383b4934305565d71c4b148", + "sha256:5d732d17b8a9061540a10fda5bfeabca5785700ab5469a5e9b93aca5e2d3a5fb", + "sha256:68b69f52e6545af010b76516f5daaef6173e73353e3295c5cb9f96c35d755641", + "sha256:7e8229f3687cdadba2c4faef39204feb51ef7c1a9b669247d49a24f3e2e1617c", + "sha256:8002574a6b46ac3b5739a003b5233376aeac5163e5dcd43dd7ad062f3e186129", + "sha256:876f60de09734fbcb4e27a97c9a286b51284df1326b1ac5f1bf0ad3678236b22", + "sha256:9ce242162015b7e88092dccd0e854548c0926b75c7924a3495e02c6067aba1f5", + "sha256:a35c4e64dfca659fe4d0f1421fc0f05b8ed1ca8c46fb73d9e5a7f175f85696bb", + "sha256:aeba539285dcf0a1ba755945865ec61240ede5432df41d6e29fab305f4384db2", + "sha256:b15c3f1ed08df4980e02cc79ee058b788a3d0bef2fb3c9ca90bb8cbd5b8a3a04", + "sha256:c2f91f88230042a130ceb1b496932aa717dcbd665350beb821534c5c7e15881c", + "sha256:d748ef349bfef2e1194b59da37ed5a29c19ea8d7e6342019921ba2ba4fd8b624", + "sha256:e0d7447679ae9a7124385ccf0ea990bb85bb869cef217e2ea6c844b6a6855073" + ], + "index": "pypi", + "version": "==1.23.1" + }, + "pandas": { + "hashes": [ + "sha256:07238a58d7cbc8a004855ade7b75bbd22c0db4b0ffccc721556bab8a095515f6", + "sha256:0daf876dba6c622154b2e6741f29e87161f844e64f84801554f879d27ba63c0d", + "sha256:16ad23db55efcc93fa878f7837267973b61ea85d244fc5ff0ccbcfa5638706c5", + "sha256:1d9382f72a4f0e93909feece6fef5500e838ce1c355a581b3d8f259839f2ea76", + "sha256:24ea75f47bbd5574675dae21d51779a4948715416413b30614c1e8b480909f81", + "sha256:2893e923472a5e090c2d5e8db83e8f907364ec048572084c7d10ef93546be6d1", + "sha256:2ff7788468e75917574f080cd4681b27e1a7bf36461fe968b49a87b5a54d007c", + "sha256:41fc406e374590a3d492325b889a2686b31e7a7780bec83db2512988550dadbf", + "sha256:48350592665ea3cbcd07efc8c12ff12d89be09cd47231c7925e3b8afada9d50d", + "sha256:605d572126eb4ab2eadf5c59d5d69f0608df2bf7bcad5c5880a47a20a0699e3e", + "sha256:6dfbf16b1ea4f4d0ee11084d9c026340514d1d30270eaa82a9f1297b6c8ecbf0", + "sha256:6f803320c9da732cc79210d7e8cc5c8019aad512589c910c66529eb1b1818230", + "sha256:721a3dd2f06ef942f83a819c0f3f6a648b2830b191a72bbe9451bcd49c3bd42e", + "sha256:755679c49460bd0d2f837ab99f0a26948e68fa0718b7e42afbabd074d945bf84", + "sha256:78b00429161ccb0da252229bcda8010b445c4bf924e721265bec5a6e96a92e92", + "sha256:958a0588149190c22cdebbc0797e01972950c927a11a900fe6c2296f207b1d6f", + "sha256:a3924692160e3d847e18702bb048dc38e0e13411d2b503fecb1adf0fcf950ba4", + "sha256:d51674ed8e2551ef7773820ef5dab9322be0828629f2cbf8d1fc31a0c4fed640", + "sha256:d5ebc990bd34f4ac3c73a2724c2dcc9ee7bf1ce6cf08e87bb25c6ad33507e318", + "sha256:d6c0106415ff1a10c326c49bc5dd9ea8b9897a6ca0c8688eb9c30ddec49535ef", + "sha256:e48fbb64165cda451c06a0f9e4c7a16b534fcabd32546d531b3c240ce2844112" + ], + "index": "pypi", + "version": "==1.4.3" + }, + "python-dateutil": { + "hashes": [ + "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", + "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.2" + }, + "pytz": { + "hashes": [ + "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7", + "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c" + ], + "version": "==2022.1" + }, + "requests": { + "hashes": [ + "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", + "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" + ], + "index": "pypi", + "version": "==2.28.1" + }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.16.0" + }, + "urllib3": { + "hashes": [ + "sha256:c33ccba33c819596124764c23a97d25f32b28433ba0dedeb77d873a38722c9bc", + "sha256:ea6e8fb210b19d950fab93b60c9009226c63a28808bc8386e05301e25883ac0a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4'", + "version": "==1.26.11" + } + }, + "develop": {} +} diff --git a/README.md b/README.md index 2894a55..9b44553 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ This Python application requires `requests` to be properly installed. This can b The following command will search for Instagram locations nearby the coordinates 32.22 N, 110.97 W (downtown Tucson, Arizona.) The list of locations is saved as a CSV file at "locs.csv". -```python3 instagram-locations.py --session "" --lat 32.22 --lng -110.97 --csv locs.csv``` +```python3 instagram-locations.py --cookie "" --lat 32.22 --lng -110.97 --csv locs.csv``` -Note that this requires an Instagram session ID in order to work! See below for how to obtain one from your account. +Note that this requires Instagram cookies in order to work! See below for how to obtain one from your account. ## Example usage with date @@ -18,7 +18,7 @@ The following command will search for Instagram locations near Seattle's "Capito protests in early June, 2020. Not all location pages in the area will have posts relevant to the Zone, but some do. Open the resulting `map.html` file in your browser to view locations. -```python3 instagram-locations.py --session "" --lat 47.6164311 --lng -122.3203952 --map map.html --date 2020-06-09``` +```python3 instagram-locations.py --cookie "" --lat 47.6164311 --lng -122.3203952 --map map.html --date 2020-06-09``` When using the `--date` argument, links to Instagram location pages will be filtered to show posts created on this date or earlier. Instagram will usually first show a 3x3 grid of "Top Images and Videos" that are more recent, however once you scroll past that @@ -43,7 +43,7 @@ Using the `--map ` command line argument, a simple Leaflet map Multiple types of output can be generated. For example, the following command will search for Instagram locations, save the JSON list, a CSV file, and a map for viewing the locations visually. -```python3 instagram-locations.py --session "" --lat 32.22 --lng -110.97 --json locs.json --csv locs.csv --map map.html``` +```python3 instagram-locations.py --cookie "" --lat 32.22 --lng -110.97 --json locs.json --csv locs.csv --map map.html``` ## Sample Usage with `instagram-scraper` The ID list generated with the `--ids` flag can be passed into `instagram-scraper` to pull down image metadata. @@ -53,7 +53,7 @@ The ID list generated with the `--ids` flag can be passed into `instagram-scrape First, get the proximal location IDs of your target location: ```sh -python3 instagram-locations.py --session "" --lat --lng --ids location_ids.txt +python3 instagram-locations.py --cookies "" --lat --lng --ids location_ids.txt ``` Be sure to install `instagram-scraper`: @@ -72,7 +72,9 @@ Now use `instagram-scraper` to pull down all the photos at those locations: instagram-scraper @creds.txt --filename @location_ids.txt --location --include-location --destination ``` -## Getting an Instagram session ID +## Getting Instagram cookies + +This now requires the entire cookie string, in the format of an HTTP request header. Details TK. __Important: an Instagram session ID should be treated like a password — it provides full access to the Instagram account. Using this session ID in multiple places or on multiple computers may trigger Instagram to invalidate all session IDs. Using this session ID for any purpose other than the official Instagram website or application may be a violation of the Instagram Terms of Service and could lead to account suspension.__ @@ -80,6 +82,11 @@ __Important: an Instagram session ID should be treated like a password — it pr 2. Right click on the page and press "Inspect" to bring up the Chrome Developer Tools. 3. Click the "Application" tab in the Developer Tools Box. 4. Under "Cookies" select "https://www.instagram.com." -5. The value next to "sessionid" is your Instagram session ID. - ![Finding the Instagram cookie](docs/cookies.jpg) + +5. Right click on any item and click "Show Requests With This Cookie". +6. Click on any request. In the "Headers" tab, scroll down to "Request Headers". + +![Finding the full cookie string](docs/cookies2.png) + +7. Copy all text after "cookie: ". This is your cookie string. Replace `` with this value when running `instagram-location-search`. diff --git a/docs/cookies2.png b/docs/cookies2.png new file mode 100644 index 0000000..ce3fc58 Binary files /dev/null and b/docs/cookies2.png differ diff --git a/instagram-locations.py b/instagram-locations.py index 9a65407..4323bac 100644 --- a/instagram-locations.py +++ b/instagram-locations.py @@ -179,7 +179,7 @@ html_template = """ def main(): parser = argparse.ArgumentParser(description="Get a list of Instagram locations near a lat/lng") - parser.add_argument("--session", action="store", dest="session") + parser.add_argument("--cookie", action="store", dest="cookie") parser.add_argument("--json", action="store", dest="output") parser.add_argument("--geojson", action="store", dest="geojson") parser.add_argument("--map", action="store", dest="map") @@ -191,7 +191,7 @@ def main(): args = parser.parse_args() - cookie = "sessionid=" + args.session + cookie = args.cookie date_var = "" if args.date is not None: