问题描述
首先,有名为 campsites.json 的JSON数据文件,数据格式为
{ "type": "FeatureCollection", "name": "DOC_Campsites", "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, "features": [ { "type": "Feature", "properties": { "OBJECTID": 54996, "name": "Rarangi Campsite", "place": "Blenheim area", "region": "Marlborough", "introduction": "Camp next to the beach. Fish, walk, picnic, or simply sit and enjoy the roar of the waves.", "campsiteCategory": "Standard", "status": "OPEN", "numberOfPoweredSites": 0, "numberOfUnpoweredSites": 55, "bookable": "No", "free": null, "facilities": "Water supply", "activities": null, "dogsAllowed": "Dogs with a DOC permit only", "landscape": "Coastal", "access": "Campervan, Car, Caravan", "hasAlerts": "Refer to DOC website for current alerts", "introductionThumbnail": "https://www.doc.govt.nz/thumbs/large/link/1b698c516b714b63b30de03203738e17.jpg", "staticLink": "https://www.doc.govt.nz/link/f5c4e8776bee486aaa1ae8ebdc1e48f8.aspx", "locationString": "Located in Blenheim area", "x": 1687530, "y": 5417097, "assetId": 100030520, "dateLoadedToGIS": "2021-05-28T04:15:08Z", "GlobalID": "{C02F0A50-9316-459A-ADD9-93518E6677EA}" }, "geometry": {"type": "Point","coordinates": [174.04700047400002,-41.39289982899993]} }
, ... ... ] }
全部的campsites.json文件内容下载地址:https://files.cnblogs.com/files/lulight/campsites.json?t=1655124060
修改下面的 server3.py 文件,以达到目标:当用户在浏览器中输入带有区域名称(例如 http://localhost:8080/Marlborough)的 URL 时,这个python服务器应该查询 region=Marlborough 的区域中的 Campsite category 类别为“Great Walk”的 Name + staticLink 数据在页面中
#Author: Sunil Lal #This is a simple HTTP server which listens on port 8080, accepts connection request, and processes the client request #in sepearte threads. It implements basic service functions (methods) which generate HTTP response to service the HTTP requests. #Currently there are 3 service functions; default, welcome and getFile. The process function maps the requet URL pattern to the service function. #When the requested resource in the URL is empty, the default function is called which currently invokes the welcome function. #The welcome service function responds with a simple HTTP response: "Welcome to my homepage". #The getFile service function fetches the requested html or img file and generates an HTTP response containing the file contents and appropriate headers. #To extend this server's functionality, define your service function(s), and map it to suitable URL pattern in the process function. #This web server runs on python v3 #Usage: execute this program, open your browser (preferably chrome) and type http://servername:8080 #e.g. if server.py and broswer are running on the same machine, then use http://localhost:8080 from socket import * import _thread serverSocket = socket(AF_INET, SOCK_STREAM) serverPort = 8080 serverSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) serverSocket.bind(("", serverPort)) serverSocket.listen(5) print('The server is running') # Server should be up and running and listening to the incoming connections #Extract the given header value from the HTTP request message def getHeader(message, header): if message.find(header) > -1: value = message.split(header)[1].split()[0] else: value = None return value #service function to fetch the requested file, and send the contents back to the client in a HTTP response. def getFile(filename): try: # open and read the file contents. This becomes the body of the HTTP response f = open(filename, "rb") body = f.read() header = ("HTTP/1.1 200 OK\r\n\r\n").encode() except IOError: # Send HTTP response message for resource not found header = "HTTP/1.1 404 Not Found\r\n\r\n".encode() body = "<html><head></head><body><h1>404 Not Found</h1></body></html>\r\n".encode() return header, body #service function to generate HTTP response with a simple welcome message def welcome(message): header = "HTTP/1.1 200 OK\r\n\r\n".encode() body = ("<html><head></head><body><h1>Welcome to my homepage</h1></body></html>\r\n").encode() return header, body #default service function def default(message): header, body = welcome(message) return header, body #We process client request here. The requested resource in the URL is mapped to a service function which generates the HTTP reponse #that is eventually returned to the client. def process(connectionSocket) : # Receives the request message from the client message = connectionSocket.recv(1024).decode() if len(message) > 1: # Extract the path of the requested object from the message # Because the extracted path of the HTTP request includes # a character '/', we read the path from the second character resource = message.split()[1][1:] #map requested resource (contained in the URL) to specific function which generates HTTP response if resource == "": responseHeader, responseBody = default(message) elif resource == "welcome": responseHeader,responseBody = welcome(message) else: responseHeader,responseBody = getFile(resource) # Send the HTTP response header line to the connection socket connectionSocket.send(responseHeader) # Send the content of the HTTP body (e.g. requested file) to the connection socket connectionSocket.send(responseBody) # Close the client connection socket connectionSocket.close() #Main web server loop. It simply accepts TCP connections, and get the request processed in seperate threads. while True: # Set up a new connection from the client connectionSocket, addr = serverSocket.accept() #Clients timeout after 60 seconds of inactivity and must reconnect. connectionSocket.settimeout(60) # start new thread to handle incoming request _thread.start_new_thread(process,(connectionSocket,))
问题解答
在server3.py 文件中,实现了默认Default,welcome 和 getFile 方法,当访问URL为 http://localhost:8080 时,调用default方法,输出 Welcome to my homepage 信息。同理,当访问URL为 http://localhost:8080/welcome 时,调用welcome方法,同样输出 Welcome to my homepage 信息。 而 getFile 方法,则是读取指定的文件,输出文件内容。所以,本题最重要的代码部分为 getFile方法实现。
当用户在浏览器中输入带有区域名称(例如 http://localhost:8080/Marlborough)的 URL 时,这个python服务器应该查询 region=Marlborough 的区域中的 Campsite category 类别为“Great Walk”的 Name + staticLink 数据在页面中
第一步:引入 JSON 包
import json
第二步:定义 region 和 campsiteCategory的过滤条件 condition1 和 condition2,以及指定filename为 campsites.json (因为这里只是完成题目,所以硬编码在代码中)
filename = "campsites.json" condition1 = "Marlborough" condition2 = "Basic" # "Great Walk"
第三步:开始使用Json.load文件中的数据,把内容转换为 dict对象,然后根据 JSON格式,读取 features 列表,通过for 循环来一条一条的判断 condtion1 和 condition 2,满足条件,通过html拼接为一个Table
def getFile(regionname): try: filename = "campsites.json" condition1 = "Marlborough" condition2 = "Basic" # "Great Walk" # open and read the file contents. This becomes the body of the HTTP response f = open(filename, "rb") jdata = json.load(f) # 查询region=Marlborough的区域中的Campsite category类别为“Great Walk”的Name , site总数并返回 # region=Marlborough ## campsiteCategory =="Great Walk"; # print(jdata['name']); # print(jdata['features'][1]['properties']['region']) # print(type(jdata['features'][1])) outputTable = "" index = 0 for fs in jdata['features']: if fs['properties']['region'] == condition1 and fs['properties']['campsiteCategory'] == condition2: outputTable += "<tr><td>" + \ fs['properties']['name']+"</td><td>" + \ fs['properties']['staticLink']+"</td></tr>" # print(fs['properties']['campsiteCategory']) index += 1 body = ("<html><head></head><body><h1>Welcome to my homepage</h1><br><h2>Total row is " + str(index)+"</h2><br><table>"+outputTable+"</table></body></html>\r\n").encode() header = ("HTTP/1.1 200 OK\r\n\r\n").encode() except IOError: # Send HTTP response message for resource not found header = "HTTP/1.1 404 Not Found\r\n\r\n".encode() body = "<html><head></head><body><h1>404 Not Found</h1></body></html>\r\n".encode() return header, body
第四步:运行 python server3.py, 检验结果
> python server3.py
因为 campsites.json 数据源中,没有同时满足 region =="Marlborough" 和 campsiteCategory =="Great Walk" 的数据。
def getFile(regionname): try: filename = "campsites.json" condition1 = regionname; # "Marlborough" condition2 = "Basic" # "Great Walk"
再次测试的效果如下:
【END】
附录:完整的Server3.py 代码
# Author: Sunil Lal # This is a simple HTTP server which listens on port 8080, accepts connection request, and processes the client request # in sepearte threads. It implements basic service functions (methods) which generate HTTP response to service the HTTP requests. # Currently there are 3 service functions; default, welcome and getFile. The process function maps the requet URL pattern to the service function. # When the requested resource in the URL is empty, the default function is called which currently invokes the welcome function. # The welcome service function responds with a simple HTTP response: "Welcome to my homepage". # The getFile service function fetches the requested html or img file and generates an HTTP response containing the file contents and appropriate headers. # To extend this server's functionality, define your service function(s), and map it to suitable URL pattern in the process function. # This web server runs on python v3 # Usage: execute this program, open your browser (preferably chrome) and type http://servername:8080 # e.g. if server.py and broswer are running on the same machine, then use http://localhost:8080 from socket import * import _thread import json serverSocket = socket(AF_INET, SOCK_STREAM) serverPort = 8080 serverSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) serverSocket.bind(("", serverPort)) serverSocket.listen(5) print('The server is running') # Server should be up and running and listening to the incoming connections # Extract the given header value from the HTTP request message def getHeader(message, header): if message.find(header) > -1: value = message.split(header)[1].split()[0] else: value = None return value # service function to fetch the requested file, and send the contents back to the client in a HTTP response. def getFile(regionname): try: filename = "campsites.json" condition1 = regionname; # "Marlborough" condition2 = "Basic" # "Great Walk" # open and read the file contents. This becomes the body of the HTTP response f = open(filename, "rb") #body = f.read() jdata = json.load(f) # 查询region=Marlborough的区域中的Campsite category类别为“Great Walk”的Name , site总数并返回 # region=Marlborough ## campsiteCategory =="Great Walk"; # print(jdata['name']); # print(jdata['crs']); # print(jdata['features'][1]['properties']['region']) # print(jdata['features'][1]['properties']['campsiteCategory']) # print(type(jdata['features'][1])) outputTable = "" index = 0 for fs in jdata['features']: if fs['properties']['region'] == condition1 and fs['properties']['campsiteCategory'] == condition2: outputTable += "<tr><td>" + \ fs['properties']['name']+"</td><td>" + \ fs['properties']['staticLink']+"</td></tr>" # print(index) # print(fs['properties']['region']) # print(fs['properties']['campsiteCategory']) index += 1 #d = filter(lambda x:x.index) #print(outputTable) body = ("<html><head></head><body><h1>Welcome to my homepage</h1><br><h2>Total row is " + str(index)+"</h2><br><table>"+outputTable+"</table></body></html>\r\n").encode() header = ("HTTP/1.1 200 OK\r\n\r\n").encode() except IOError: # Send HTTP response message for resource not found header = "HTTP/1.1 404 Not Found\r\n\r\n".encode() body = "<html><head></head><body><h1>404 Not Found</h1></body></html>\r\n".encode() return header, body # service function to generate HTTP response with a simple welcome message def welcome(message): header = "HTTP/1.1 200 OK\r\n\r\n".encode() body = ("<html><head></head><body><h1>Welcome to my homepage</h1></body></html>\r\n").encode() return header, body # default service function def default(message): header, body = welcome(message) return header, body # We process client request here. The requested resource in the URL is mapped to a service function which generates the HTTP reponse # that is eventually returned to the client. def process(connectionSocket): # Receives the request message from the client message = connectionSocket.recv(1024).decode() if len(message) > 1: # Extract the path of the requested object from the message # Because the extracted path of the HTTP request includes # a character '/', we read the path from the second character resource = message.split()[1][1:] # map requested resource (contained in the URL) to specific function which generates HTTP response if resource == "": responseHeader, responseBody = default(message) elif resource == "welcome": responseHeader, responseBody = welcome(message) else: responseHeader, responseBody = getFile(resource) # Send the HTTP response header line to the connection socket connectionSocket.send(responseHeader) # Send the content of the HTTP body (e.g. requested file) to the connection socket connectionSocket.send(responseBody) # Close the client connection socket connectionSocket.close() # Main web server loop. It simply accepts TCP connections, and get the request processed in seperate threads. while True: # Set up a new connection from the client connectionSocket, addr = serverSocket.accept() # Clients timeout after 60 seconds of inactivity and must reconnect. connectionSocket.settimeout(60) # start new thread to handle incoming request _thread.start_new_thread(process, (connectionSocket,))
参考资料
...