Street View Snapper

Download location and orientation in Google Street View to a local file.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

Advertisement:

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

Advertisement:

// ==UserScript==
// @name         Street View Snapper
// @name:ja         Street View スナップ
// @namespace    http://tampermonkey.net/
// @version      0.1.1.7
// @description  Download location and orientation in Google Street View to a local file.
// @description:ja  Google Street View 内の位置と方向情報を geoJSON 及び KML 形式でダウンロードします。
// @author       Paul Richter
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=google.com
// @grant        none
// @license      GPL-3.0-or-later
// ==/UserScript==

function is_google_gsv() {
    return location.href.includes("google.com/maps") && location.href.includes('@') && location.href.includes('data=')
}

function is_embedded_gm() {
    return document.querySelector(".gm-iv-address-link") && document.querySelector(".gm-iv-short-address-description")
}

function wrap_xml(name, value) {
    if(name == 'url') {
        value = value.replace('&', '&') ;
    }
    return `<Data name="${name}"><value>${value}</value></Data>`
}

function as_kml(data) {
    let kml_str = "<kml xmlns=\"http://www.opengis.net/kml/2.2\"><Document>\n<Placemark>\n" ;

    const coords = data.geometry.coordinates ;
    const coord_str = `<coordinates>${coords[0]}, ${coords[1]}</coordinates>`

    kml_str += "<Point>" + coord_str + "</Point>"

    kml_str += "<ExtendedData>\n" ;

    Object.entries(data.properties).forEach(([k, v])=> {
        kml_str += wrap_xml(k, v) ;
    }) ;

    kml_str += "</ExtendedData>\n"

    kml_str += "</Placemark>\n</Document>\n</kml>" ;

    return kml_str ;
}

function gsv_long_address() {
    const attribDiv = document.querySelector('[data-attribution-url="//www.google.com/streetview"]') ;

    if(attribDiv) {
        return attribDiv.parentElement.parentElement.parentElement.parentElement.children[1].firstChild.innerText ;
    }
    return null ;
}



function crack_locstr(locstr) {
    const loc_fields = locstr.split(',') ;

    let data = {
        lng:null,
        lat:null,
        height:null,
        zoom:null,
        heading:null,
        tilt:null
    } ;

    loc_fields.forEach((field) => {
        if(field[0] == '@') {
            data.lat = parseFloat(field.slice(1)) ;
            return ;
        }
        const lastChar = field.slice(-1) ;

        if('ahty'.includes(lastChar)) {
            const val = parseFloat(field.slice(0, -1)) ;
            switch(lastChar) {
                case 'a':
                    data.height = val;
                    break;
                case 'h':
                    data.heading = val;
                    break;
                case 't':
                    data.tilt = val;
                    break;
                case 'y':
                    data.zoom = val;
                    break;
                default:
            }
        } else {
            data.lng = parseFloat(field) ;
        }
    }) ;
    return data ;
}

function snap_gsv(label, format) {
    let url = location.href;
    let place = "";

    console.log("Format", format) ;

    if (is_google_gsv()) {
        console.log("This is google maps in street view mode.") ;
        const title_fields = document.title.split(' - ');
        place = title_fields[0] ;

        const place_sub = gsv_long_address() ;
        if (place_sub) {
            place += " - " + place_sub
        }
    } else if (is_embedded_gm()) {
        console.log("This is a site with an embedded google map in street view mode.") ;

        const addressLink = document.querySelector(".gm-iv-address-link") ;
        const anchor = addressLink.getElementsByTagName('a')[0] ;
        url = anchor.getAttribute("href") ;

        place = document.querySelector(".gm-iv-short-address-description").innerText ;
        const place_long = document.querySelector(".gm-iv-long-address-description").innerText ;

        if(place_long.length > 0) {
            place += " - " + place_long ;
        }
        //also check for "gm-iv-profile-url") ;
    } else {
        alert("You are not viewing a Google Street View page") ;
        return ;
    }

    const url_fields = url.split('/');
    const locstr = url_fields.at(-2) ;// '/@'
    const svdata = url_fields.at(-1) ;// '/data='

    const loc_fields = crack_locstr(locstr) ;

    const data={
        type:"Feature",
        geometry: {
            type:"Point",
            coordinates:[loc_fields.lng, loc_fields.lat],
        },
        properties: {
            heading:loc_fields.heading,
            tilt:loc_fields.tilt,
            zoom:loc_fields.zoom,
            label:label,
            place: place,
            url:url
        }
    };

    let dataStr = JSON.stringify(data,null,2) ;
    let extension = ".geojson" ;

    if(format == "kml") {
        dataStr = as_kml(data) ;
        extension = ".kml"
    }

    const blob=new Blob([dataStr],{type:"application/json"});
    const a=document.createElement("a");

    a.href=URL.createObjectURL(blob);
    a.download=`gsvs_${place}_${label}_${Date.now()}${extension}`;
    a.click();
    setTimeout(()=>URL.revokeObjectURL(a.href),1000);
}

window.snap_gsv = snap_gsv ;