├── docs ├── .nojekyll ├── objects.inv ├── _static │ ├── up.png │ ├── down.png │ ├── file.png │ ├── minus.png │ ├── plus.png │ ├── comment.png │ ├── up-pressed.png │ ├── ajax-loader.gif │ ├── down-pressed.png │ ├── comment-bright.png │ ├── comment-close.png │ ├── documentation_options.js │ ├── pygments.css │ ├── classic.css │ ├── sidebar.js │ ├── doctools.js │ ├── underscore.js │ ├── basic.css │ └── searchtools.js ├── .doctrees │ ├── index.doctree │ └── environment.pickle ├── _images │ ├── fov_example.jpg │ ├── pano_example.jpg │ ├── size_example.jpg │ ├── heading_example.jpg │ ├── multi_example.jpg │ ├── pitch_example.jpg │ ├── download_example.jpg │ ├── location_example.jpg │ └── panorama_example.jpg ├── source │ ├── img │ │ ├── fov_example.jpg │ │ ├── pano_example.jpg │ │ ├── size_example.jpg │ │ ├── multi_example.jpg │ │ ├── pitch_example.jpg │ │ ├── download_example.JPG │ │ ├── heading_example.jpg │ │ ├── location_example.jpg │ │ └── panorama_example.jpg │ ├── conf.py │ └── index.rst ├── .buildinfo ├── searchindex.js ├── _modules │ ├── index.html │ ├── helpers.html │ ├── cli.html │ └── api.html ├── search.html ├── py-modindex.html ├── genindex.html └── _sources │ └── index.rst.txt ├── google_streetview ├── tests │ ├── __init__.py │ ├── test_helpers.py │ ├── test_api_results.py │ └── test_cli.py ├── __main__.py ├── config.json ├── __init__.py ├── helpers.py ├── cli.py └── api.py ├── google_streetview.py ├── .travis.yml ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── setup.py ├── LICENSE ├── CONTRIBUTING.rst ├── .gitignore ├── NOTES.rst └── README.md /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /google_streetview/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /docs/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/objects.inv -------------------------------------------------------------------------------- /docs/_static/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_static/up.png -------------------------------------------------------------------------------- /docs/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_static/down.png -------------------------------------------------------------------------------- /docs/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_static/file.png -------------------------------------------------------------------------------- /docs/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_static/minus.png -------------------------------------------------------------------------------- /docs/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_static/plus.png -------------------------------------------------------------------------------- /google_streetview/__main__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .cli import run 4 | 5 | run() 6 | -------------------------------------------------------------------------------- /docs/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_static/comment.png -------------------------------------------------------------------------------- /docs/_static/up-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_static/up-pressed.png -------------------------------------------------------------------------------- /docs/.doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/.doctrees/index.doctree -------------------------------------------------------------------------------- /docs/_images/fov_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_images/fov_example.jpg -------------------------------------------------------------------------------- /docs/_images/pano_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_images/pano_example.jpg -------------------------------------------------------------------------------- /docs/_images/size_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_images/size_example.jpg -------------------------------------------------------------------------------- /docs/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_static/ajax-loader.gif -------------------------------------------------------------------------------- /docs/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_static/down-pressed.png -------------------------------------------------------------------------------- /docs/_images/heading_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_images/heading_example.jpg -------------------------------------------------------------------------------- /docs/_images/multi_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_images/multi_example.jpg -------------------------------------------------------------------------------- /docs/_images/pitch_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_images/pitch_example.jpg -------------------------------------------------------------------------------- /docs/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_static/comment-bright.png -------------------------------------------------------------------------------- /docs/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_static/comment-close.png -------------------------------------------------------------------------------- /docs/source/img/fov_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/source/img/fov_example.jpg -------------------------------------------------------------------------------- /docs/source/img/pano_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/source/img/pano_example.jpg -------------------------------------------------------------------------------- /docs/source/img/size_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/source/img/size_example.jpg -------------------------------------------------------------------------------- /docs/.doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/.doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/_images/download_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_images/download_example.jpg -------------------------------------------------------------------------------- /docs/_images/location_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_images/location_example.jpg -------------------------------------------------------------------------------- /docs/_images/panorama_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/_images/panorama_example.jpg -------------------------------------------------------------------------------- /docs/source/img/multi_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/source/img/multi_example.jpg -------------------------------------------------------------------------------- /docs/source/img/pitch_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/source/img/pitch_example.jpg -------------------------------------------------------------------------------- /google_streetview/config.json: -------------------------------------------------------------------------------- 1 | {"size": "640x640", "fov": "90", "pitch": "0", "option_silent": "false", "option_preview": "10"} -------------------------------------------------------------------------------- /docs/source/img/download_example.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/source/img/download_example.JPG -------------------------------------------------------------------------------- /docs/source/img/heading_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/source/img/heading_example.jpg -------------------------------------------------------------------------------- /docs/source/img/location_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/source/img/location_example.jpg -------------------------------------------------------------------------------- /docs/source/img/panorama_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rrwen/google_streetview/HEAD/docs/source/img/panorama_example.jpg -------------------------------------------------------------------------------- /google_streetview.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from google_streetview.cli import run 5 | 6 | if __name__ == '__main__': 7 | run() 8 | -------------------------------------------------------------------------------- /docs/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: ead79e131aa5e7eda801dc77bf346a0f 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: '', 3 | VERSION: '1.2.9', 4 | LANGUAGE: 'None', 5 | COLLAPSE_INDEX: false, 6 | FILE_SUFFIX: '.html', 7 | HAS_SOURCE: true, 8 | SOURCELINK_SUFFIX: '.txt' 9 | }; -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "3.6" 5 | cache: pip 6 | install: 7 | - pip install git+https://github.com/rrwen/google_streetview 8 | - pip install coveralls 9 | script: 10 | - google_streetview -s key="AIzaSyDLzW6n52tcRTGboOOepiKelNVdLC9qSzA" 11 | - coverage run --source=google_streetview -m unittest 12 | - google_streetview -d 13 | after_success: 14 | - coveralls 15 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | This section details the purpose of the report such as bug issues, request for features, and other improvements, etc. 4 | 5 | ## Example 6 | 7 | The example section should provide steps, explanations, and/or code to: 8 | 9 | 1. Reproduce the issue 10 | 2. Demonstrate requested features 11 | 3. Explain improvements and other suggestions 12 | 13 | ## Notes 14 | 15 | The notes section provides any additional text that do not fit into the above sections. 16 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | The purpose can mention goals that include fixes to bugs, addition of features, and other improvements, etc. 4 | 5 | ## Summary 6 | 7 | This section should provide a short summary of the changes made such as improved speeds or features, and implementation details. 8 | 9 | ## Changes 10 | 11 | The changes are a list of general edits made to the files and their respective components such as: 12 | 13 | * `file_path1`: 14 | * `function_module_etc`: changed loop to map 15 | * `function_module_etc`: changed variable value 16 | * `file_path2`: 17 | * `function_module_etc`: changed loop to map 18 | * `function_module_etc`: changed variable value 19 | 20 | ## Notes 21 | 22 | The notes provide any additional text that do not fit into the above sections. 23 | -------------------------------------------------------------------------------- /google_streetview/tests/test_helpers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from google_streetview import helpers 4 | from unittest import TestCase 5 | 6 | class cliTest(TestCase): 7 | 8 | def test_api_list(self): 9 | apiargs = { 10 | 'location': '46.414382,10.013988', 11 | 'size': '640x300', 12 | 'heading': '0' 13 | } 14 | api_list = helpers.api_list(apiargs) 15 | self.assertTrue(1 == len(api_list)) 16 | 17 | def test_api_list_multi(self): 18 | apiargs = { 19 | 'location': '46.414382,10.013988;40.720032,-73.988354', 20 | 'size': '640x300;640x640', 21 | 'heading': '0;90;180;270', 22 | 'fov': '0;90;120', 23 | 'pitch': '-90;0;90' 24 | } 25 | api_list = helpers.api_list(apiargs) 26 | self.assertTrue(144 == len(api_list)) 27 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from setuptools import setup 4 | 5 | import google_streetview as package 6 | 7 | def readme(): 8 | with open('README.md') as f: 9 | return ''.join(f.readlines()) 10 | 11 | setup( 12 | name=package.__name__, 13 | version=package.__version__, 14 | description=package.__description__, 15 | long_description=readme(), 16 | long_description_content_type=package.__long_description_content_type__, 17 | author=package.__author__, 18 | author_email=package.__email__, 19 | license=package.__license__, 20 | url=package.__url__, 21 | download_url=package.__download_url__, 22 | keywords =package. __keywords__, 23 | entry_points=package.__entry_points__, 24 | packages=package.__packages__, 25 | package_data=package.__package_data__, 26 | install_requires=package.__install_requires__ 27 | ) 28 | -------------------------------------------------------------------------------- /google_streetview/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | __name__ = 'google_streetview' 4 | __author__ = 'Richard Wen' 5 | __email__ = 'rrwen.dev@gmail.com' 6 | __version__ = '1.2.9' 7 | __license__ = 'MIT' 8 | __description__ = 'A command line tool and module for Google Street View Image API.' 9 | __long_description_content_type__='text/markdown' 10 | __keywords__ = [ 11 | 'google', 12 | 'api', 13 | 'street', 14 | 'view', 15 | 'streetview', 16 | 'image', 17 | 'map', 18 | 'address', 19 | 'location', 20 | 'road', 21 | 'route', 22 | 'city', 23 | 'panorama', 24 | 'photo', 25 | 'cli', 26 | 'command', 27 | 'line', 28 | 'interface', 29 | 'tool', 30 | 'module'] 31 | __url__ = 'https://github.com/rrwen/google_streetview' 32 | __download_url__ = 'https://github.com/rrwen/google_streetview/archive/master.zip' 33 | __install_requires__ = [ 34 | 'kwconfig', 35 | 'requests' 36 | ] 37 | __packages__ = ['google_streetview'] 38 | __package_data__ = {'google_streetview': ['config.json']} 39 | __entry_points__ = {'console_scripts': ['google_streetview=google_streetview.cli:run']} 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 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 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | Contributions 2 | ------------- 3 | 4 | Report Contributions 5 | ******************** 6 | 7 | Reports for issues and suggestions can be made using the `issue submission `_ interface. 8 | 9 | When possible, ensure that your submission is: 10 | 11 | * **Descriptive**: has informative title, explanations, and screenshots 12 | * **Specific**: has details of environment (such as operating system and hardware) and software used 13 | * **Reproducible**: has steps, code, and examples to reproduce the issue 14 | 15 | A template of a report contribution is provided in `ISSUE_TEMPLATE.md `_. 16 | 17 | Code Contributions 18 | ****************** 19 | 20 | Code contributions are submitted via `pull requests `_: 21 | 22 | 1. Ensure that you pass the `Tests `_ 23 | 2. Create a new `pull request `_ 24 | 3. Provide an explanation of the changes 25 | 26 | A template of a code contribution is provided in `PULL_REQUEST_TEMPLATE.md `_. 27 | 28 | For more information, see `Developer Install `_ and `Implementation `_. 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | -------------------------------------------------------------------------------- /google_streetview/tests/test_api_results.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from os import listdir, remove 4 | from os.path import isdir, isfile 5 | from pkg_resources import resource_filename, Requirement 6 | from unittest import TestCase 7 | from shutil import rmtree 8 | from tempfile import TemporaryFile, TemporaryDirectory 9 | 10 | import google_streetview.api 11 | import json 12 | 13 | class apiTest(TestCase): 14 | 15 | def setUp(self): 16 | file_path = resource_filename(Requirement.parse('google_streetview'), 'google_streetview/config.json') 17 | with open(file_path, 'r') as in_file: 18 | defaults = json.load(in_file) 19 | params = [{ 20 | 'size': '600x300', # max 640x640 pixels 21 | 'location': '46.414382,10.013988', 22 | 'heading': '151.78', 23 | 'pitch': '-0.76', 24 | 'key': defaults['key'] 25 | }] 26 | self.results = google_streetview.api.results(params) 27 | tempfile = TemporaryFile() 28 | self.tempfile = str(tempfile.name) 29 | tempfile.close() 30 | self.tempdir = str(TemporaryDirectory().name) 31 | 32 | def test_preview(self): 33 | results = self.results 34 | expected = None 35 | self.assertTrue(expected == results.preview()) 36 | 37 | def test_download_links(self): 38 | self.results.download_links(self.tempdir) 39 | nfiles = len(listdir(self.tempdir)) 40 | rmtree(self.tempdir) 41 | self.assertTrue(nfiles > 0) 42 | 43 | def test_metadata_status_ok(self): 44 | status = self.results.metadata[0]['status'] 45 | expected = 'OK' 46 | self.assertTrue(status == expected) 47 | 48 | def test_save_links(self): 49 | results = self.results 50 | results.save_links(self.tempfile) 51 | with open(self.tempfile, 'r') as f: 52 | nlinks = len(f.readlines()) 53 | self.assertTrue(nlinks == 1) 54 | 55 | def test_save_metadata(self): 56 | results = self.results 57 | results.save_metadata(self.tempfile) 58 | with open(self.tempfile, 'r') as f: 59 | metadata = json.load(f) 60 | self.assertTrue(metadata == results.metadata) 61 | 62 | def tearDown(self): 63 | if isfile(self.tempfile): 64 | remove(self.tempfile) 65 | if isdir(self.tempdir): 66 | rmtree(self.tempdir) 67 | 68 | -------------------------------------------------------------------------------- /google_streetview/tests/test_cli.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from os import listdir, makedirs, remove 4 | from os.path import isdir, isfile 5 | from google_streetview.cli import run 6 | from shutil import rmtree 7 | from tempfile import TemporaryFile, TemporaryDirectory 8 | from unittest import TestCase 9 | 10 | import json 11 | 12 | class cliTest(TestCase): 13 | 14 | def setUp(self): 15 | tempfile = TemporaryFile() 16 | self.tempfile = str(tempfile.name) 17 | tempfile.close() 18 | self.tempdir = str(TemporaryDirectory().name) 19 | 20 | def test_search_location(self): 21 | argv = [ 22 | 'cli.py', 23 | '--location=46.414382,10.013988' 24 | ] 25 | run(argv) 26 | 27 | def test_search_location_multi(self): 28 | argv = [ 29 | 'cli.py', 30 | '--location=46.414382,10.013988;40.720032,-73.988354' 31 | ] 32 | run(argv) 33 | 34 | def test_search_pano(self): 35 | argv = [ 36 | 'cli.py', 37 | '--pano=vPnURflnc8AZu5NMLYRddw' 38 | ] 39 | run(argv) 40 | 41 | def test_search_pano_multi(self): 42 | argv = [ 43 | 'cli.py', 44 | '--pano=vPnURflnc8AZu5NMLYRddw;A1v2IdX_6HKnIQa2SPyyAg' 45 | ] 46 | run(argv) 47 | 48 | def test_camera_multi(self): 49 | argv = [ 50 | 'cli.py', 51 | '--pano=vPnURflnc8AZu5NMLYRddw;A1v2IdX_6HKnIQa2SPyyAg', 52 | '--size=640x300', 53 | '--heading=0;90;180;270', 54 | '--fov=90', 55 | '--pitch=0' 56 | ] 57 | run(argv) 58 | 59 | def test_save_links(self): 60 | argv = [ 61 | 'cli.py', 62 | '--location=46.414382,10.013988', 63 | '--save_links=' + self.tempfile 64 | ] 65 | run(argv) 66 | 67 | def test_save_metadata(self): 68 | argv = [ 69 | 'cli.py', 70 | '--location=46.414382,10.013988', 71 | '--save_metadata=' + self.tempfile 72 | ] 73 | run(argv) 74 | 75 | def test_download_links(self): 76 | argv = [ 77 | 'cli.py', 78 | '--location=46.414382,10.013988', 79 | '--save_downloads=' + str(self.tempdir) 80 | ] 81 | run(argv) 82 | 83 | def tearDown(self): 84 | if isfile(self.tempfile): 85 | remove(self.tempfile) 86 | if isdir(self.tempdir): 87 | rmtree(self.tempdir) 88 | 89 | -------------------------------------------------------------------------------- /NOTES.rst: -------------------------------------------------------------------------------- 1 | Developer Notes 2 | --------------- 3 | 4 | Developer Install 5 | ***************** 6 | 7 | Install the latest developer version with ``pip`` from github:: 8 | 9 | pip install git+https://github.com/rrwen/google_streetview 10 | 11 | Install from ``git`` cloned source: 12 | 13 | 1. Ensure `git `__ is installed 14 | 2. Clone into current path 15 | 3. Install via ``pip`` 16 | 17 | :: 18 | 19 | git clone https://github.com/rrwen/google_streetview 20 | cd google_streetview 21 | pip install . -I 22 | 23 | Tests 24 | ***** 25 | 26 | 1. Clone into current path ``git clone https://github.com/rrwen/google_streetview`` 27 | 2. Enter into folder ``cd google_streetview`` 28 | 3. Ensure `unittest `_ is available 29 | 4. Set your `Google API developer key `__ 30 | 5. Run tests 31 | 6. Reset config file to defaults 32 | 7. Please note that this will use up 16 requests from your quota 33 | 34 | :: 35 | 36 | pip install . -I 37 | python -m google_streetview -s key=your_dev_key 38 | python -m unittest 39 | python -m google_streetview -d 40 | 41 | Documentation Maintenance 42 | ************************* 43 | 44 | 1. Ensure `sphinx `__ is installed ``pip install -U sphinx`` 45 | 2. Update the documentation in ``docs/`` 46 | 47 | :: 48 | 49 | pip install . -I 50 | sphinx-build -b html docs/source docs 51 | 52 | Upload to github 53 | **************** 54 | 55 | 1. Ensure `git `__ is installed 56 | 2. Add all files and commit changes 57 | 3. Push to github 58 | 59 | :: 60 | 61 | git add . 62 | git commit -a -m "Generic update" 63 | git push 64 | 65 | Upload to PyPi 66 | ************** 67 | 68 | 1. Ensure `twine `_ is installed ``pip install twine`` 69 | 2. Ensure `sphinx `__ is installed ``pip install -U sphinx`` 70 | 3. Run tests and check for OK status 71 | 4. Delete ``dist`` directory 72 | 5. Update the version ``google_streetview/__init__.py`` 73 | 6. Update the documentation in ``docs/`` 74 | 7. Create source distribution 75 | 8. Upload to `PyPi `_ 76 | 77 | :: 78 | 79 | pip install . -I 80 | python -m google_streetview -s key=your_dev_key 81 | python -m unittest 82 | python -m google_streetview -d 83 | sphinx-build -b html docs/source docs 84 | python setup.py sdist 85 | twine upload dist/* -------------------------------------------------------------------------------- /google_streetview/helpers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from itertools import product 4 | 5 | import requests 6 | import shutil 7 | 8 | def api_list(apiargs): 9 | """Google Street View Image API results. 10 | 11 | Constructs a list of `Google Street View Image API queries `_ 12 | from a dictionary. 13 | 14 | Args: 15 | apiargs (listof dict): 16 | Dict containing `street view URL parameters `_. 17 | Each parameter can have multiple values if separated by ``;``. 18 | 19 | Returns: 20 | A ``listof dict`` containing single query requests per dictionary for Google Street View Image API. 21 | 22 | Examples: 23 | :: 24 | 25 | # Import google_streetview for the api and helper module 26 | import google_streetview.api 27 | import google_streetview.helpers 28 | 29 | # Create a dictionary with multiple parameters separated by ; 30 | apiargs = { 31 | 'location': '46.414382,10.013988;40.720032,-73.988354', 32 | 'size': '640x300;640x640', 33 | 'heading': '0;90;180;270', 34 | 'fov': '0;90;120', 35 | 'pitch': '-90;0;90' 36 | } 37 | 38 | # Get a list of all possible queries from multiple parameters 39 | api_list = google_streetview.helpers.api_list(apiargs) 40 | 41 | # Create a results object for all possible queries 42 | results = google_streetview.api.results(api_list) 43 | 44 | # Preview results 45 | results.preview() 46 | 47 | # Download images to directory 'downloads' 48 | results.download_links('downloads') 49 | 50 | # Save metadata 51 | results.save_metadata('metadata.json') 52 | """ 53 | 54 | # (api_query) Query combinations for each parameter 55 | api_queries = {} 56 | keywords = [k for k in apiargs] 57 | for k in keywords: 58 | if k in apiargs: 59 | api_queries[k] = apiargs[k].split(';') 60 | apiargs.pop(k, None) 61 | 62 | # (api_list) Build list of api requests based on query combinations 63 | out = [] 64 | keys = [k for k in api_queries] 65 | queries = [api_queries[k] for k in api_queries] 66 | combinations = product(*queries) 67 | for combo in combinations: 68 | api_copy = apiargs.copy() 69 | for k, parameter in zip(keys, combo): 70 | api_copy[k] = parameter 71 | out.append(api_copy) 72 | return(out) 73 | 74 | def download(url, file_path): 75 | r = requests.get(url, stream=True) 76 | if r.status_code == 200: # if request is successful 77 | with open(file_path, 'wb') as f: 78 | r.raw.decode_content = True 79 | shutil.copyfileobj(r.raw, f) 80 | -------------------------------------------------------------------------------- /docs/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({docnames:["index"],envversion:53,filenames:["index.rst"],objects:{"":{api:[0,0,0,"-"]},"api.results":{download_links:[0,2,1,""],preview:[0,2,1,""],save_links:[0,2,1,""],save_metadata:[0,2,1,""]},api:{results:[0,1,1,""]},cli:{run:[0,3,1,""]},helpers:{api_list:[0,3,1,""]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:function"},terms:{"200x200":0,"600x300":0,"640x300":0,"640x640":0,"class":0,"function":0,"int":0,"long":0,"new":0,"return":0,"true":0,For:0,The:0,These:0,Uses:0,__entry_points__:0,__init__:0,__main__:0,__name__:0,a1v2idx_6hkniqa2spyyag:0,access:0,account:0,adjust:0,after:0,again:0,all:0,also:0,anaconda3:0,angl:0,api_list:0,apiarg:0,applic:0,arg:0,argv:0,ask:0,attribut:0,avail:0,batch:0,below:0,bill:0,build:0,build_developerkei:0,call:0,camera:0,can:0,cat:0,chang:0,click:0,close:0,colon:0,com:0,command:0,complet:0,consol:0,console_script:0,construct:0,contain:0,creat:0,credenti:0,custom:0,date:0,defin:0,degre:0,depend:0,detail:0,dev:0,develop:0,dict:0,dictionari:0,digit:0,dir_path:0,directori:0,distribut:0,doc:0,down:0,download:0,download_link:0,each:0,east:0,enabl:0,ensur:0,even:0,everi:0,exampl:0,execut:0,extens:0,field:0,file:0,file_path:0,folder:0,follow:0,fov:0,from:0,get:0,given:0,gmail:0,googleapi:0,have:0,head:0,header:0,height:0,help:0,horizont:0,html:0,http:0,ids:0,imageri:0,increas:0,indic:0,input:0,insid:0,instruct:0,intend:0,interfac:0,json:0,kei:0,kheader:0,latitud:0,level:0,line:0,link:0,list:0,listof:0,locat:0,longitud:0,mai:0,map:0,march:0,max:0,maximum:0,metadata:0,metadata_fil:0,metadata_link:0,metadata_statu:0,more:0,must:0,name:0,neg:0,north:0,note:0,num:0,number:0,object:0,off:0,option:0,option_preview:0,option_sil:0,packag:0,pano:0,pano_id:0,panorama:0,param:0,paramet:0,paramt:0,pass:0,path:0,per:0,persist:0,pip:0,pitch:0,pixel:0,plan:0,pleas:0,posit:0,possibl:0,preview:0,print:0,program:0,provid:0,python:0,queri:0,ref_:0,refer:0,remov:0,replac:0,repres:0,request:0,requir:0,reset:0,respons:0,richard:0,rrwen:0,run:0,same:0,save_download:0,save_link:0,save_metadata:0,scale:0,script:0,search_result:0,searchtyp:0,section:0,see:0,seen:0,semi:0,separ:0,set:0,shown:0,sign:0,signatur:0,singl:0,site:0,site_api:0,site_metadata:0,size:0,sourc:0,south:0,specifi:0,sphinx:0,statu:0,status_ok:0,str:0,straight:0,street:0,streetview:0,subject:0,termin:0,text:0,thei:0,thi:0,tool:0,turn:0,txt:0,url:0,use:0,used:0,user:0,using:0,valu:0,via:0,view:0,vision:0,vpnurflnc8azu5nmlyrdd:0,vpnurflnc8azu5nmlyrddw:0,websit:0,wen:0,were:0,west:0,when:0,whenev:0,where:0,which:0,width:0,window:0,without:0,written:0,your:0,your_cx_id:0,your_dev_kei:0,your_signatur:0,yourdevkei:0,zoom:0},titles:["google_streetview"],titleterms:{"default":0,"import":0,addit:0,api:0,argument:0,cli:0,googl:0,google_streetview:0,helper:0,imag:0,instal:0,modul:0,multipl:0,result:0,save:0,search:0,setup:0,usag:0}}) -------------------------------------------------------------------------------- /docs/_modules/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Overview: module code — google_streetview 1.2.9 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 31 | 32 |
33 |
34 |
35 |
36 | 37 |

All modules for which code is available

38 | 42 | 43 |
44 |
45 |
46 | 62 |
63 |
64 | 76 | 80 | 81 | -------------------------------------------------------------------------------- /docs/search.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Search — google_streetview 1.2.9 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 39 | 40 |
41 |
42 |
43 |
44 | 45 |

Search

46 |
47 | 48 |

49 | Please activate JavaScript to enable the search 50 | functionality. 51 |

52 |
53 |

54 | From here you can search these documents. Enter your search 55 | words into the box below and click "search". Note that the search 56 | function will automatically search for all of the words. Pages 57 | containing fewer words won't appear in the result list. 58 |

59 |
60 | 61 | 62 | 63 |
64 | 65 |
66 | 67 |
68 | 69 |
70 |
71 |
72 | 76 |
77 |
78 | 90 | 94 | 95 | -------------------------------------------------------------------------------- /docs/py-modindex.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | Python Module Index — google_streetview 1.2.9 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 38 | 39 |
40 |
41 |
42 |
43 | 44 | 45 |

Python Module Index

46 | 47 |
48 | a 49 |
50 | 51 | 52 | 53 | 55 | 56 | 57 | 60 |
 
54 | a
58 | api 59 |
61 | 62 | 63 |
64 |
65 |
66 | 82 |
83 |
84 | 96 | 100 | 101 | -------------------------------------------------------------------------------- /docs/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #eeffcc; } 3 | .highlight .c { color: #408090; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ 8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 9 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ 11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 14 | .highlight .ge { font-style: italic } /* Generic.Emph */ 15 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 18 | .highlight .go { color: #333333 } /* Generic.Output */ 19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 20 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 28 | .highlight .kt { color: #902000 } /* Keyword.Type */ 29 | .highlight .m { color: #208050 } /* Literal.Number */ 30 | .highlight .s { color: #4070a0 } /* Literal.String */ 31 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 32 | .highlight .nb { color: #007020 } /* Name.Builtin */ 33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 34 | .highlight .no { color: #60add5 } /* Name.Constant */ 35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 37 | .highlight .ne { color: #007020 } /* Name.Exception */ 38 | .highlight .nf { color: #06287e } /* Name.Function */ 39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */ 46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 50 | .highlight .sa { color: #4070a0 } /* Literal.String.Affix */ 51 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 52 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 53 | .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ 54 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 55 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 56 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 57 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 58 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 59 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 60 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 61 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 62 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 63 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 64 | .highlight .fm { color: #06287e } /* Name.Function.Magic */ 65 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 66 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 67 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 68 | .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ 69 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # google_streetview 2 | 3 | Richard Wen 4 | rrwen.dev@gmail.com 5 | 6 | * [Documentation](https://rrwen.github.io/google_streetview) 7 | 8 | A command line tool and module for Google Street View Image API. 9 | 10 | 11 | [![pypi version](https://badge.fury.io/py/google-streetview.svg)](https://badge.fury.io/py/google-streetview) 12 | [![Build Status](https://travis-ci.org/rrwen/google_streetview.svg?branch=master)](https://travis-ci.org/rrwen/google_streetview) 13 | [![Coverage Status](https://coveralls.io/repos/github/rrwen/google_streetview/badge.svg?branch=master)](https://coveralls.io/github/rrwen/google_streetview?branch=master) 14 | [![Stars](https://img.shields.io/github/stars/rrwen/google_streetview.svg)](https://github.com/google_streetview/stargazers) 15 | [![GitHub license](https://img.shields.io/github/license/rrwen/google_streetview.svg)](https://github.com/rrwen/google_streetview/blob/master/LICENSE) 16 | [![Donarbox Donate](https://img.shields.io/badge/donate-Donarbox-yellow.svg)](https://donorbox.org/rrwen) 17 | [![PayPal Donate](https://img.shields.io/badge/donate-PayPal-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=NQNSAHK5X46D2) 18 | [![Twitter](https://img.shields.io/twitter/url/https/github.com/rrwen/google_streetview.svg?style=social)](https://twitter.com/intent/tweet?text=A%20command%20line%20tool%20and%20module%20for%20Google%20Street%20View%20Image%20API:%20https://github.com/rrwen/google_streetview%20%23python%20%23pip) 19 | 20 | **Note**: Google changed [StreetView API pricing](https://developers.google.com/maps/documentation/streetview/usage-and-billing) and a billing plan may be required (checked March 5, 2019). 21 | 22 | ## Install 23 | 24 | 1. Install [Python](https://www.python.org/downloads/) 25 | 2. Install [google_streetview](https://pypi.python.org/pypi/google-streetview) via `pip` 26 | 27 | ``` 28 | pip install google_streetview 29 | ``` 30 | 31 | For the latest developer version, see [Developer Install](https://github.com/rrwen/google_streetview/blob/master/NOTES.rst#developer-install). 32 | 33 | ## Usage 34 | 35 | For help in the console: 36 | 37 | ``` 38 | google_streetview -h 39 | ``` 40 | 41 | Ensure that a [Google API developer key](https://developers.google.com/api-client-library/python/auth/api-keys) is set: 42 | 43 | ``` 44 | google_streetview -s key="your_dev_key" 45 | ``` 46 | 47 | Search street view for latitude and longitude `46.414382,10.013988`: 48 | 49 | ``` 50 | google_streetview "46.414382,10.013988" 51 | ``` 52 | 53 | Save images to a directory: 54 | 55 | ``` 56 | google_streetview --location="46.414382,10.013988" --save_downloads=downloads 57 | ``` 58 | 59 | Obtain a 360 panorama by rotating the camera ``heading`` given a 90 degree field of vision `fov`:: 60 | 61 | ``` 62 | google_streetview --location="46.414382,10.013988" --fov=90 --heading=0;90;180;270 63 | ``` 64 | 65 | Use as a Python module: 66 | 67 | ```python 68 | 69 | # Import google_streetview for the api module 70 | import google_streetview.api 71 | 72 | # Define parameters for street view api 73 | params = [{ 74 | 'size': '600x300', # max 640x640 pixels 75 | 'location': '46.414382,10.013988', 76 | 'heading': '151.78', 77 | 'pitch': '-0.76', 78 | 'key': 'your_dev_key' 79 | }] 80 | 81 | # Create a results object 82 | results = google_streetview.api.results(params) 83 | 84 | # Download images to directory 'downloads' 85 | results.download_links('downloads') 86 | ``` 87 | 88 | For more usage details, see the [Documentation](https://rrwen.github.io/google_streetview). 89 | 90 | ## Contributions 91 | 92 | 1. Reports for issues and suggestions can be made using the [issue submission](https://github.com/rrwen/google_streetview/issues) 93 | 2. Code contributions are submitted via [pull requests](https://github.com/rrwen/google_streetview/pulls) 94 | 95 | See [CONTRIBUTING.rst](https://github.com/rrwen/google_streetview/blob/master/CONTRIBUTING.rst) for more details. 96 | 97 | ## Implementation 98 | 99 | The package [google_streetview](https://pypi.python.org/pypi/google-streetview) uses the following components: 100 | 101 | | Component | Purpose | 102 | |----------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| 103 | | [Google Street View Image API](https://developers.google.com/maps/documentation/streetview) | API for Google Street View images | 104 | | [google_streetview.api](https://github.com/rrwen/google_streetview/blob/master/google_streetview/api.py) | Module for interfacing with Google Street View Image API using requests | 105 | | [requests](https://pypi.python.org/pypi/requests) | Download and get URLs from Google Street View Image API | 106 | 107 | ``` 108 | 109 | Google Street View Image API <-- API for Street View Images 110 | | 111 | google_streetview.api <-- URL Request with query string 112 | | 113 | request <-- Download URLs and images 114 | ``` 115 | For more information, see [NOTES.rst](https://github.com/rrwen/google_streetview/blob/master/NOTES.rst). 116 | -------------------------------------------------------------------------------- /docs/_static/classic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * classic.css_t 3 | * ~~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- classic theme. 6 | * 7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | @import url("basic.css"); 13 | 14 | /* -- page layout ----------------------------------------------------------- */ 15 | 16 | body { 17 | font-family: sans-serif; 18 | font-size: 100%; 19 | background-color: #11303d; 20 | color: #000; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | div.document { 26 | background-color: #1c4e63; 27 | } 28 | 29 | div.documentwrapper { 30 | float: left; 31 | width: 100%; 32 | } 33 | 34 | div.bodywrapper { 35 | margin: 0 0 0 230px; 36 | } 37 | 38 | div.body { 39 | background-color: #ffffff; 40 | color: #000000; 41 | padding: 0 20px 30px 20px; 42 | } 43 | 44 | div.footer { 45 | color: #ffffff; 46 | width: 100%; 47 | padding: 9px 0 9px 0; 48 | text-align: center; 49 | font-size: 75%; 50 | } 51 | 52 | div.footer a { 53 | color: #ffffff; 54 | text-decoration: underline; 55 | } 56 | 57 | div.related { 58 | background-color: #133f52; 59 | line-height: 30px; 60 | color: #ffffff; 61 | } 62 | 63 | div.related a { 64 | color: #ffffff; 65 | } 66 | 67 | div.sphinxsidebar { 68 | } 69 | 70 | div.sphinxsidebar h3 { 71 | font-family: 'Trebuchet MS', sans-serif; 72 | color: #ffffff; 73 | font-size: 1.4em; 74 | font-weight: normal; 75 | margin: 0; 76 | padding: 0; 77 | } 78 | 79 | div.sphinxsidebar h3 a { 80 | color: #ffffff; 81 | } 82 | 83 | div.sphinxsidebar h4 { 84 | font-family: 'Trebuchet MS', sans-serif; 85 | color: #ffffff; 86 | font-size: 1.3em; 87 | font-weight: normal; 88 | margin: 5px 0 0 0; 89 | padding: 0; 90 | } 91 | 92 | div.sphinxsidebar p { 93 | color: #ffffff; 94 | } 95 | 96 | div.sphinxsidebar p.topless { 97 | margin: 5px 10px 10px 10px; 98 | } 99 | 100 | div.sphinxsidebar ul { 101 | margin: 10px; 102 | padding: 0; 103 | color: #ffffff; 104 | } 105 | 106 | div.sphinxsidebar a { 107 | color: #98dbcc; 108 | } 109 | 110 | div.sphinxsidebar input { 111 | border: 1px solid #98dbcc; 112 | font-family: sans-serif; 113 | font-size: 1em; 114 | } 115 | 116 | 117 | 118 | /* -- hyperlink styles ------------------------------------------------------ */ 119 | 120 | a { 121 | color: #355f7c; 122 | text-decoration: none; 123 | } 124 | 125 | a:visited { 126 | color: #355f7c; 127 | text-decoration: none; 128 | } 129 | 130 | a:hover { 131 | text-decoration: underline; 132 | } 133 | 134 | 135 | 136 | /* -- body styles ----------------------------------------------------------- */ 137 | 138 | div.body h1, 139 | div.body h2, 140 | div.body h3, 141 | div.body h4, 142 | div.body h5, 143 | div.body h6 { 144 | font-family: 'Trebuchet MS', sans-serif; 145 | background-color: #f2f2f2; 146 | font-weight: normal; 147 | color: #20435c; 148 | border-bottom: 1px solid #ccc; 149 | margin: 20px -20px 10px -20px; 150 | padding: 3px 0 3px 10px; 151 | } 152 | 153 | div.body h1 { margin-top: 0; font-size: 200%; } 154 | div.body h2 { font-size: 160%; } 155 | div.body h3 { font-size: 140%; } 156 | div.body h4 { font-size: 120%; } 157 | div.body h5 { font-size: 110%; } 158 | div.body h6 { font-size: 100%; } 159 | 160 | a.headerlink { 161 | color: #c60f0f; 162 | font-size: 0.8em; 163 | padding: 0 4px 0 4px; 164 | text-decoration: none; 165 | } 166 | 167 | a.headerlink:hover { 168 | background-color: #c60f0f; 169 | color: white; 170 | } 171 | 172 | div.body p, div.body dd, div.body li, div.body blockquote { 173 | text-align: justify; 174 | line-height: 130%; 175 | } 176 | 177 | div.admonition p.admonition-title + p { 178 | display: inline; 179 | } 180 | 181 | div.admonition p { 182 | margin-bottom: 5px; 183 | } 184 | 185 | div.admonition pre { 186 | margin-bottom: 5px; 187 | } 188 | 189 | div.admonition ul, div.admonition ol { 190 | margin-bottom: 5px; 191 | } 192 | 193 | div.note { 194 | background-color: #eee; 195 | border: 1px solid #ccc; 196 | } 197 | 198 | div.seealso { 199 | background-color: #ffc; 200 | border: 1px solid #ff6; 201 | } 202 | 203 | div.topic { 204 | background-color: #eee; 205 | } 206 | 207 | div.warning { 208 | background-color: #ffe4e4; 209 | border: 1px solid #f66; 210 | } 211 | 212 | p.admonition-title { 213 | display: inline; 214 | } 215 | 216 | p.admonition-title:after { 217 | content: ":"; 218 | } 219 | 220 | pre { 221 | padding: 5px; 222 | background-color: #eeffcc; 223 | color: #333333; 224 | line-height: 120%; 225 | border: 1px solid #ac9; 226 | border-left: none; 227 | border-right: none; 228 | } 229 | 230 | code { 231 | background-color: #ecf0f3; 232 | padding: 0 1px 0 1px; 233 | font-size: 0.95em; 234 | } 235 | 236 | th { 237 | background-color: #ede; 238 | } 239 | 240 | .warning code { 241 | background: #efc2c2; 242 | } 243 | 244 | .note code { 245 | background: #d6d6d6; 246 | } 247 | 248 | .viewcode-back { 249 | font-family: sans-serif; 250 | } 251 | 252 | div.viewcode-block:target { 253 | background-color: #f4debf; 254 | border-top: 1px solid #ac9; 255 | border-bottom: 1px solid #ac9; 256 | } 257 | 258 | div.code-block-caption { 259 | color: #efefef; 260 | background-color: #1c4e63; 261 | } -------------------------------------------------------------------------------- /docs/_static/sidebar.js: -------------------------------------------------------------------------------- 1 | /* 2 | * sidebar.js 3 | * ~~~~~~~~~~ 4 | * 5 | * This script makes the Sphinx sidebar collapsible. 6 | * 7 | * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds 8 | * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton 9 | * used to collapse and expand the sidebar. 10 | * 11 | * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden 12 | * and the width of the sidebar and the margin-left of the document 13 | * are decreased. When the sidebar is expanded the opposite happens. 14 | * This script saves a per-browser/per-session cookie used to 15 | * remember the position of the sidebar among the pages. 16 | * Once the browser is closed the cookie is deleted and the position 17 | * reset to the default (expanded). 18 | * 19 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 20 | * :license: BSD, see LICENSE for details. 21 | * 22 | */ 23 | 24 | $(function() { 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | // global elements used by the functions. 34 | // the 'sidebarbutton' element is defined as global after its 35 | // creation, in the add_sidebar_button function 36 | var bodywrapper = $('.bodywrapper'); 37 | var sidebar = $('.sphinxsidebar'); 38 | var sidebarwrapper = $('.sphinxsidebarwrapper'); 39 | 40 | // for some reason, the document has no sidebar; do not run into errors 41 | if (!sidebar.length) return; 42 | 43 | // original margin-left of the bodywrapper and width of the sidebar 44 | // with the sidebar expanded 45 | var bw_margin_expanded = bodywrapper.css('margin-left'); 46 | var ssb_width_expanded = sidebar.width(); 47 | 48 | // margin-left of the bodywrapper and width of the sidebar 49 | // with the sidebar collapsed 50 | var bw_margin_collapsed = '.8em'; 51 | var ssb_width_collapsed = '.8em'; 52 | 53 | // colors used by the current theme 54 | var dark_color = $('.related').css('background-color'); 55 | var light_color = $('.document').css('background-color'); 56 | 57 | function sidebar_is_collapsed() { 58 | return sidebarwrapper.is(':not(:visible)'); 59 | } 60 | 61 | function toggle_sidebar() { 62 | if (sidebar_is_collapsed()) 63 | expand_sidebar(); 64 | else 65 | collapse_sidebar(); 66 | } 67 | 68 | function collapse_sidebar() { 69 | sidebarwrapper.hide(); 70 | sidebar.css('width', ssb_width_collapsed); 71 | bodywrapper.css('margin-left', bw_margin_collapsed); 72 | sidebarbutton.css({ 73 | 'margin-left': '0', 74 | 'height': bodywrapper.height() 75 | }); 76 | sidebarbutton.find('span').text('»'); 77 | sidebarbutton.attr('title', _('Expand sidebar')); 78 | document.cookie = 'sidebar=collapsed'; 79 | } 80 | 81 | function expand_sidebar() { 82 | bodywrapper.css('margin-left', bw_margin_expanded); 83 | sidebar.css('width', ssb_width_expanded); 84 | sidebarwrapper.show(); 85 | sidebarbutton.css({ 86 | 'margin-left': ssb_width_expanded-12, 87 | 'height': bodywrapper.height() 88 | }); 89 | sidebarbutton.find('span').text('«'); 90 | sidebarbutton.attr('title', _('Collapse sidebar')); 91 | document.cookie = 'sidebar=expanded'; 92 | } 93 | 94 | function add_sidebar_button() { 95 | sidebarwrapper.css({ 96 | 'float': 'left', 97 | 'margin-right': '0', 98 | 'width': ssb_width_expanded - 28 99 | }); 100 | // create the button 101 | sidebar.append( 102 | '
«
' 103 | ); 104 | var sidebarbutton = $('#sidebarbutton'); 105 | light_color = sidebarbutton.css('background-color'); 106 | // find the height of the viewport to center the '<<' in the page 107 | var viewport_height; 108 | if (window.innerHeight) 109 | viewport_height = window.innerHeight; 110 | else 111 | viewport_height = $(window).height(); 112 | sidebarbutton.find('span').css({ 113 | 'display': 'block', 114 | 'margin-top': (viewport_height - sidebar.position().top - 20) / 2 115 | }); 116 | 117 | sidebarbutton.click(toggle_sidebar); 118 | sidebarbutton.attr('title', _('Collapse sidebar')); 119 | sidebarbutton.css({ 120 | 'color': '#FFFFFF', 121 | 'border-left': '1px solid ' + dark_color, 122 | 'font-size': '1.2em', 123 | 'cursor': 'pointer', 124 | 'height': bodywrapper.height(), 125 | 'padding-top': '1px', 126 | 'margin-left': ssb_width_expanded - 12 127 | }); 128 | 129 | sidebarbutton.hover( 130 | function () { 131 | $(this).css('background-color', dark_color); 132 | }, 133 | function () { 134 | $(this).css('background-color', light_color); 135 | } 136 | ); 137 | } 138 | 139 | function set_position_from_cookie() { 140 | if (!document.cookie) 141 | return; 142 | var items = document.cookie.split(';'); 143 | for(var k=0; k 5 | 6 | 7 | 8 | 9 | 10 | Index — google_streetview 1.2.9 documentation 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 32 | 33 |
34 |
35 |
36 |
37 | 38 | 39 |

Index

40 | 41 |
42 | A 43 | | D 44 | | P 45 | | R 46 | | S 47 | 48 |
49 |

A

50 | 51 | 55 | 59 |
60 | 61 |

D

62 | 63 | 67 |
68 | 69 |

P

70 | 71 | 75 |
76 | 77 |

R

78 | 79 | 83 | 87 |
88 | 89 |

S

90 | 91 | 95 | 99 |
100 | 101 | 102 | 103 |
104 |
105 |
106 | 122 |
123 |
124 | 136 | 140 | 141 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # google_streetview documentation build configuration file, created by 5 | # sphinx-quickstart on Sun May 14 23:52:19 2017. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | # 20 | 21 | from datetime import datetime 22 | 23 | import os 24 | import sys 25 | sys.path.insert(0, os.path.abspath('../../google_streetview')) 26 | import google_streetview as package 27 | 28 | 29 | # -- General configuration ------------------------------------------------ 30 | 31 | # If your documentation needs a minimal Sphinx version, state it here. 32 | # 33 | # needs_sphinx = '1.0' 34 | 35 | # Add any Sphinx extension module names here, as strings. They can be 36 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 37 | # ones. 38 | extensions = ['sphinx.ext.autodoc', 39 | 'sphinx.ext.viewcode', 40 | 'sphinx.ext.githubpages'] 41 | 42 | # Add any paths that contain templates here, relative to this directory. 43 | templates_path = ['_templates'] 44 | 45 | # The suffix(es) of source filenames. 46 | # You can specify multiple suffix as a list of string: 47 | # 48 | # source_suffix = ['.rst', '.md'] 49 | source_suffix = '.rst' 50 | 51 | # The master toctree document. 52 | master_doc = 'index' 53 | 54 | # General information about the project. 55 | project = package.__name__ 56 | copyright = str(datetime.now().year) + ', ' + package.__author__ 57 | author = package.__author__ 58 | 59 | # The version info for the project you're documenting, acts as replacement for 60 | # |version| and |release|, also used in various other places throughout the 61 | # built documents. 62 | # 63 | # The short X.Y version. 64 | version = package.__version__ 65 | # The full version, including alpha/beta/rc tags. 66 | release = package.__version__ 67 | 68 | # The language for content autogenerated by Sphinx. Refer to documentation 69 | # for a list of supported languages. 70 | # 71 | # This is also used if you do content translation via gettext catalogs. 72 | # Usually you set "language" from the command line for these cases. 73 | language = None 74 | 75 | # List of patterns, relative to source directory, that match files and 76 | # directories to ignore when looking for source files. 77 | # This patterns also effect to html_static_path and html_extra_path 78 | exclude_patterns = [] 79 | 80 | # The name of the Pygments (syntax highlighting) style to use. 81 | pygments_style = 'sphinx' 82 | 83 | # If true, `todo` and `todoList` produce output, else they produce nothing. 84 | todo_include_todos = False 85 | 86 | 87 | # -- Options for HTML output ---------------------------------------------- 88 | 89 | # The theme to use for HTML and HTML Help pages. See the documentation for 90 | # a list of builtin themes. 91 | # 92 | html_theme = 'classic' 93 | 94 | # Theme options are theme-specific and customize the look and feel of a theme 95 | # further. For a list of options available for each theme, see the 96 | # documentation. 97 | # 98 | # html_theme_options = {} 99 | 100 | # Add any paths that contain custom static files (such as style sheets) here, 101 | # relative to this directory. They are copied after the builtin static files, 102 | # so a file named "default.css" will overwrite the builtin "default.css". 103 | html_static_path = ['_static'] 104 | 105 | 106 | # -- Options for HTMLHelp output ------------------------------------------ 107 | 108 | # Output file base name for HTML help builder. 109 | htmlhelp_basename = 'google_streetviewdoc' 110 | 111 | 112 | # -- Options for LaTeX output --------------------------------------------- 113 | 114 | latex_elements = { 115 | # The paper size ('letterpaper' or 'a4paper'). 116 | # 117 | # 'papersize': 'letterpaper', 118 | 119 | # The font size ('10pt', '11pt' or '12pt'). 120 | # 121 | # 'pointsize': '10pt', 122 | 123 | # Additional stuff for the LaTeX preamble. 124 | # 125 | # 'preamble': '', 126 | 127 | # Latex figure (float) alignment 128 | # 129 | # 'figure_align': 'htbp', 130 | } 131 | 132 | # Grouping the document tree into LaTeX files. List of tuples 133 | # (source start file, target name, title, 134 | # author, documentclass [howto, manual, or own class]). 135 | latex_documents = [ 136 | (master_doc, 'google_streetview.tex', 'google\\_streetview Documentation', 137 | package.__author__, 'manual'), 138 | ] 139 | 140 | 141 | # -- Options for manual page output --------------------------------------- 142 | 143 | # One entry per manual page. List of tuples 144 | # (source start file, name, description, authors, manual section). 145 | man_pages = [ 146 | (master_doc, package.__name__, package.__name__ + ' Documentation', 147 | [author], 1) 148 | ] 149 | 150 | 151 | # -- Options for Texinfo output ------------------------------------------- 152 | 153 | # Grouping the document tree into Texinfo files. List of tuples 154 | # (source start file, target name, title, author, 155 | # dir menu entry, description, category) 156 | texinfo_documents = [ 157 | (master_doc, package.__name__, package.__name__ + ' Documentation', 158 | author, package.__name__, package.__description__, 159 | 'Miscellaneous'), 160 | ] 161 | -------------------------------------------------------------------------------- /google_streetview/cli.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Usage: 5 | google_streetview [--optional] 6 | google_streetview [-positional] ... 7 | 8 | A command line tool for Google Street View search. 9 | 10 | Positional arguments: 11 | -h show this help message and exit 12 | -i show documentation in browser 13 | -a show optional arguments in browser 14 | -s = set default optional arguments 15 | -r remove default arguments 16 | -v view default arguments 17 | -d reset default arguments 18 | 19 | Optional arguments: 20 | --pano panorama ids (req) 21 | --location text or latitude/longitude (req) 22 | --size image size (default: 640x640) 23 | --heading camera heading 0 to 360 24 | --fov camera zoom up 120 (default: 90) 25 | --pitch camera angle 90 to -90 (default: 0) 26 | --site_api base url for api site 27 | --site_metadata base url for metadata site 28 | --save_links path for links text file 29 | --save_metadata path for metadata JSON file 30 | --save_downloads path for directory of image downloads 31 | --option_silent 'True' to disable preview 32 | --option_preview num of results to preview 33 | 34 | For more arguments use: google_streetview -a 35 | 36 | Examples: 37 | 38 | Set developer key arguments 39 | > google_streetview -s key="dev_key" 40 | 41 | Get street view image using location 42 | > google_streetview --location=46.414382,10.013988 43 | > google_streetview --location=46.414382,10.013988;40.720032,-73.988354 44 | 45 | Get street view image using panorama id 46 | > google_streetview --pano=vPnURflnc8AZu5NMLYRddw 47 | > google_streetview --pano=vPnURflnc8AZu5NMLYRddw;A1v2IdX_6HKnIQa2SPyyAg 48 | 49 | Get 360 panorama using heading 50 | > google_streetview --location=46.414382,10.013988 --heading=0;90;180;270 --fov=90 51 | 52 | Download street view images to "downloads" folder 53 | > google_streetview --location=46.414382,10.013988 --save_downloads=downloads 54 | 55 | Save street view links and metadata 56 | > google_streetview --location=46.414382,10.013988 --save_links=links.txt 57 | > google_streetview --location=46.414382,10.013988 --save_metadata=metadata.json 58 | 59 | For more information visit use: google_streetview -i 60 | """ 61 | 62 | from google_streetview import helpers 63 | from os.path import isfile 64 | from pkg_resources import resource_filename, Requirement 65 | from pprint import pprint 66 | from sys import argv 67 | from webbrowser import open_new_tab 68 | 69 | import kwconfig 70 | import google_streetview.api 71 | 72 | _doc_link = 'https://github.com/rrwen/google_streetview' 73 | _api_link = 'https://developers.google.com/maps/documentation/streetview/intro#url_parameters' 74 | 75 | def run(argv=argv): 76 | """Runs the google_streetview command line tool. 77 | 78 | This function runs the google_streetview command line tool 79 | in a terminal. It was intended for use inside a py file 80 | (.py) to be executed using python. 81 | 82 | Notes: 83 | * Optional arguments with ``ref_`` are for the ``site`` and ``site_metadata`` parameters in :class:`api.results` 84 | 85 | For distribution, this function must be defined in the following files:: 86 | 87 | # In 'google_streetview/google_streetview/__main__.py' 88 | from .cli import run 89 | run() 90 | 91 | # In 'google_streetview/google_streetview.py' 92 | from google_streetview.cli import run 93 | if __name__ == '__main__': 94 | run() 95 | 96 | # In 'google_streetview/__init__.py' 97 | __entry_points__ = {'console_scripts': ['google_streetview=google_streetview.cli:run']} 98 | 99 | Examples:: 100 | 101 | # Import google_streetview for the cli module 102 | import google_streetview.cli 103 | 104 | # Create command line arguments 105 | argv = [ 106 | 'cli.py', 107 | 'google', 108 | '--searchType=image', 109 | '--build_developerKey=your_dev_key', 110 | '--cx=your_cx_id' 111 | '--num=1' 112 | ] 113 | 114 | # Run command line 115 | google_streetview.cli.run(argv) 116 | 117 | """ 118 | config_file = kwconfig.manage( 119 | file_path=resource_filename(Requirement.parse('google_streetview'), 'google_streetview/config.json'), 120 | defaults={ 121 | 'size': '640x640', 122 | 'fov': '90', 123 | 'pitch': '0', 124 | 'option_silent': 'false', 125 | 'option_preview': '10'} 126 | ) 127 | 128 | # (commands) Main command calls 129 | if len(argv) > 1: 130 | if argv[1] == '-i': # browse docs 131 | open_new_tab(_doc_link) 132 | exit() 133 | elif argv[1] == '-a': # browse arguments 134 | open_new_tab(_api_link) 135 | exit() 136 | config_file.command(argv, i=1, doc=__doc__, quit=True, silent=False) 137 | 138 | # (parse_args) Parse command arguments into dict 139 | kwargs = kwconfig.parse(argv[1:]) 140 | kwargs = config_file.add(kwargs) 141 | 142 | # (split_args) Split args into build, cse, and save arguments 143 | siteargs = {} 144 | apiargs = {} 145 | saveargs = {} 146 | optionargs = {} 147 | for k, v in kwargs.items(): 148 | if 'site_' == k[0:4]: 149 | siteargs[k[4:]] = v 150 | elif 'save_' == k[0:5]: 151 | saveargs[k[5:]] = v 152 | elif 'option_' == k[0:7]: 153 | optionargs[k[7:]] = v 154 | else: 155 | apiargs[k] = v 156 | 157 | # (api_results) Get google api results 158 | site_api = siteargs['api'] if 'api' in siteargs else 'https://maps.googleapis.com/maps/api/streetview' 159 | site_metadata = siteargs['site_metadata'] if 'metadata' in siteargs else 'https://maps.googleapis.com/maps/api/streetview/metadata' 160 | results = google_streetview.api.results( 161 | helpers.api_list(apiargs), 162 | site_api=site_api, 163 | site_metadata=site_metadata) 164 | 165 | # (api_print) Print a preview of results 166 | if 'silent' in optionargs: 167 | if optionargs['silent'].lower() != 'true': 168 | results.preview(n=int(optionargs['preview'])) 169 | 170 | # (api_save) Save metadata 171 | if 'links' in saveargs: 172 | results.save_links(saveargs['links']) 173 | if 'metadata' in saveargs: 174 | results.save_metadata(saveargs['metadata']) 175 | 176 | # (api_download) Download links 177 | if 'downloads' in saveargs: 178 | results.download_links(saveargs['downloads']) 179 | -------------------------------------------------------------------------------- /google_streetview/api.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from google_streetview import helpers 4 | from os import path, makedirs 5 | from pprint import pprint 6 | try: 7 | from urllib.parse import urlencode 8 | except ImportError: 9 | from urllib import urlencode 10 | 11 | import json 12 | import requests 13 | 14 | class results: 15 | """Google Street View Image API results. 16 | 17 | Uses the `Google Street View Image API `_ 18 | to search for street level imagery. 19 | 20 | Args: 21 | params (listof dict): 22 | List of dict containing batch `street view URL parameters `_. 23 | site_api(str): 24 | The site for the URL request (example: https://maps.googleapis.com/maps/api/streetview). 25 | site_metadata(str): 26 | The site for the URL `metadata `_ request (example: https://maps.googleapis.com/maps/api/streetview/metadata). 27 | 28 | Attributes: 29 | params (listof dict): 30 | Same as argument ``params`` for reference of inputs. 31 | links (listof str): 32 | List of str containing street view URL requests. 33 | metadata (listof dict): 34 | Objects returned from `street view metadata request `_. 35 | metadata_links (listof str): 36 | List of str containing street view URL metadata requests. 37 | 38 | Examples: 39 | :: 40 | 41 | # Import google_streetview for the api module 42 | import google_streetview.api 43 | 44 | # Define parameters for street view api 45 | params = [{ 46 | 'size': '600x300', # max 640x640 pixels 47 | 'location': '46.414382,10.013988', 48 | 'heading': '151.78', 49 | 'pitch': '-0.76', 50 | 'key': 'your_dev_key' 51 | }] 52 | 53 | # Create a results object 54 | results = google_streetview.api.results(params) 55 | 56 | # Preview results 57 | results.preview() 58 | 59 | # Download images to directory 'downloads' 60 | results.download_links('downloads') 61 | 62 | # Save links 63 | results.save_links('links.txt') 64 | 65 | # Save metadata 66 | results.save_metadata('metadata.json') 67 | """ 68 | def __init__( 69 | self, 70 | params, 71 | site_api='https://maps.googleapis.com/maps/api/streetview', 72 | site_metadata='https://maps.googleapis.com/maps/api/streetview/metadata'): 73 | 74 | # (params) Set default params 75 | defaults = { 76 | 'size': '640x640' 77 | } 78 | for i in range(len(params)): 79 | for k in defaults: 80 | if k not in params[i]: 81 | params[i][k] = defaults[k] 82 | self.params = params 83 | 84 | # (image) Create image api links from parameters 85 | self.links = [site_api + '?' + urlencode(p) for p in params] 86 | 87 | # (metadata) Create metadata api links and data from parameters 88 | self.metadata_links = [site_metadata + '?' + urlencode(p) for p in params] 89 | self.metadata = [requests.get(url, stream=True).json() for url in self.metadata_links] 90 | 91 | def download_links(self, dir_path, metadata_file='metadata.json', metadata_status='status', status_ok='OK'): 92 | """Download Google Street View images from parameter queries if they are available. 93 | 94 | Args: 95 | dir_path (str): 96 | Path of directory to save downloads of images from :class:`api.results`.links 97 | metadata_file (str): 98 | Name of the file with extension to save the :class:`api.results`.metadata 99 | metadata_status (str): 100 | Key name of the status value from :class:`api.results`.metadata response from the metadata API request. 101 | status_ok (str): 102 | Value from the metadata API response status indicating that an image is available. 103 | """ 104 | metadata = self.metadata 105 | if not path.isdir(dir_path): 106 | makedirs(dir_path) 107 | 108 | # (download) Download images if status from metadata is ok 109 | for i, url in enumerate(self.links): 110 | if metadata[i][metadata_status] == status_ok: 111 | file_path = path.join(dir_path, 'gsv_' + str(i) + '.jpg') 112 | metadata[i]['_file'] = path.basename(file_path) # add file reference 113 | helpers.download(url, file_path) 114 | 115 | # (metadata) Save metadata with file reference 116 | metadata_path = path.join(dir_path, metadata_file) 117 | with open(metadata_path, 'w') as out_file: 118 | json.dump(metadata, out_file) 119 | 120 | def preview(self, n=10, k=['date', 'location', 'pano_id', 'status'], kheader='pano_id'): 121 | """Print a preview of the request results. 122 | 123 | Args: 124 | n (int): 125 | Maximum number of requests to preview 126 | k (str): 127 | Keys in :class:`api.results`.metadata to preview 128 | kheader (str): 129 | Key in :class:`api.results`.metadata[``k``] to use as the header 130 | """ 131 | items = self.metadata 132 | 133 | # (cse_print) Print results 134 | for i, kv in enumerate(items[:n]): 135 | 136 | # (print_header) Print result header 137 | header = '\n[' + str(i) + '] ' + kv[kheader] 138 | print(header) 139 | print('=' * len(header)) 140 | 141 | # (print_metadata) Print result metadata 142 | for ki in k: 143 | if ki in kv: 144 | if ki == 'location': 145 | print(ki + ': \n lat: ' + str(kv[ki]['lat']) + '\n lng: ' + str(kv[ki]['lng'])) 146 | else: 147 | print(ki + ': ' + str(kv[ki])) 148 | 149 | def save_links(self, file_path): 150 | """Saves a text file of the search result links. 151 | 152 | Saves a text file of the search result links, where each link 153 | is saved in a new line. An example is provided below:: 154 | 155 | https://maps.googleapis.com/maps/api/streetview?size=600x300&location=46.414382,10.013988&heading=151.78&pitch=-0.76&key=yourdevkey 156 | https://maps.googleapis.com/maps/api/streetview?size=600x300&location=41.403609,2.174448&heading=100&pitch=28&scale=2&key=yourdevkey 157 | 158 | Args: 159 | file_path (str): 160 | Path to the text file to save links to. 161 | """ 162 | data = '\n'.join(self.links) 163 | with open(file_path, 'w+') as out_file: 164 | out_file.write(data) 165 | 166 | def save_metadata(self, file_path): 167 | """Save Google Street View metadata from parameter queries. 168 | 169 | Args: 170 | file_path (str): 171 | Path of the file with extension to save the :class:`api.results`.metadata 172 | """ 173 | with open(file_path, 'w+') as out_file: 174 | json.dump(self.metadata, out_file) 175 | 176 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | google_streetview 2 | ================= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | 7 | | Richard Wen 8 | | rrwen.dev@gmail.com 9 | 10 | A command line tool and module for Google Street View Image API. 11 | 12 | :: 13 | 14 | google_streetview -h 15 | google_streetview --location=46.414382,10.013988 16 | google_streetview --pano=vPnURflnc8AZu5NMLYRddw 17 | 18 | Install 19 | ------- 20 | 21 | 1. Install `Python `__ 22 | 2. Install `google_streetview `__ via ``pip`` 23 | 24 | :: 25 | 26 | pip install google_streetview 27 | 28 | Setup 29 | ----- 30 | 31 | * A `Google API developer key `__ is required to use this package 32 | * A `Gmail `__ account will also be required to create and access the developer key 33 | * When asked to sign in, use your Gmail account for access 34 | * Please note that usage of the Google Street View API may require a `billing plan `__ 35 | 36 | *Note: Instructions and links were written on March 5, 2019, and are subject to change depending on Google's website and API.* 37 | 38 | Google API 39 | ********** 40 | 41 | An `API developer key `__ for the `Google Application Programming Interface (API) `__ can be setup with the following instructions: 42 | 43 | 1. Enable `Google Street View Image API `__ 44 | 2. Go to `Google API Console Credentials `__ 45 | 3. Click **Create Credentials -> API Key** 46 | 4. Set ``key`` by replacing "your_dev_key" with the **API Key** 47 | 48 | :: 49 | 50 | google_streetview -s key="your_dev_key" 51 | 52 | Usage 53 | ----- 54 | 55 | For help in the console, use:: 56 | 57 | google_streetview -h 58 | 59 | Please ensure that the `Setup`_ section was completed:: 60 | 61 | google_streetview -s key="your_dev_key" 62 | 63 | Image Search 64 | ************ 65 | 66 | Get street view image using the location argument ``--location`` and providing ``,`` values:: 67 | 68 | google_streetview --location=46.414382,10.013988 69 | 70 | .. image:: img/location_example.jpg 71 | 72 | Get street view image using the panorama id argument ``--pano``:: 73 | 74 | google_streetview --pano=vPnURflnc8AZu5NMLYRddw 75 | 76 | .. image:: img/pano_example.jpg 77 | 78 | Multiple locations and panorama ids can be given by separating with ``;``:: 79 | 80 | google_streetview --location=46.414382,10.013988;40.720032,-73.988354 81 | google_streetview --pano=vPnURflnc8AZu5NMLYRddw;A1v2IdX_6HKnIQa2SPyyAg 82 | 83 | .. image:: img/multi_example.jpg 84 | 85 | Adjust size of the images up to 640 by 640 pixels with the ``--size`` argument and providing ``x`` values (the default is ``640x640``):: 86 | 87 | google_streetview --location=46.414382,10.013988;40.720032,-73.988354 --size=200x200 88 | 89 | .. image:: img/size_example.jpg 90 | 91 | Adjust the heading of the camera with the ``--heading`` argument, where 0 and 360 are north, 90 is east, 180 is south, and 270 is west:: 92 | 93 | google_streetview --location=46.414382,10.013988 --heading=0 94 | google_streetview --location=46.414382,10.013988 --heading=90 95 | google_streetview --location=46.414382,10.013988 --heading=180 96 | google_streetview --location=46.414382,10.013988 --heading=270 97 | google_streetview --location=46.414382,10.013988 --heading=360 98 | 99 | .. image:: img/heading_example.jpg 100 | 101 | Adjust the image's horizontal field of view with the ``--fov`` argument, which represents zoom values of up to 120 (the default is ``90``):: 102 | 103 | google_streetview --location=46.414382,10.013988 --fov=0 104 | google_streetview --location=46.414382,10.013988 --fov=90 105 | google_streetview --location=46.414382,10.013988 --fov=120 106 | 107 | .. image:: img/fov_example.jpg 108 | 109 | Adjust the camera's up and down angle with the ``--pitch`` argument, where positive values up to 90 degrees indicate straight up and negative values down to -90 indicate straight down (the default is ``0``:: 110 | 111 | google_streetview --location=46.414382,10.013988 --pitch=0 112 | google_streetview --location=46.414382,10.013988 --pitch=90 113 | google_streetview --location=46.414382,10.013988 --pitch=-90 114 | 115 | .. image:: img/pitch_example.jpg 116 | 117 | Save Results 118 | ************ 119 | 120 | Download street view images to "downloads" folder with the ``--save_downloads`` argument:: 121 | 122 | google_streetview --location=46.414382,10.013988;40.720032,-73.988354 --save_downloads=downloads 123 | 124 | .. image:: img/download_example.jpg 125 | 126 | Save metadata:: 127 | 128 | google_streetview --location=46.414382,10.013988 --save_metadata=metadata.json 129 | google_streetview --pano=vPnURflnc8AZu5NMLYRddw --save_metadata=metadata.json 130 | 131 | Save URL links:: 132 | 133 | google_streetview --location=46.414382,10.013988 --save_links=links.txt 134 | google_streetview --pano=vPnURflnc8AZu5NMLYRdd --save_links=links.txt 135 | 136 | Save links and metadata:: 137 | 138 | google_streetview --location=46.414382,10.013988 --save_links=links.txt --save_metadata=metadata.json 139 | google_streetview --pano=vPnURflnc8AZu5NMLYRdd --save_links=links.txt --save_metadata=metadata.json 140 | 141 | Multiple Arguments 142 | ****************** 143 | 144 | Multiple arguments can be specified by separating parameter values with the semi-colon ``;`` seen in the ``heading`` parameter:: 145 | 146 | google_streetview --location=46.414382,10.013988 --heading=0;90;180;270 147 | 148 | .. image:: img/heading_example.jpg 149 | 150 | Download the 360 panorama imagery for 2 locations using a field of vision ``fov`` of 90, which provides 8 images (90 degree from ``fov`` up to 270 degrees as 0 and 360 refer to the same ``heading``):: 151 | 152 | google_streetview --location=46.414382,10.013988;40.720032,-73.988354 --fov=90 --heading=0;90;180;270 153 | 154 | .. image:: img/panorama_example.jpg 155 | 156 | Default Arguments 157 | ***************** 158 | 159 | Default arguments persist even after the console is closed. Defaults enable user customization of the google_streetview command without a long list of arguments every call. 160 | 161 | View the defaults:: 162 | 163 | google_streetview -v 164 | 165 | Increase number of results previewed to ``20``:: 166 | 167 | google_streetview -s option_preview=20 168 | 169 | Turn off preview of results:: 170 | 171 | google_streetview -s option_silent=True 172 | 173 | Set the ``fov`` argument to default to ``45``:: 174 | 175 | google_streetview -s fov=45 176 | 177 | Set the ``heading`` argument to default to ``0`` images:: 178 | 179 | google_streetview -s heading=0 180 | 181 | Set to save a text file named ``links.txt`` with result links whenever used:: 182 | 183 | google_streetview -s save_links=links.txt 184 | 185 | Remove default arguments:: 186 | 187 | search_result -r option_preview 188 | google_streetview -r option_silent 189 | google_streetview -r fov 190 | google_streetview -r heading 191 | google_streetview -r save_links 192 | 193 | Reset the defaults:: 194 | 195 | google_streetview -d 196 | 197 | After resetting defaults, the developer key will have to be set again:: 198 | 199 | google_streetview -s key="your_dev_key" 200 | 201 | Additional Arguments 202 | ******************** 203 | 204 | A number of optional arguments defined using ``--`` are not shown when using ``google_streetview -h``. These can be used with the same names as the paramters passed to `Google's Street View Image API `__:: 205 | 206 | google_streetview -a 207 | 208 | For example, the digital signature for billing can be set by argument ``signature`` which is a named paramter in the API:: 209 | 210 | google_streetview cat --signature="your_signature" 211 | 212 | Module Import 213 | ************* 214 | 215 | The `google_streetview `__ package may also be used as a `Python module `__:: 216 | 217 | # Import google_streetview for the api module 218 | import google_streetview.api 219 | 220 | # Define parameters for street view api 221 | params = [{ 222 | 'size': '600x300', # max 640x640 pixels 223 | 'location': '46.414382,10.013988', 224 | 'heading': '151.78', 225 | 'pitch': '-0.76', 226 | 'key': 'your_dev_key' 227 | }] 228 | 229 | # Create a results object 230 | results = google_streetview.api.results(params) 231 | 232 | # Download images to directory 'downloads' 233 | results.download_links('downloads') 234 | 235 | For more details on module usage, see the examples in `api`_ for single argument queries and `helpers.api_list`_ for multiple argument queries. 236 | 237 | Modules 238 | ------- 239 | 240 | api 241 | *** 242 | 243 | .. automodule:: api 244 | :members: 245 | 246 | cli 247 | *** 248 | 249 | .. autofunction:: cli.run 250 | 251 | helpers 252 | ******* 253 | 254 | .. autofunction:: helpers.api_list 255 | -------------------------------------------------------------------------------- /docs/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | google_streetview 2 | ================= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | 7 | | Richard Wen 8 | | rrwen.dev@gmail.com 9 | 10 | A command line tool and module for Google Street View Image API. 11 | 12 | :: 13 | 14 | google_streetview -h 15 | google_streetview --location=46.414382,10.013988 16 | google_streetview --pano=vPnURflnc8AZu5NMLYRddw 17 | 18 | Install 19 | ------- 20 | 21 | 1. Install `Python `__ 22 | 2. Install `google_streetview `__ via ``pip`` 23 | 24 | :: 25 | 26 | pip install google_streetview 27 | 28 | Setup 29 | ----- 30 | 31 | * A `Google API developer key `__ is required to use this package 32 | * A `Gmail `__ account will also be required to create and access the developer key 33 | * When asked to sign in, use your Gmail account for access 34 | * Please note that usage of the Google Street View API may require a `billing plan `__ 35 | 36 | *Note: Instructions and links were written on March 5, 2019, and are subject to change depending on Google's website and API.* 37 | 38 | Google API 39 | ********** 40 | 41 | An `API developer key `__ for the `Google Application Programming Interface (API) `__ can be setup with the following instructions: 42 | 43 | 1. Enable `Google Street View Image API `__ 44 | 2. Go to `Google API Console Credentials `__ 45 | 3. Click **Create Credentials -> API Key** 46 | 4. Set ``key`` by replacing "your_dev_key" with the **API Key** 47 | 48 | :: 49 | 50 | google_streetview -s key="your_dev_key" 51 | 52 | Usage 53 | ----- 54 | 55 | For help in the console, use:: 56 | 57 | google_streetview -h 58 | 59 | Please ensure that the `Setup`_ section was completed:: 60 | 61 | google_streetview -s key="your_dev_key" 62 | 63 | Image Search 64 | ************ 65 | 66 | Get street view image using the location argument ``--location`` and providing ``,`` values:: 67 | 68 | google_streetview --location=46.414382,10.013988 69 | 70 | .. image:: img/location_example.jpg 71 | 72 | Get street view image using the panorama id argument ``--pano``:: 73 | 74 | google_streetview --pano=vPnURflnc8AZu5NMLYRddw 75 | 76 | .. image:: img/pano_example.jpg 77 | 78 | Multiple locations and panorama ids can be given by separating with ``;``:: 79 | 80 | google_streetview --location=46.414382,10.013988;40.720032,-73.988354 81 | google_streetview --pano=vPnURflnc8AZu5NMLYRddw;A1v2IdX_6HKnIQa2SPyyAg 82 | 83 | .. image:: img/multi_example.jpg 84 | 85 | Adjust size of the images up to 640 by 640 pixels with the ``--size`` argument and providing ``x`` values (the default is ``640x640``):: 86 | 87 | google_streetview --location=46.414382,10.013988;40.720032,-73.988354 --size=200x200 88 | 89 | .. image:: img/size_example.jpg 90 | 91 | Adjust the heading of the camera with the ``--heading`` argument, where 0 and 360 are north, 90 is east, 180 is south, and 270 is west:: 92 | 93 | google_streetview --location=46.414382,10.013988 --heading=0 94 | google_streetview --location=46.414382,10.013988 --heading=90 95 | google_streetview --location=46.414382,10.013988 --heading=180 96 | google_streetview --location=46.414382,10.013988 --heading=270 97 | google_streetview --location=46.414382,10.013988 --heading=360 98 | 99 | .. image:: img/heading_example.jpg 100 | 101 | Adjust the image's horizontal field of view with the ``--fov`` argument, which represents zoom values of up to 120 (the default is ``90``):: 102 | 103 | google_streetview --location=46.414382,10.013988 --fov=0 104 | google_streetview --location=46.414382,10.013988 --fov=90 105 | google_streetview --location=46.414382,10.013988 --fov=120 106 | 107 | .. image:: img/fov_example.jpg 108 | 109 | Adjust the camera's up and down angle with the ``--pitch`` argument, where positive values up to 90 degrees indicate straight up and negative values down to -90 indicate straight down (the default is ``0``:: 110 | 111 | google_streetview --location=46.414382,10.013988 --pitch=0 112 | google_streetview --location=46.414382,10.013988 --pitch=90 113 | google_streetview --location=46.414382,10.013988 --pitch=-90 114 | 115 | .. image:: img/pitch_example.jpg 116 | 117 | Save Results 118 | ************ 119 | 120 | Download street view images to "downloads" folder with the ``--save_downloads`` argument:: 121 | 122 | google_streetview --location=46.414382,10.013988;40.720032,-73.988354 --save_downloads=downloads 123 | 124 | .. image:: img/download_example.jpg 125 | 126 | Save metadata:: 127 | 128 | google_streetview --location=46.414382,10.013988 --save_metadata=metadata.json 129 | google_streetview --pano=vPnURflnc8AZu5NMLYRddw --save_metadata=metadata.json 130 | 131 | Save URL links:: 132 | 133 | google_streetview --location=46.414382,10.013988 --save_links=links.txt 134 | google_streetview --pano=vPnURflnc8AZu5NMLYRdd --save_links=links.txt 135 | 136 | Save links and metadata:: 137 | 138 | google_streetview --location=46.414382,10.013988 --save_links=links.txt --save_metadata=metadata.json 139 | google_streetview --pano=vPnURflnc8AZu5NMLYRdd --save_links=links.txt --save_metadata=metadata.json 140 | 141 | Multiple Arguments 142 | ****************** 143 | 144 | Multiple arguments can be specified by separating parameter values with the semi-colon ``;`` seen in the ``heading`` parameter:: 145 | 146 | google_streetview --location=46.414382,10.013988 --heading=0;90;180;270 147 | 148 | .. image:: img/heading_example.jpg 149 | 150 | Download the 360 panorama imagery for 2 locations using a field of vision ``fov`` of 90, which provides 8 images (90 degree from ``fov`` up to 270 degrees as 0 and 360 refer to the same ``heading``):: 151 | 152 | google_streetview --location=46.414382,10.013988;40.720032,-73.988354 --fov=90 --heading=0;90;180;270 153 | 154 | .. image:: img/panorama_example.jpg 155 | 156 | Default Arguments 157 | ***************** 158 | 159 | Default arguments persist even after the console is closed. Defaults enable user customization of the google_streetview command without a long list of arguments every call. 160 | 161 | View the defaults:: 162 | 163 | google_streetview -v 164 | 165 | Increase number of results previewed to ``20``:: 166 | 167 | google_streetview -s option_preview=20 168 | 169 | Turn off preview of results:: 170 | 171 | google_streetview -s option_silent=True 172 | 173 | Set the ``fov`` argument to default to ``45``:: 174 | 175 | google_streetview -s fov=45 176 | 177 | Set the ``heading`` argument to default to ``0`` images:: 178 | 179 | google_streetview -s heading=0 180 | 181 | Set to save a text file named ``links.txt`` with result links whenever used:: 182 | 183 | google_streetview -s save_links=links.txt 184 | 185 | Remove default arguments:: 186 | 187 | search_result -r option_preview 188 | google_streetview -r option_silent 189 | google_streetview -r fov 190 | google_streetview -r heading 191 | google_streetview -r save_links 192 | 193 | Reset the defaults:: 194 | 195 | google_streetview -d 196 | 197 | After resetting defaults, the developer key will have to be set again:: 198 | 199 | google_streetview -s key="your_dev_key" 200 | 201 | Additional Arguments 202 | ******************** 203 | 204 | A number of optional arguments defined using ``--`` are not shown when using ``google_streetview -h``. These can be used with the same names as the paramters passed to `Google's Street View Image API `__:: 205 | 206 | google_streetview -a 207 | 208 | For example, the digital signature for billing can be set by argument ``signature`` which is a named paramter in the API:: 209 | 210 | google_streetview cat --signature="your_signature" 211 | 212 | Module Import 213 | ************* 214 | 215 | The `google_streetview `__ package may also be used as a `Python module `__:: 216 | 217 | # Import google_streetview for the api module 218 | import google_streetview.api 219 | 220 | # Define parameters for street view api 221 | params = [{ 222 | 'size': '600x300', # max 640x640 pixels 223 | 'location': '46.414382,10.013988', 224 | 'heading': '151.78', 225 | 'pitch': '-0.76', 226 | 'key': 'your_dev_key' 227 | }] 228 | 229 | # Create a results object 230 | results = google_streetview.api.results(params) 231 | 232 | # Download images to directory 'downloads' 233 | results.download_links('downloads') 234 | 235 | For more details on module usage, see the examples in `api`_ for single argument queries and `helpers.api_list`_ for multiple argument queries. 236 | 237 | Modules 238 | ------- 239 | 240 | api 241 | *** 242 | 243 | .. automodule:: api 244 | :members: 245 | 246 | cli 247 | *** 248 | 249 | .. autofunction:: cli.run 250 | 251 | helpers 252 | ******* 253 | 254 | .. autofunction:: helpers.api_list 255 | -------------------------------------------------------------------------------- /docs/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | */ 33 | jQuery.urldecode = function(x) { 34 | return decodeURIComponent(x).replace(/\+/g, ' '); 35 | }; 36 | 37 | /** 38 | * small helper function to urlencode strings 39 | */ 40 | jQuery.urlencode = encodeURIComponent; 41 | 42 | /** 43 | * This function returns the parsed url parameters of the 44 | * current request. Multiple values per key are supported, 45 | * it will always return arrays of strings for the value parts. 46 | */ 47 | jQuery.getQueryParameters = function(s) { 48 | if (typeof s === 'undefined') 49 | s = document.location.search; 50 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 51 | var result = {}; 52 | for (var i = 0; i < parts.length; i++) { 53 | var tmp = parts[i].split('=', 2); 54 | var key = jQuery.urldecode(tmp[0]); 55 | var value = jQuery.urldecode(tmp[1]); 56 | if (key in result) 57 | result[key].push(value); 58 | else 59 | result[key] = [value]; 60 | } 61 | return result; 62 | }; 63 | 64 | /** 65 | * highlight a given string on a jquery object by wrapping it in 66 | * span elements with the given class name. 67 | */ 68 | jQuery.fn.highlightText = function(text, className) { 69 | function highlight(node, addItems) { 70 | if (node.nodeType === 3) { 71 | var val = node.nodeValue; 72 | var pos = val.toLowerCase().indexOf(text); 73 | if (pos >= 0 && 74 | !jQuery(node.parentNode).hasClass(className) && 75 | !jQuery(node.parentNode).hasClass("nohighlight")) { 76 | var span; 77 | var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); 78 | if (isInSVG) { 79 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 80 | } else { 81 | span = document.createElement("span"); 82 | span.className = className; 83 | } 84 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 85 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 86 | document.createTextNode(val.substr(pos + text.length)), 87 | node.nextSibling)); 88 | node.nodeValue = val.substr(0, pos); 89 | if (isInSVG) { 90 | var bbox = span.getBBox(); 91 | var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); 92 | rect.x.baseVal.value = bbox.x; 93 | rect.y.baseVal.value = bbox.y; 94 | rect.width.baseVal.value = bbox.width; 95 | rect.height.baseVal.value = bbox.height; 96 | rect.setAttribute('class', className); 97 | var parentOfText = node.parentNode.parentNode; 98 | addItems.push({ 99 | "parent": node.parentNode, 100 | "target": rect}); 101 | } 102 | } 103 | } 104 | else if (!jQuery(node).is("button, select, textarea")) { 105 | jQuery.each(node.childNodes, function() { 106 | highlight(this, addItems); 107 | }); 108 | } 109 | } 110 | var addItems = []; 111 | var result = this.each(function() { 112 | highlight(this, addItems); 113 | }); 114 | for (var i = 0; i < addItems.length; ++i) { 115 | jQuery(addItems[i].parent).before(addItems[i].target); 116 | } 117 | return result; 118 | }; 119 | 120 | /* 121 | * backward compatibility for jQuery.browser 122 | * This will be supported until firefox bug is fixed. 123 | */ 124 | if (!jQuery.browser) { 125 | jQuery.uaMatch = function(ua) { 126 | ua = ua.toLowerCase(); 127 | 128 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 129 | /(webkit)[ \/]([\w.]+)/.exec(ua) || 130 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 131 | /(msie) ([\w.]+)/.exec(ua) || 132 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || 133 | []; 134 | 135 | return { 136 | browser: match[ 1 ] || "", 137 | version: match[ 2 ] || "0" 138 | }; 139 | }; 140 | jQuery.browser = {}; 141 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; 142 | } 143 | 144 | /** 145 | * Small JavaScript module for the documentation. 146 | */ 147 | var Documentation = { 148 | 149 | init : function() { 150 | this.fixFirefoxAnchorBug(); 151 | this.highlightSearchWords(); 152 | this.initIndexTable(); 153 | 154 | }, 155 | 156 | /** 157 | * i18n support 158 | */ 159 | TRANSLATIONS : {}, 160 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, 161 | LOCALE : 'unknown', 162 | 163 | // gettext and ngettext don't access this so that the functions 164 | // can safely bound to a different name (_ = Documentation.gettext) 165 | gettext : function(string) { 166 | var translated = Documentation.TRANSLATIONS[string]; 167 | if (typeof translated === 'undefined') 168 | return string; 169 | return (typeof translated === 'string') ? translated : translated[0]; 170 | }, 171 | 172 | ngettext : function(singular, plural, n) { 173 | var translated = Documentation.TRANSLATIONS[singular]; 174 | if (typeof translated === 'undefined') 175 | return (n == 1) ? singular : plural; 176 | return translated[Documentation.PLURALEXPR(n)]; 177 | }, 178 | 179 | addTranslations : function(catalog) { 180 | for (var key in catalog.messages) 181 | this.TRANSLATIONS[key] = catalog.messages[key]; 182 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 183 | this.LOCALE = catalog.locale; 184 | }, 185 | 186 | /** 187 | * add context elements like header anchor links 188 | */ 189 | addContextElements : function() { 190 | $('div[id] > :header:first').each(function() { 191 | $('\u00B6'). 192 | attr('href', '#' + this.id). 193 | attr('title', _('Permalink to this headline')). 194 | appendTo(this); 195 | }); 196 | $('dt[id]').each(function() { 197 | $('\u00B6'). 198 | attr('href', '#' + this.id). 199 | attr('title', _('Permalink to this definition')). 200 | appendTo(this); 201 | }); 202 | }, 203 | 204 | /** 205 | * workaround a firefox stupidity 206 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 207 | */ 208 | fixFirefoxAnchorBug : function() { 209 | if (document.location.hash && $.browser.mozilla) 210 | window.setTimeout(function() { 211 | document.location.href += ''; 212 | }, 10); 213 | }, 214 | 215 | /** 216 | * highlight the search words provided in the url in the text 217 | */ 218 | highlightSearchWords : function() { 219 | var params = $.getQueryParameters(); 220 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 221 | if (terms.length) { 222 | var body = $('div.body'); 223 | if (!body.length) { 224 | body = $('body'); 225 | } 226 | window.setTimeout(function() { 227 | $.each(terms, function() { 228 | body.highlightText(this.toLowerCase(), 'highlighted'); 229 | }); 230 | }, 10); 231 | $('') 233 | .appendTo($('#searchbox')); 234 | } 235 | }, 236 | 237 | /** 238 | * init the domain index toggle buttons 239 | */ 240 | initIndexTable : function() { 241 | var togglers = $('img.toggler').click(function() { 242 | var src = $(this).attr('src'); 243 | var idnum = $(this).attr('id').substr(7); 244 | $('tr.cg-' + idnum).toggle(); 245 | if (src.substr(-9) === 'minus.png') 246 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 247 | else 248 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 249 | }).css('display', ''); 250 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 251 | togglers.click(); 252 | } 253 | }, 254 | 255 | /** 256 | * helper function to hide the search marks again 257 | */ 258 | hideSearchWords : function() { 259 | $('#searchbox .highlight-link').fadeOut(300); 260 | $('span.highlighted').removeClass('highlighted'); 261 | }, 262 | 263 | /** 264 | * make the url absolute 265 | */ 266 | makeURL : function(relativeURL) { 267 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 268 | }, 269 | 270 | /** 271 | * get the current relative url 272 | */ 273 | getCurrentURL : function() { 274 | var path = document.location.pathname; 275 | var parts = path.split(/\//); 276 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 277 | if (this === '..') 278 | parts.pop(); 279 | }); 280 | var url = parts.join('/'); 281 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 282 | }, 283 | 284 | initOnKeyListeners: function() { 285 | $(document).keyup(function(event) { 286 | var activeElementType = document.activeElement.tagName; 287 | // don't navigate when in search box or textarea 288 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { 289 | switch (event.keyCode) { 290 | case 37: // left 291 | var prevHref = $('link[rel="prev"]').prop('href'); 292 | if (prevHref) { 293 | window.location.href = prevHref; 294 | return false; 295 | } 296 | case 39: // right 297 | var nextHref = $('link[rel="next"]').prop('href'); 298 | if (nextHref) { 299 | window.location.href = nextHref; 300 | return false; 301 | } 302 | } 303 | } 304 | }); 305 | } 306 | }; 307 | 308 | // quick alias for translations 309 | _ = Documentation.gettext; 310 | 311 | $(document).ready(function() { 312 | Documentation.init(); 313 | }); -------------------------------------------------------------------------------- /docs/_static/underscore.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.3.1 2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 3 | // Underscore is freely distributable under the MIT license. 4 | // Portions of Underscore are inspired or borrowed from Prototype, 5 | // Oliver Steele's Functional, and John Resig's Micro-Templating. 6 | // For all details and documentation: 7 | // http://documentcloud.github.com/underscore 8 | (function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== 9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c, 10 | h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each= 11 | b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a== 12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect= 13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e= 14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= 15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a, 17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}}; 24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments, 25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)}; 26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"}; 27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a), 28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+ 29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]= 30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain= 31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); 32 | -------------------------------------------------------------------------------- /docs/_modules/helpers.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | helpers — google_streetview 1.2.9 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 32 | 33 |
34 |
35 |
36 |
37 | 38 |

Source code for helpers

 39 | # -*- coding: utf-8 -*-
 40 | 
 41 | from itertools import product
 42 | 
 43 | import requests
 44 | import shutil
 45 | 
 46 | 
[docs]def api_list(apiargs): 47 | """Google Street View Image API results. 48 | 49 | Constructs a list of `Google Street View Image API queries <https://developers.google.com/maps/documentation/streetview/>`_ 50 | from a dictionary. 51 | 52 | Args: 53 | apiargs (listof dict): 54 | Dict containing `street view URL parameters <https://developers.google.com/maps/documentation/streetview/intro>`_. 55 | Each parameter can have multiple values if separated by ``;``. 56 | 57 | Returns: 58 | A ``listof dict`` containing single query requests per dictionary for Google Street View Image API. 59 | 60 | Examples: 61 | :: 62 | 63 | # Import google_streetview for the api and helper module 64 | import google_streetview.api 65 | import google_streetview.helpers 66 | 67 | # Create a dictionary with multiple parameters separated by ; 68 | apiargs = { 69 | 'location': '46.414382,10.013988;40.720032,-73.988354', 70 | 'size': '640x300;640x640', 71 | 'heading': '0;90;180;270', 72 | 'fov': '0;90;120', 73 | 'pitch': '-90;0;90' 74 | } 75 | 76 | # Get a list of all possible queries from multiple parameters 77 | api_list = google_streetview.helpers.api_list(apiargs) 78 | 79 | # Create a results object for all possible queries 80 | results = google_streetview.api.results(api_list) 81 | 82 | # Preview results 83 | results.preview() 84 | 85 | # Download images to directory 'downloads' 86 | results.download_links('downloads') 87 | 88 | # Save metadata 89 | results.save_metadata('metadata.json') 90 | """ 91 | 92 | # (api_query) Query combinations for each parameter 93 | api_queries = {} 94 | keywords = [k for k in apiargs] 95 | for k in keywords: 96 | if k in apiargs: 97 | api_queries[k] = apiargs[k].split(';') 98 | apiargs.pop(k, None) 99 | 100 | # (api_list) Build list of api requests based on query combinations 101 | out = [] 102 | keys = [k for k in api_queries] 103 | queries = [api_queries[k] for k in api_queries] 104 | combinations = product(*queries) 105 | for combo in combinations: 106 | api_copy = apiargs.copy() 107 | for k, parameter in zip(keys, combo): 108 | api_copy[k] = parameter 109 | out.append(api_copy) 110 | return(out)
111 | 112 | def download(url, file_path): 113 | r = requests.get(url, stream=True) 114 | if r.status_code == 200: # if request is successful 115 | with open(file_path, 'wb') as f: 116 | r.raw.decode_content = True 117 | shutil.copyfileobj(r.raw, f) 118 |
119 | 120 |
121 |
122 |
123 | 139 |
140 |
141 | 154 | 158 | 159 | -------------------------------------------------------------------------------- /docs/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /* -- main layout ----------------------------------------------------------- */ 13 | 14 | div.clearer { 15 | clear: both; 16 | } 17 | 18 | /* -- relbar ---------------------------------------------------------------- */ 19 | 20 | div.related { 21 | width: 100%; 22 | font-size: 90%; 23 | } 24 | 25 | div.related h3 { 26 | display: none; 27 | } 28 | 29 | div.related ul { 30 | margin: 0; 31 | padding: 0 0 0 10px; 32 | list-style: none; 33 | } 34 | 35 | div.related li { 36 | display: inline; 37 | } 38 | 39 | div.related li.right { 40 | float: right; 41 | margin-right: 5px; 42 | } 43 | 44 | /* -- sidebar --------------------------------------------------------------- */ 45 | 46 | div.sphinxsidebarwrapper { 47 | padding: 10px 5px 0 10px; 48 | } 49 | 50 | div.sphinxsidebar { 51 | float: left; 52 | width: 230px; 53 | margin-left: -100%; 54 | font-size: 90%; 55 | word-wrap: break-word; 56 | overflow-wrap : break-word; 57 | } 58 | 59 | div.sphinxsidebar ul { 60 | list-style: none; 61 | } 62 | 63 | div.sphinxsidebar ul ul, 64 | div.sphinxsidebar ul.want-points { 65 | margin-left: 20px; 66 | list-style: square; 67 | } 68 | 69 | div.sphinxsidebar ul ul { 70 | margin-top: 0; 71 | margin-bottom: 0; 72 | } 73 | 74 | div.sphinxsidebar form { 75 | margin-top: 10px; 76 | } 77 | 78 | div.sphinxsidebar input { 79 | border: 1px solid #98dbcc; 80 | font-family: sans-serif; 81 | font-size: 1em; 82 | } 83 | 84 | div.sphinxsidebar #searchbox input[type="text"] { 85 | float: left; 86 | width: 80%; 87 | padding: 0.25em; 88 | box-sizing: border-box; 89 | } 90 | 91 | div.sphinxsidebar #searchbox input[type="submit"] { 92 | float: left; 93 | width: 20%; 94 | border-left: none; 95 | padding: 0.25em; 96 | box-sizing: border-box; 97 | } 98 | 99 | 100 | img { 101 | border: 0; 102 | max-width: 100%; 103 | } 104 | 105 | /* -- search page ----------------------------------------------------------- */ 106 | 107 | ul.search { 108 | margin: 10px 0 0 20px; 109 | padding: 0; 110 | } 111 | 112 | ul.search li { 113 | padding: 5px 0 5px 20px; 114 | background-image: url(file.png); 115 | background-repeat: no-repeat; 116 | background-position: 0 7px; 117 | } 118 | 119 | ul.search li a { 120 | font-weight: bold; 121 | } 122 | 123 | ul.search li div.context { 124 | color: #888; 125 | margin: 2px 0 0 30px; 126 | text-align: left; 127 | } 128 | 129 | ul.keywordmatches li.goodmatch a { 130 | font-weight: bold; 131 | } 132 | 133 | /* -- index page ------------------------------------------------------------ */ 134 | 135 | table.contentstable { 136 | width: 90%; 137 | margin-left: auto; 138 | margin-right: auto; 139 | } 140 | 141 | table.contentstable p.biglink { 142 | line-height: 150%; 143 | } 144 | 145 | a.biglink { 146 | font-size: 1.3em; 147 | } 148 | 149 | span.linkdescr { 150 | font-style: italic; 151 | padding-top: 5px; 152 | font-size: 90%; 153 | } 154 | 155 | /* -- general index --------------------------------------------------------- */ 156 | 157 | table.indextable { 158 | width: 100%; 159 | } 160 | 161 | table.indextable td { 162 | text-align: left; 163 | vertical-align: top; 164 | } 165 | 166 | table.indextable ul { 167 | margin-top: 0; 168 | margin-bottom: 0; 169 | list-style-type: none; 170 | } 171 | 172 | table.indextable > tbody > tr > td > ul { 173 | padding-left: 0em; 174 | } 175 | 176 | table.indextable tr.pcap { 177 | height: 10px; 178 | } 179 | 180 | table.indextable tr.cap { 181 | margin-top: 10px; 182 | background-color: #f2f2f2; 183 | } 184 | 185 | img.toggler { 186 | margin-right: 3px; 187 | margin-top: 3px; 188 | cursor: pointer; 189 | } 190 | 191 | div.modindex-jumpbox { 192 | border-top: 1px solid #ddd; 193 | border-bottom: 1px solid #ddd; 194 | margin: 1em 0 1em 0; 195 | padding: 0.4em; 196 | } 197 | 198 | div.genindex-jumpbox { 199 | border-top: 1px solid #ddd; 200 | border-bottom: 1px solid #ddd; 201 | margin: 1em 0 1em 0; 202 | padding: 0.4em; 203 | } 204 | 205 | /* -- domain module index --------------------------------------------------- */ 206 | 207 | table.modindextable td { 208 | padding: 2px; 209 | border-collapse: collapse; 210 | } 211 | 212 | /* -- general body styles --------------------------------------------------- */ 213 | 214 | div.body { 215 | min-width: 450px; 216 | max-width: 800px; 217 | } 218 | 219 | div.body p, div.body dd, div.body li, div.body blockquote { 220 | -moz-hyphens: auto; 221 | -ms-hyphens: auto; 222 | -webkit-hyphens: auto; 223 | hyphens: auto; 224 | } 225 | 226 | a.headerlink { 227 | visibility: hidden; 228 | } 229 | 230 | h1:hover > a.headerlink, 231 | h2:hover > a.headerlink, 232 | h3:hover > a.headerlink, 233 | h4:hover > a.headerlink, 234 | h5:hover > a.headerlink, 235 | h6:hover > a.headerlink, 236 | dt:hover > a.headerlink, 237 | caption:hover > a.headerlink, 238 | p.caption:hover > a.headerlink, 239 | div.code-block-caption:hover > a.headerlink { 240 | visibility: visible; 241 | } 242 | 243 | div.body p.caption { 244 | text-align: inherit; 245 | } 246 | 247 | div.body td { 248 | text-align: left; 249 | } 250 | 251 | .first { 252 | margin-top: 0 !important; 253 | } 254 | 255 | p.rubric { 256 | margin-top: 30px; 257 | font-weight: bold; 258 | } 259 | 260 | img.align-left, .figure.align-left, object.align-left { 261 | clear: left; 262 | float: left; 263 | margin-right: 1em; 264 | } 265 | 266 | img.align-right, .figure.align-right, object.align-right { 267 | clear: right; 268 | float: right; 269 | margin-left: 1em; 270 | } 271 | 272 | img.align-center, .figure.align-center, object.align-center { 273 | display: block; 274 | margin-left: auto; 275 | margin-right: auto; 276 | } 277 | 278 | .align-left { 279 | text-align: left; 280 | } 281 | 282 | .align-center { 283 | text-align: center; 284 | } 285 | 286 | .align-right { 287 | text-align: right; 288 | } 289 | 290 | /* -- sidebars -------------------------------------------------------------- */ 291 | 292 | div.sidebar { 293 | margin: 0 0 0.5em 1em; 294 | border: 1px solid #ddb; 295 | padding: 7px 7px 0 7px; 296 | background-color: #ffe; 297 | width: 40%; 298 | float: right; 299 | } 300 | 301 | p.sidebar-title { 302 | font-weight: bold; 303 | } 304 | 305 | /* -- topics ---------------------------------------------------------------- */ 306 | 307 | div.topic { 308 | border: 1px solid #ccc; 309 | padding: 7px 7px 0 7px; 310 | margin: 10px 0 10px 0; 311 | } 312 | 313 | p.topic-title { 314 | font-size: 1.1em; 315 | font-weight: bold; 316 | margin-top: 10px; 317 | } 318 | 319 | /* -- admonitions ----------------------------------------------------------- */ 320 | 321 | div.admonition { 322 | margin-top: 10px; 323 | margin-bottom: 10px; 324 | padding: 7px; 325 | } 326 | 327 | div.admonition dt { 328 | font-weight: bold; 329 | } 330 | 331 | div.admonition dl { 332 | margin-bottom: 0; 333 | } 334 | 335 | p.admonition-title { 336 | margin: 0px 10px 5px 0px; 337 | font-weight: bold; 338 | } 339 | 340 | div.body p.centered { 341 | text-align: center; 342 | margin-top: 25px; 343 | } 344 | 345 | /* -- tables ---------------------------------------------------------------- */ 346 | 347 | table.docutils { 348 | border: 0; 349 | border-collapse: collapse; 350 | } 351 | 352 | table.align-center { 353 | margin-left: auto; 354 | margin-right: auto; 355 | } 356 | 357 | table caption span.caption-number { 358 | font-style: italic; 359 | } 360 | 361 | table caption span.caption-text { 362 | } 363 | 364 | table.docutils td, table.docutils th { 365 | padding: 1px 8px 1px 5px; 366 | border-top: 0; 367 | border-left: 0; 368 | border-right: 0; 369 | border-bottom: 1px solid #aaa; 370 | } 371 | 372 | table.footnote td, table.footnote th { 373 | border: 0 !important; 374 | } 375 | 376 | th { 377 | text-align: left; 378 | padding-right: 5px; 379 | } 380 | 381 | table.citation { 382 | border-left: solid 1px gray; 383 | margin-left: 1px; 384 | } 385 | 386 | table.citation td { 387 | border-bottom: none; 388 | } 389 | 390 | /* -- figures --------------------------------------------------------------- */ 391 | 392 | div.figure { 393 | margin: 0.5em; 394 | padding: 0.5em; 395 | } 396 | 397 | div.figure p.caption { 398 | padding: 0.3em; 399 | } 400 | 401 | div.figure p.caption span.caption-number { 402 | font-style: italic; 403 | } 404 | 405 | div.figure p.caption span.caption-text { 406 | } 407 | 408 | /* -- field list styles ----------------------------------------------------- */ 409 | 410 | table.field-list td, table.field-list th { 411 | border: 0 !important; 412 | } 413 | 414 | .field-list ul { 415 | margin: 0; 416 | padding-left: 1em; 417 | } 418 | 419 | .field-list p { 420 | margin: 0; 421 | } 422 | 423 | .field-name { 424 | -moz-hyphens: manual; 425 | -ms-hyphens: manual; 426 | -webkit-hyphens: manual; 427 | hyphens: manual; 428 | } 429 | 430 | /* -- other body styles ----------------------------------------------------- */ 431 | 432 | ol.arabic { 433 | list-style: decimal; 434 | } 435 | 436 | ol.loweralpha { 437 | list-style: lower-alpha; 438 | } 439 | 440 | ol.upperalpha { 441 | list-style: upper-alpha; 442 | } 443 | 444 | ol.lowerroman { 445 | list-style: lower-roman; 446 | } 447 | 448 | ol.upperroman { 449 | list-style: upper-roman; 450 | } 451 | 452 | dl { 453 | margin-bottom: 15px; 454 | } 455 | 456 | dd p { 457 | margin-top: 0px; 458 | } 459 | 460 | dd ul, dd table { 461 | margin-bottom: 10px; 462 | } 463 | 464 | dd { 465 | margin-top: 3px; 466 | margin-bottom: 10px; 467 | margin-left: 30px; 468 | } 469 | 470 | dt:target, span.highlighted { 471 | background-color: #fbe54e; 472 | } 473 | 474 | rect.highlighted { 475 | fill: #fbe54e; 476 | } 477 | 478 | dl.glossary dt { 479 | font-weight: bold; 480 | font-size: 1.1em; 481 | } 482 | 483 | .optional { 484 | font-size: 1.3em; 485 | } 486 | 487 | .sig-paren { 488 | font-size: larger; 489 | } 490 | 491 | .versionmodified { 492 | font-style: italic; 493 | } 494 | 495 | .system-message { 496 | background-color: #fda; 497 | padding: 5px; 498 | border: 3px solid red; 499 | } 500 | 501 | .footnote:target { 502 | background-color: #ffa; 503 | } 504 | 505 | .line-block { 506 | display: block; 507 | margin-top: 1em; 508 | margin-bottom: 1em; 509 | } 510 | 511 | .line-block .line-block { 512 | margin-top: 0; 513 | margin-bottom: 0; 514 | margin-left: 1.5em; 515 | } 516 | 517 | .guilabel, .menuselection { 518 | font-family: sans-serif; 519 | } 520 | 521 | .accelerator { 522 | text-decoration: underline; 523 | } 524 | 525 | .classifier { 526 | font-style: oblique; 527 | } 528 | 529 | abbr, acronym { 530 | border-bottom: dotted 1px; 531 | cursor: help; 532 | } 533 | 534 | /* -- code displays --------------------------------------------------------- */ 535 | 536 | pre { 537 | overflow: auto; 538 | overflow-y: hidden; /* fixes display issues on Chrome browsers */ 539 | } 540 | 541 | span.pre { 542 | -moz-hyphens: none; 543 | -ms-hyphens: none; 544 | -webkit-hyphens: none; 545 | hyphens: none; 546 | } 547 | 548 | td.linenos pre { 549 | padding: 5px 0px; 550 | border: 0; 551 | background-color: transparent; 552 | color: #aaa; 553 | } 554 | 555 | table.highlighttable { 556 | margin-left: 0.5em; 557 | } 558 | 559 | table.highlighttable td { 560 | padding: 0 0.5em 0 0.5em; 561 | } 562 | 563 | div.code-block-caption { 564 | padding: 2px 5px; 565 | font-size: small; 566 | } 567 | 568 | div.code-block-caption code { 569 | background-color: transparent; 570 | } 571 | 572 | div.code-block-caption + div > div.highlight > pre { 573 | margin-top: 0; 574 | } 575 | 576 | div.code-block-caption span.caption-number { 577 | padding: 0.1em 0.3em; 578 | font-style: italic; 579 | } 580 | 581 | div.code-block-caption span.caption-text { 582 | } 583 | 584 | div.literal-block-wrapper { 585 | padding: 1em 1em 0; 586 | } 587 | 588 | div.literal-block-wrapper div.highlight { 589 | margin: 0; 590 | } 591 | 592 | code.descname { 593 | background-color: transparent; 594 | font-weight: bold; 595 | font-size: 1.2em; 596 | } 597 | 598 | code.descclassname { 599 | background-color: transparent; 600 | } 601 | 602 | code.xref, a code { 603 | background-color: transparent; 604 | font-weight: bold; 605 | } 606 | 607 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { 608 | background-color: transparent; 609 | } 610 | 611 | .viewcode-link { 612 | float: right; 613 | } 614 | 615 | .viewcode-back { 616 | float: right; 617 | font-family: sans-serif; 618 | } 619 | 620 | div.viewcode-block:target { 621 | margin: -1px -10px; 622 | padding: 0 10px; 623 | } 624 | 625 | /* -- math display ---------------------------------------------------------- */ 626 | 627 | img.math { 628 | vertical-align: middle; 629 | } 630 | 631 | div.body div.math p { 632 | text-align: center; 633 | } 634 | 635 | span.eqno { 636 | float: right; 637 | } 638 | 639 | span.eqno a.headerlink { 640 | position: relative; 641 | left: 0px; 642 | z-index: 1; 643 | } 644 | 645 | div.math:hover a.headerlink { 646 | visibility: visible; 647 | } 648 | 649 | /* -- printout stylesheet --------------------------------------------------- */ 650 | 651 | @media print { 652 | div.document, 653 | div.documentwrapper, 654 | div.bodywrapper { 655 | margin: 0 !important; 656 | width: 100%; 657 | } 658 | 659 | div.sphinxsidebar, 660 | div.related, 661 | div.footer, 662 | #top-link { 663 | display: none; 664 | } 665 | } -------------------------------------------------------------------------------- /docs/_modules/cli.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | cli — google_streetview 1.2.9 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 32 | 33 |
34 |
35 |
36 |
37 | 38 |

Source code for cli

 39 | # -*- coding: utf-8 -*-
 40 | 
 41 | """
 42 |   Usage:
 43 |     google_streetview [--optional]
 44 |     google_streetview [-positional] ...
 45 |   
 46 |   A command line tool for Google Street View search.
 47 |   
 48 |   Positional arguments:
 49 |     -h                show this help message and exit
 50 |     -i                show documentation in browser
 51 |     -a                show optional arguments in browser
 52 |     -s <arg>=<value>  set default optional arguments
 53 |     -r <arg>          remove default arguments
 54 |     -v                view default arguments
 55 |     -d                reset default arguments
 56 |   
 57 |   Optional arguments:
 58 |     --pano            panorama ids (req)
 59 |     --location        text or latitude/longitude (req)
 60 |     --size            image size (default: 640x640)
 61 |     --heading         camera heading 0 to 360
 62 |     --fov             camera zoom up 120 (default: 90)
 63 |     --pitch           camera angle 90 to -90 (default: 0)
 64 |     --site_api        base url for api site
 65 |     --site_metadata   base url for metadata site
 66 |     --save_links      path for links text file
 67 |     --save_metadata   path for metadata JSON file
 68 |     --save_downloads  path for directory of image downloads
 69 |     --option_silent   'True' to disable preview
 70 |     --option_preview  num of results to preview
 71 |     
 72 |     For more arguments use: google_streetview -a
 73 |     
 74 |   Examples:
 75 |     
 76 |     Set developer key arguments
 77 |       > google_streetview -s key="dev_key"
 78 |     
 79 |     Get street view image using location
 80 |       > google_streetview --location=46.414382,10.013988
 81 |       > google_streetview --location=46.414382,10.013988;40.720032,-73.988354
 82 |     
 83 |     Get street view image using panorama id
 84 |       > google_streetview --pano=vPnURflnc8AZu5NMLYRddw
 85 |       > google_streetview --pano=vPnURflnc8AZu5NMLYRddw;A1v2IdX_6HKnIQa2SPyyAg
 86 |       
 87 |     Get 360 panorama using heading
 88 |       > google_streetview --location=46.414382,10.013988 --heading=0;90;180;270 --fov=90
 89 |     
 90 |     Download street view images to "downloads" folder
 91 |       > google_streetview --location=46.414382,10.013988 --save_downloads=downloads
 92 |     
 93 |     Save street view links and metadata
 94 |       > google_streetview --location=46.414382,10.013988 --save_links=links.txt
 95 |       > google_streetview --location=46.414382,10.013988 --save_metadata=metadata.json
 96 |   
 97 |   For more information visit use: google_streetview -i
 98 | """
 99 | 
100 | from google_streetview import helpers
101 | from os.path import isfile
102 | from pkg_resources import resource_filename, Requirement
103 | from pprint import pprint
104 | from sys import argv
105 | from webbrowser import open_new_tab
106 | 
107 | import kwconfig
108 | import google_streetview.api
109 | 
110 | _doc_link = 'https://github.com/rrwen/google_streetview'
111 | _api_link = 'https://developers.google.com/maps/documentation/streetview/intro#url_parameters'
112 |     
113 | 
[docs]def run(argv=argv): 114 | """Runs the google_streetview command line tool. 115 | 116 | This function runs the google_streetview command line tool 117 | in a terminal. It was intended for use inside a py file 118 | (.py) to be executed using python. 119 | 120 | Notes: 121 | * Optional arguments with ``ref_`` are for the ``site`` and ``site_metadata`` parameters in :class:`api.results` 122 | 123 | For distribution, this function must be defined in the following files:: 124 | 125 | # In 'google_streetview/google_streetview/__main__.py' 126 | from .cli import run 127 | run() 128 | 129 | # In 'google_streetview/google_streetview.py' 130 | from google_streetview.cli import run 131 | if __name__ == '__main__': 132 | run() 133 | 134 | # In 'google_streetview/__init__.py' 135 | __entry_points__ = {'console_scripts': ['google_streetview=google_streetview.cli:run']} 136 | 137 | Examples:: 138 | 139 | # Import google_streetview for the cli module 140 | import google_streetview.cli 141 | 142 | # Create command line arguments 143 | argv = [ 144 | 'cli.py', 145 | 'google', 146 | '--searchType=image', 147 | '--build_developerKey=your_dev_key', 148 | '--cx=your_cx_id' 149 | '--num=1' 150 | ] 151 | 152 | # Run command line 153 | google_streetview.cli.run(argv) 154 | 155 | """ 156 | config_file = kwconfig.manage( 157 | file_path=resource_filename(Requirement.parse('google_streetview'), 'google_streetview/config.json'), 158 | defaults={ 159 | 'size': '640x640', 160 | 'fov': '90', 161 | 'pitch': '0', 162 | 'option_silent': 'false', 163 | 'option_preview': '10'} 164 | ) 165 | 166 | # (commands) Main command calls 167 | if len(argv) > 1: 168 | if argv[1] == '-i': # browse docs 169 | open_new_tab(_doc_link) 170 | exit() 171 | elif argv[1] == '-a': # browse arguments 172 | open_new_tab(_api_link) 173 | exit() 174 | config_file.command(argv, i=1, doc=__doc__, quit=True, silent=False) 175 | 176 | # (parse_args) Parse command arguments into dict 177 | kwargs = kwconfig.parse(argv[1:]) 178 | kwargs = config_file.add(kwargs) 179 | 180 | # (split_args) Split args into build, cse, and save arguments 181 | siteargs = {} 182 | apiargs = {} 183 | saveargs = {} 184 | optionargs = {} 185 | for k, v in kwargs.items(): 186 | if 'site_' == k[0:4]: 187 | siteargs[k[4:]] = v 188 | elif 'save_' == k[0:5]: 189 | saveargs[k[5:]] = v 190 | elif 'option_' == k[0:7]: 191 | optionargs[k[7:]] = v 192 | else: 193 | apiargs[k] = v 194 | 195 | # (api_results) Get google api results 196 | site_api = siteargs['api'] if 'api' in siteargs else 'https://maps.googleapis.com/maps/api/streetview' 197 | site_metadata = siteargs['site_metadata'] if 'metadata' in siteargs else 'https://maps.googleapis.com/maps/api/streetview/metadata' 198 | results = google_streetview.api.results( 199 | helpers.api_list(apiargs), 200 | site_api=site_api, 201 | site_metadata=site_metadata) 202 | 203 | # (api_print) Print a preview of results 204 | if 'silent' in optionargs: 205 | if optionargs['silent'].lower() != 'true': 206 | results.preview(n=int(optionargs['preview'])) 207 | 208 | # (api_save) Save metadata 209 | if 'links' in saveargs: 210 | results.save_links(saveargs['links']) 211 | if 'metadata' in saveargs: 212 | results.save_metadata(saveargs['metadata']) 213 | 214 | # (api_download) Download links 215 | if 'downloads' in saveargs: 216 | results.download_links(saveargs['downloads'])
217 | 218 |
219 | 220 |
221 |
222 |
223 | 239 |
240 |
241 | 254 | 258 | 259 | -------------------------------------------------------------------------------- /docs/_modules/api.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | api — google_streetview 1.2.9 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 32 | 33 |
34 |
35 |
36 |
37 | 38 |

Source code for api

 39 | # -*- coding: utf-8 -*-
 40 | 
 41 | from google_streetview import helpers
 42 | from os import path, makedirs
 43 | from pprint import pprint
 44 | try:
 45 |   from urllib.parse import urlencode
 46 | except ImportError:
 47 |   from urllib import urlencode
 48 | 
 49 | import json
 50 | import requests
 51 | 
 52 | 
[docs]class results: 53 | """Google Street View Image API results. 54 | 55 | Uses the `Google Street View Image API <https://developers.google.com/maps/documentation/streetview/>`_ 56 | to search for street level imagery. 57 | 58 | Args: 59 | params (listof dict): 60 | List of dict containing batch `street view URL parameters <https://developers.google.com/maps/documentation/streetview/intro>`_. 61 | site_api(str): 62 | The site for the URL request (example: https://maps.googleapis.com/maps/api/streetview). 63 | site_metadata(str): 64 | The site for the URL `metadata <https://developers.google.com/maps/documentation/streetview/metadata>`_ request (example: https://maps.googleapis.com/maps/api/streetview/metadata). 65 | 66 | Attributes: 67 | params (listof dict): 68 | Same as argument ``params`` for reference of inputs. 69 | links (listof str): 70 | List of str containing street view URL requests. 71 | metadata (listof dict): 72 | Objects returned from `street view metadata request <https://developers.google.com/maps/documentation/streetview/metadata>`_. 73 | metadata_links (listof str): 74 | List of str containing street view URL metadata requests. 75 | 76 | Examples: 77 | :: 78 | 79 | # Import google_streetview for the api module 80 | import google_streetview.api 81 | 82 | # Define parameters for street view api 83 | params = [{ 84 | 'size': '600x300', # max 640x640 pixels 85 | 'location': '46.414382,10.013988', 86 | 'heading': '151.78', 87 | 'pitch': '-0.76', 88 | 'key': 'your_dev_key' 89 | }] 90 | 91 | # Create a results object 92 | results = google_streetview.api.results(params) 93 | 94 | # Preview results 95 | results.preview() 96 | 97 | # Download images to directory 'downloads' 98 | results.download_links('downloads') 99 | 100 | # Save links 101 | results.save_links('links.txt') 102 | 103 | # Save metadata 104 | results.save_metadata('metadata.json') 105 | """ 106 | def __init__( 107 | self, 108 | params, 109 | site_api='https://maps.googleapis.com/maps/api/streetview', 110 | site_metadata='https://maps.googleapis.com/maps/api/streetview/metadata'): 111 | 112 | # (params) Set default params 113 | defaults = { 114 | 'size': '640x640' 115 | } 116 | for i in range(len(params)): 117 | for k in defaults: 118 | if k not in params[i]: 119 | params[i][k] = defaults[k] 120 | self.params = params 121 | 122 | # (image) Create image api links from parameters 123 | self.links = [site_api + '?' + urlencode(p) for p in params] 124 | 125 | # (metadata) Create metadata api links and data from parameters 126 | self.metadata_links = [site_metadata + '?' + urlencode(p) for p in params] 127 | self.metadata = [requests.get(url, stream=True).json() for url in self.metadata_links] 128 | 129 | 157 | 158 |
[docs] def preview(self, n=10, k=['date', 'location', 'pano_id', 'status'], kheader='pano_id'): 159 | """Print a preview of the request results. 160 | 161 | Args: 162 | n (int): 163 | Maximum number of requests to preview 164 | k (str): 165 | Keys in :class:`api.results`.metadata to preview 166 | kheader (str): 167 | Key in :class:`api.results`.metadata[``k``] to use as the header 168 | """ 169 | items = self.metadata 170 | 171 | # (cse_print) Print results 172 | for i, kv in enumerate(items[:n]): 173 | 174 | # (print_header) Print result header 175 | header = '\n[' + str(i) + '] ' + kv[kheader] 176 | print(header) 177 | print('=' * len(header)) 178 | 179 | # (print_metadata) Print result metadata 180 | for ki in k: 181 | if ki in kv: 182 | if ki == 'location': 183 | print(ki + ': \n lat: ' + str(kv[ki]['lat']) + '\n lng: ' + str(kv[ki]['lng'])) 184 | else: 185 | print(ki + ': ' + str(kv[ki]))
186 | 187 | 203 | 204 |
[docs] def save_metadata(self, file_path): 205 | """Save Google Street View metadata from parameter queries. 206 | 207 | Args: 208 | file_path (str): 209 | Path of the file with extension to save the :class:`api.results`.metadata 210 | """ 211 | with open(file_path, 'w+') as out_file: 212 | json.dump(self.metadata, out_file)
213 | 214 |
215 | 216 |
217 |
218 |
219 | 235 |
236 |
237 | 250 | 254 | 255 | -------------------------------------------------------------------------------- /docs/_static/searchtools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * searchtools.js_t 3 | * ~~~~~~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for the full-text search. 6 | * 7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | 13 | /* Non-minified version JS is _stemmer.js if file is provided */ 14 | /** 15 | * Porter Stemmer 16 | */ 17 | var Stemmer = function() { 18 | 19 | var step2list = { 20 | ational: 'ate', 21 | tional: 'tion', 22 | enci: 'ence', 23 | anci: 'ance', 24 | izer: 'ize', 25 | bli: 'ble', 26 | alli: 'al', 27 | entli: 'ent', 28 | eli: 'e', 29 | ousli: 'ous', 30 | ization: 'ize', 31 | ation: 'ate', 32 | ator: 'ate', 33 | alism: 'al', 34 | iveness: 'ive', 35 | fulness: 'ful', 36 | ousness: 'ous', 37 | aliti: 'al', 38 | iviti: 'ive', 39 | biliti: 'ble', 40 | logi: 'log' 41 | }; 42 | 43 | var step3list = { 44 | icate: 'ic', 45 | ative: '', 46 | alize: 'al', 47 | iciti: 'ic', 48 | ical: 'ic', 49 | ful: '', 50 | ness: '' 51 | }; 52 | 53 | var c = "[^aeiou]"; // consonant 54 | var v = "[aeiouy]"; // vowel 55 | var C = c + "[^aeiouy]*"; // consonant sequence 56 | var V = v + "[aeiou]*"; // vowel sequence 57 | 58 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 59 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 60 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 61 | var s_v = "^(" + C + ")?" + v; // vowel in stem 62 | 63 | this.stemWord = function (w) { 64 | var stem; 65 | var suffix; 66 | var firstch; 67 | var origword = w; 68 | 69 | if (w.length < 3) 70 | return w; 71 | 72 | var re; 73 | var re2; 74 | var re3; 75 | var re4; 76 | 77 | firstch = w.substr(0,1); 78 | if (firstch == "y") 79 | w = firstch.toUpperCase() + w.substr(1); 80 | 81 | // Step 1a 82 | re = /^(.+?)(ss|i)es$/; 83 | re2 = /^(.+?)([^s])s$/; 84 | 85 | if (re.test(w)) 86 | w = w.replace(re,"$1$2"); 87 | else if (re2.test(w)) 88 | w = w.replace(re2,"$1$2"); 89 | 90 | // Step 1b 91 | re = /^(.+?)eed$/; 92 | re2 = /^(.+?)(ed|ing)$/; 93 | if (re.test(w)) { 94 | var fp = re.exec(w); 95 | re = new RegExp(mgr0); 96 | if (re.test(fp[1])) { 97 | re = /.$/; 98 | w = w.replace(re,""); 99 | } 100 | } 101 | else if (re2.test(w)) { 102 | var fp = re2.exec(w); 103 | stem = fp[1]; 104 | re2 = new RegExp(s_v); 105 | if (re2.test(stem)) { 106 | w = stem; 107 | re2 = /(at|bl|iz)$/; 108 | re3 = new RegExp("([^aeiouylsz])\\1$"); 109 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 110 | if (re2.test(w)) 111 | w = w + "e"; 112 | else if (re3.test(w)) { 113 | re = /.$/; 114 | w = w.replace(re,""); 115 | } 116 | else if (re4.test(w)) 117 | w = w + "e"; 118 | } 119 | } 120 | 121 | // Step 1c 122 | re = /^(.+?)y$/; 123 | if (re.test(w)) { 124 | var fp = re.exec(w); 125 | stem = fp[1]; 126 | re = new RegExp(s_v); 127 | if (re.test(stem)) 128 | w = stem + "i"; 129 | } 130 | 131 | // Step 2 132 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; 133 | if (re.test(w)) { 134 | var fp = re.exec(w); 135 | stem = fp[1]; 136 | suffix = fp[2]; 137 | re = new RegExp(mgr0); 138 | if (re.test(stem)) 139 | w = stem + step2list[suffix]; 140 | } 141 | 142 | // Step 3 143 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; 144 | if (re.test(w)) { 145 | var fp = re.exec(w); 146 | stem = fp[1]; 147 | suffix = fp[2]; 148 | re = new RegExp(mgr0); 149 | if (re.test(stem)) 150 | w = stem + step3list[suffix]; 151 | } 152 | 153 | // Step 4 154 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; 155 | re2 = /^(.+?)(s|t)(ion)$/; 156 | if (re.test(w)) { 157 | var fp = re.exec(w); 158 | stem = fp[1]; 159 | re = new RegExp(mgr1); 160 | if (re.test(stem)) 161 | w = stem; 162 | } 163 | else if (re2.test(w)) { 164 | var fp = re2.exec(w); 165 | stem = fp[1] + fp[2]; 166 | re2 = new RegExp(mgr1); 167 | if (re2.test(stem)) 168 | w = stem; 169 | } 170 | 171 | // Step 5 172 | re = /^(.+?)e$/; 173 | if (re.test(w)) { 174 | var fp = re.exec(w); 175 | stem = fp[1]; 176 | re = new RegExp(mgr1); 177 | re2 = new RegExp(meq1); 178 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 179 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) 180 | w = stem; 181 | } 182 | re = /ll$/; 183 | re2 = new RegExp(mgr1); 184 | if (re.test(w) && re2.test(w)) { 185 | re = /.$/; 186 | w = w.replace(re,""); 187 | } 188 | 189 | // and turn initial Y back to y 190 | if (firstch == "y") 191 | w = firstch.toLowerCase() + w.substr(1); 192 | return w; 193 | } 194 | } 195 | 196 | 197 | 198 | /** 199 | * Simple result scoring code. 200 | */ 201 | var Scorer = { 202 | // Implement the following function to further tweak the score for each result 203 | // The function takes a result array [filename, title, anchor, descr, score] 204 | // and returns the new score. 205 | /* 206 | score: function(result) { 207 | return result[4]; 208 | }, 209 | */ 210 | 211 | // query matches the full name of an object 212 | objNameMatch: 11, 213 | // or matches in the last dotted part of the object name 214 | objPartialMatch: 6, 215 | // Additive scores depending on the priority of the object 216 | objPrio: {0: 15, // used to be importantResults 217 | 1: 5, // used to be objectResults 218 | 2: -5}, // used to be unimportantResults 219 | // Used when the priority is not in the mapping. 220 | objPrioDefault: 0, 221 | 222 | // query found in title 223 | title: 15, 224 | // query found in terms 225 | term: 5 226 | }; 227 | 228 | 229 | 230 | 231 | 232 | var splitChars = (function() { 233 | var result = {}; 234 | var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, 235 | 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, 236 | 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, 237 | 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, 238 | 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, 239 | 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, 240 | 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, 241 | 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, 242 | 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, 243 | 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; 244 | var i, j, start, end; 245 | for (i = 0; i < singles.length; i++) { 246 | result[singles[i]] = true; 247 | } 248 | var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], 249 | [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], 250 | [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], 251 | [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], 252 | [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], 253 | [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], 254 | [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], 255 | [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], 256 | [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], 257 | [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], 258 | [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], 259 | [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], 260 | [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], 261 | [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], 262 | [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], 263 | [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], 264 | [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], 265 | [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], 266 | [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], 267 | [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], 268 | [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], 269 | [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], 270 | [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], 271 | [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], 272 | [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], 273 | [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], 274 | [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], 275 | [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], 276 | [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], 277 | [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], 278 | [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], 279 | [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], 280 | [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], 281 | [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], 282 | [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], 283 | [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], 284 | [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], 285 | [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], 286 | [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], 287 | [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], 288 | [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], 289 | [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], 290 | [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], 291 | [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], 292 | [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], 293 | [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], 294 | [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], 295 | [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], 296 | [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; 297 | for (i = 0; i < ranges.length; i++) { 298 | start = ranges[i][0]; 299 | end = ranges[i][1]; 300 | for (j = start; j <= end; j++) { 301 | result[j] = true; 302 | } 303 | } 304 | return result; 305 | })(); 306 | 307 | function splitQuery(query) { 308 | var result = []; 309 | var start = -1; 310 | for (var i = 0; i < query.length; i++) { 311 | if (splitChars[query.charCodeAt(i)]) { 312 | if (start !== -1) { 313 | result.push(query.slice(start, i)); 314 | start = -1; 315 | } 316 | } else if (start === -1) { 317 | start = i; 318 | } 319 | } 320 | if (start !== -1) { 321 | result.push(query.slice(start)); 322 | } 323 | return result; 324 | } 325 | 326 | 327 | 328 | 329 | /** 330 | * Search Module 331 | */ 332 | var Search = { 333 | 334 | _index : null, 335 | _queued_query : null, 336 | _pulse_status : -1, 337 | 338 | init : function() { 339 | var params = $.getQueryParameters(); 340 | if (params.q) { 341 | var query = params.q[0]; 342 | $('input[name="q"]')[0].value = query; 343 | this.performSearch(query); 344 | } 345 | }, 346 | 347 | loadIndex : function(url) { 348 | $.ajax({type: "GET", url: url, data: null, 349 | dataType: "script", cache: true, 350 | complete: function(jqxhr, textstatus) { 351 | if (textstatus != "success") { 352 | document.getElementById("searchindexloader").src = url; 353 | } 354 | }}); 355 | }, 356 | 357 | setIndex : function(index) { 358 | var q; 359 | this._index = index; 360 | if ((q = this._queued_query) !== null) { 361 | this._queued_query = null; 362 | Search.query(q); 363 | } 364 | }, 365 | 366 | hasIndex : function() { 367 | return this._index !== null; 368 | }, 369 | 370 | deferQuery : function(query) { 371 | this._queued_query = query; 372 | }, 373 | 374 | stopPulse : function() { 375 | this._pulse_status = 0; 376 | }, 377 | 378 | startPulse : function() { 379 | if (this._pulse_status >= 0) 380 | return; 381 | function pulse() { 382 | var i; 383 | Search._pulse_status = (Search._pulse_status + 1) % 4; 384 | var dotString = ''; 385 | for (i = 0; i < Search._pulse_status; i++) 386 | dotString += '.'; 387 | Search.dots.text(dotString); 388 | if (Search._pulse_status > -1) 389 | window.setTimeout(pulse, 500); 390 | } 391 | pulse(); 392 | }, 393 | 394 | /** 395 | * perform a search for something (or wait until index is loaded) 396 | */ 397 | performSearch : function(query) { 398 | // create the required interface elements 399 | this.out = $('#search-results'); 400 | this.title = $('

' + _('Searching') + '

').appendTo(this.out); 401 | this.dots = $('').appendTo(this.title); 402 | this.status = $('

').appendTo(this.out); 403 | this.output = $('