Is there a Python Lib for requesting WMS/WFS and saving as image/PDF?
There is OWSLib which should provide exactly what you need.
OWSLib is a Python package for client programming with Open Geospatial Consortium (OGC) web service (hence OWS) interface standards, and their related content models.
OWSLib provides a common API for accessing service metadata and wrappers for numerous OGC Web Service interfaces.
Documentation and examples here. Client in this context means it is a client application to a WMS/WFS server - it can be run on a server if required.
After you added more details to your answer it looks like the MapFish print application fits your needs exactly. It is a Java application that can be integrated with OpenLayers and stitches tiles, WMS, WFS etc. together and produces a PDF.
As it is a command line application it can be manipulated with a Python wrapper. See following links for more details:
http://geographika.co.uk/mapfish-print-module-for-iis
https://github.com/amercader/MapFish-Print-IIS
You can use the python urllib library to call a WMS directly and write the response out to a file. There is a decent example of using urllib in this answer. Just replace the URL with one for a WMS, e.g. http://some.wms.service?request=GetMap&VERSION=1.1.1&BBOX=141.00,-29.00,141.80,-28.40&SRS=EPSG:4326&LAYERS=LANDSAT_MOSAIC&WIDTH=800&HEIGHT=600&FORMAT=image/png.
You can also use the GDAL library to access WMS (http://www.gdal.org/frmt_wms.html) and the OGR library to access WFS (http://www.gdal.org/ogr/drv_wfs.html)
If you wanted to create a picture of the WFS, you could use the gdal.RasterizeLayer function to create a jpg. There is an example here.
Here Is a simple example. On server side:
def get_wfs():
'''
Get data from wfs server. Example url is:
http://192.168.0.1:8080/geoserver/wfs?request=GetFeature&version=1.0.0&service=WFS&typeName=ChistaWS:Chista_new_POIs&maxfeatures=20&srsname=EPSG:4326&outputFormat=json
We can add CQL filter like this:
CQL_FILTER=name LIKE 'A%25'
or
CQL_FILTER=type=1913
'''
cql = ''
if request.vars.cql:
cql = urllib.quote_plus(request.vars.cql)
req = 'GetFeature' # request
version = '1.0.0'
service = 'WFS'
typeName = 'Test:Test_Places'
maxfeatures = 200000
if request.vars.mf:
maxfeatures = request.vars.mf
srsname = 'EPSG:4326'
outputFormat = 'json'
# format_options = 'callback:getLayerFeatures_MY'
wfs_url = '%s?request=%s&version=%s&service=%s&typeName=%s&maxfeatures=%s&srsname=%s&outputFormat=%s' % \
(wfs_server, req, version, service, typeName,\
maxfeatures, srsname, outputFormat)
if cql:
# print cql
wfs_url += '&CQL_FILTER=%s'%cql
# print wfs_url
try:
jsonp = urllib2.urlopen(wfs_url).read() # Get the raw server data
except urllib2.HTTPError:
return 'WFS Server <a target="_new" href="%s">%s</a> is down!' % (wfs_server, wfs_server)
# return jsonp
# try:
# apijson = jsonp[ jsonp.index("(") + 1 : jsonp.rindex(")") ]
# except ValueError:
apijson = jsonp
try:
data = sj.loads(apijson)
except sj.JSONDecodeError:
return 'Can not parse data. No JSON! here is the data: <pre>%s</pre>' % apijson
# return data
features =[{
'name':i['properties']['name'],
'type':i['properties']['type'],
'coordinates':i['geometry']['coordinates'],
} for i in data['features']]
# features =[i for i in data['features']]
# return dict(features=features)
return {'result':features, 'length':len(features)}
And in client side using jquery:
$.ajax({
dataType : 'json',
url: wfsurl,
success : function (response) {
if (response.length>0){
$('#'+subitem).empty();
for (var i = 0, len = response.length; i < len; i++) {
name = response.result[i].name;
lng = response.result[i].coordinates[0];
lat = response.result[i].coordinates[1];
// console.log(name, lng, lat)
html = '<li class="li-subitem"><a onclick="lazyview($(this));" lat="'+lat+'" lng="'+lng+'">'+name+'</a></li>';
$('#'+subitem).append(html);
}}
else{
$('#'+subitem).toggle(100);
}}});