#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Requires pyshp: https://pypi.python.org/pypi/pyshp
#

import os
import shapefile
import shutil
import tempfile
import zipfile

ROOT = '/path/to/folder/containing/zips/'

# For example.
FIELDS = (
    ('Country', 'C', 50, 0),
    ('POINT_X', 'N', 19, 11),
    ('POINT_Y', 'N', 19, 11),
)

# grab a list of the input files
zips = []
for fname in os.listdir(ROOT):
    if fname.endswith('.zip'):
        zips.append(fname)


shape = shapefile.Writer(shapefile.POINT)

# Set up the structure of the attribute table. If they're all the same, you
# could set this on the first iteration of the below loop by reading from
# sf.fields
for field in FIELDS:
    shape.field(*field)

for i, fname in enumerate(zips):
    # extract the zip into a temporary folder
    out = tempfile.mkdtemp()
    zf = zipfile.ZipFile(os.path.join(ROOT, fname))
    zf.extractall(out)

    # Read the shapefile ready for copying
    shp = filter(lambda x: x.endswith('.shp'), zf.namelist())[0]
    sf = shapefile.Reader(os.path.join(out, shp))

    try:
        for r in sf.shapeRecords():
            # If not all of the shapefiles we're merging have all of the field
            # data available, we can create a blank row and fill in what we can
            # from the available data.
            row = [0 for f in FIELDS]
            for j, val in enumerate(r.record):
                row[j] = val
            shape.record(*row)
            shape._shapes.append(r.shape)
    except Exception as ex:
        print 'ERR: %s' % zf.fp.name
        continue

    # Bin the temporary folder
    shutil.rmtree(out)

shape.save('merged')