使用urllib循环请求

时间:2019-06-28 13:46:32

标签: python urllib

在使用urllib向在线api发送多个循环请求方面寻求帮助。

我目前正在处理一些Python脚本,以帮助我们确定雷达与拟议中的风力涡轮机开发之间的潜在视线问题。

最后一个难题是创建一个高度剖面,以便我们可以快速评估哪些涡轮机可能是问题,哪些不是问题。我一直在尝试操纵here中发现的现有代码来查询我已经签名并拥有密钥的OpenElevation API。

以前,我曾尝试将从GIS软件中提取的高程数据解析为.xyz文件。但是,这很耗时,提取的高程仅精确到小数点后三位。

该代码从radars.csv中读取,然后将该雷达与每个单独的涡轮机配对,发送视线请求。不幸的是,当我反复遇到connection forcibly closedgateway time-out错误返回时,我想一定是在轰炸服务器。

import csv
import math
import urllib.request
import json
import matplotlib.pyplot as plt

##Extract data from radar and turbine csv files##
with open('readfiles/radars.csv') as csvfile: #get radar data
    reader = csv.reader(csvfile, delimiter=',')
    for row in reader:
        #START-END POINT
        P1=[]
        P2=[]

        radarlong=(float(row[0])) #convert to correct data types
        radarlat=(float(row[1]))
        radarheight=(int(row[2]))
        radarname=(row[3])

        P1.append(radarlong)
        P1.append(radarlat)

        ##Open windfarm csv and store variables
        with open('readfiles/windfarms.csv') as csvfile: #get windfarm data
            reader = csv.reader(csvfile, delimiter=',')
            for row in reader:
                windfarmlong = (float(row[0])) #convert to correct data types
                windfarmlat = (float(row[1]))
                windfarmheight = (int(row[2]))
                windfarmname = (row[3])

                P2=[windfarmlong, windfarmlat]

                print(P1, P2)

                #NUMBER OF POINTS
                s=100
                interval_lat=(P2[0]-P1[0])/s #interval for latitude
                interval_lon=(P2[1]-P1[1])/s #interval for longitude

                #SET A NEW VARIABLE FOR START POINT
                lat0=P1[0]
                lon0=P1[1]

                #LATITUDE AND LONGITUDE LIST
                lat_list=[lat0]
                lon_list=[lon0]

                #GENERATING POINTS
                for i in range(s):
                    lat_step=lat0+interval_lat
                    lon_step=lon0+interval_lon
                    lon0=lon_step
                    lat0=lat_step
                    lat_list.append(lat_step)
                    lon_list.append(lon_step)

                #HAVERSINE FUNCTION
                def haversine(lat1,lon1,lat2,lon2):
                    lat1_rad=math.radians(lat1)
                    lat2_rad=math.radians(lat2)
                    lon1_rad=math.radians(lon1)
                    lon2_rad=math.radians(lon2)
                    delta_lat=lat2_rad-lat1_rad
                    delta_lon=lon2_rad-lon1_rad
                    a=math.sqrt((math.sin(delta_lat/2))**2+math.cos(lat1_rad)*math.cos(lat2_rad)*(math.sin(delta_lon/2))**2)
                    d=2*6371000*math.asin(a)
                    return d

                #DISTANCE CALCULATION
                d_list=[]
                for j in range(len(lat_list)):
                    lat_p=lat_list[j]
                    lon_p=lon_list[j]
                    dp=haversine(lat0,lon0,lat_p,lon_p)/1000 #km
                    d_list.append(dp)
                d_list_rev=d_list[::-1] #reverse list


                #CONSTRUCT JSON
                d_ar=[{}]*len(lat_list)
                for i in range(len(lat_list)):
                    d_ar[i]={"latitude":lat_list[i],"longitude":lon_list[i]}
                location={"locations":d_ar}
                json_data=json.dumps(location,skipkeys=int).encode('utf8')

                try:
                    #SEND REQUEST 
                    url="https://api.open-elevation.com/api/v1/lookup"
                    response = urllib.request.Request(url,json_data,headers={'Content-Type': 'application/json'})
                    fp=urllib.request.urlopen(response)

                    #RESPONSE PROCESSING
                    res_byte=fp.read()
                    res_str=res_byte.decode("utf8")
                    js_str=json.loads(res_str)
                    #print (js_mystr)
                    fp.close()

                    #GETTING ELEVATION 
                    response_len=len(js_str['results'])
                    elev_list=[]
                    for j in range(response_len):
                        elev_list.append(js_str['results'][j]['elevation'])

                    #BASIC STAT INFORMATION
                    mean_elev=round((sum(elev_list)/len(elev_list)),3)
                    min_elev=min(elev_list)
                    max_elev=max(elev_list)
                    distance=d_list_rev[-1]

                    #PLOT ELEVATION PROFILE
                    base_reg=0
                    plt.figure(figsize=(10,4))
                    plt.plot(d_list_rev,elev_list)
                    plt.plot([0,distance],[min_elev,min_elev],'--g',label='min: '+str(min_elev)+' m')
                    plt.plot([0,distance],[max_elev,max_elev],'--r',label='max: '+str(max_elev)+' m')
                    plt.plot([0,distance],[mean_elev,mean_elev],'--y',label='ave: '+str(mean_elev)+' m')
                    plt.fill_between(d_list_rev,elev_list,base_reg,alpha=0.1)
                    plt.text(d_list_rev[0],elev_list[0],"P1")
                    plt.text(d_list_rev[-1],elev_list[-1],"P2")
                    plt.xlabel("Distance(km)")
                    plt.ylabel("Elevation(m)")
                    plt.grid()
                    plt.legend(fontsize='small')
                    plt.show()
                except Exception as e:
                    print(str(e))

在尝试批量处理大量数据时,有人可以建议我如何有效地查询远程API吗?我也很抱歉,如果我错过了一些基本的知识,或者我想以尽可能低效的方式来解决这个问题-我是Python的新手,而且一般来说都是编码的,所以我想边学习边学习。

1 个答案:

答案 0 :(得分:1)

您的主要问题是对服务器的请求过多。您已经将坐标列表发送到'https://api.open-elevation.com/api/v1/lookup'。

我看到了增加请求数量的唯一方法。

  1. 将数据分组到一个请求中

  2. proxy中使用requests 您可以使用https://free-proxy-list.net/或类似网址中的免费代理。

import requests

proxies = {
  'http': 'http://10.10.1.10:3128',
  'https': 'http://10.10.1.10:1080',
}

requests.get('http://example.org', proxies=proxies)
  1. 使用两次请求之间的延迟。它有助于绕过DDoS防御
import time
time.sleep(5)