I found a webcam in your neighborhood. As I type, I see your dog easing out a steady stream of its steady-stream onto your neighbor's freshly lacquered patio. Don't believe me? see the results for yourself:

(Unsecure) Webcams Around the World

How?

It first started with this link, And then this, And finally this.

These three simple google searches reveal security cameras around the world that are ironically left unsecure for the entire internet to see. While I used Google for illustrative purposes above, Yahoo works pretty much the same when it comes to these particular searches. More importantly, there is a nice python interface to Yahoo called pYsearch, which means that you can use it to programatically harvest urls to thousands of these cameras. Below, I use this module to locate the first 40 webcam urls on a Yahoo Search Page:

from yahoo.search import web

# Do the search
query_string = 'inurl:"viewerframe?mode=motion"'
s = web.WebSearch("YahooDemo", query=query_string, results=40, start=0)
result_list =  s.parse_results().results

# Extract the urls
webcam_urls = [ result['Url'] for result in result_list ]

Geolocating the Cameras

By itself, this is already cool, but to make things a little more interesting, I wanted to identify the exotic locations these cameras were spying on day-in and day-out. There happens to be a wonderful web service that does geolocation on IP addresses, and they have an open API available at ipinfodb.

In order to use it, we must first translate the webcam URLs into IP addresses if it's not done for us already. Below is a utility function I wrote to accomplish this.

Extract IP Address from URL

def url2ip(url):
    import socket
    from urlparse import urlparse
    basename = urlparse(url)[1].split(':')[0]
    return socket.gethostbyname(basename)

# obtain a list of ip addresses
ip_list = [ url2ip(url) for url in webcam_urls ]

After extracting the IP address from all of these urls, you're now ready to geolocate the IP addresses using ipinfodb, The function below, given the IP address, will return the longitude, latitude and various other pieces of geographical information associated with the IP address.

Geolocate IP addresses

def ip2geo(ip_addr):
    from urllib import urlopen
    from xml.dom import minidom

    # setup url and request
    url =  u"http://ipinfodb.com/ip_query.php?ip=%s" % ip_addr
    response = urlopen(url)

    # Convert response into a dictionary with key:value pairs
    results = {}
    doc = minidom.parse(response)
    for node in doc.firstChild.childNodes:
        if node.firstChild: 
            results[node.nodeName] = node.firstChild.nodeValue
    return results

Example output

In [2]: ip2geo("74.125.45.100")

Out[2]: 
{u'City': u'Mountain View',
 u'CountryCode': u'US',
 u'CountryName': u'United States',
 u'Dstoffset': u'-7.0',
 u'Gmtoffset': u'-8.0',
 u'Ip': u'74.125.45.100',
 u'Latitude': u'37.4192',
 u'Longitude': u'-122.057',
 u'RegionCode': u'06',
 u'RegionName': u'California',
 u'Status': u'OK',
 u'ZipPostalCode': u'94043'}

Plotting the Locations on a Google Map

Google has a fairly simple mechanism that allows developers to create custom google maps. You first load their map widget onto your webpage using some boiler-plate javascript/html:

Google Maps Basic Setup

These two lines -

var geoXml = new GGeoXml("http://code.google.com/apis/kml/documentation/KML_Samples.kml" );
map.addOverlay(geoXml);

- in the boilerplate code will then load an external KML file, which is where you can put all of the anotations to the map such as placemarkers, shape boundaries and etc. Note that since you will be generating your own KML file for pinpointing the camera locations, you must point the boiler plate code to reflect this change.

At this point we have a list of longitude/latitude coordinates obtained from geolocating IP addresses associated with webcam URLs. To plot these camera locations on a Google map, we will generate a KML file using a small utility that I wrote:

pygmap - A KML Generator

It essentially gives you a pythonic interface for generating KML files like these:

Sample KML - A placemark over Mountain View,CA

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Placemark>
    <name>Simple placemark</name>
    <description>
        A longer description for the placemark. It can include <b>HTML</b>
    </description>
    <Point>
      <coordinates>39,39,0</coordinates>
    </Point>
  </Placemark>
</kml>

All we have to do now is to loop over our list of longitudes and latitudes, and plot them onto the Google Map using KML. You can see this in action from the code below:

from pygmap import GMap
m = GMap()

for ipaddr in ip_list:

    # Geolocate ipaddress
    geo = ip2geo(ipaddr)
    lon = float( geo['Longitude'] )
    lat = float( geo['Latitude'] )
    m.add_placemark(lon=lon, lat=lat, title="Camera", desc="this is a <b>Camera</b>")

# Output the result KML
print m.renderKML()

So there you have it, a KML file that has all of the camera locations plotted. Just make sure to point the boilerplate google-map html page to your own generated KML file and you should see results like the map at the beginning of this post:

Webcams Around the World

Source Code

pygmap - A KML Placemark Generator
Google Maps HTML Boilerplate