【问题标题】:Looping requests using urllib使用 urllib 循环请求
【发布时间】:2019-06-28 13:46:32
【问题描述】:

寻求有关使用 urllib 向在线 api 发送多个循环请求的帮助。

我目前正在编写一些 python 脚本,以帮助我们识别雷达和拟议的风力涡轮机开发之间的潜在视线问题。

最后一个难题是创建海拔剖面,以便我们可以快速评估哪些涡轮机可能存在问题,哪些不是。我一直在尝试操纵找到的现有代码 here 来询问我已注册并拥有密钥的 OpenElevation API。

以前我曾尝试将从 GIS 软件中提取的高程数据解析为 .xyz 文件。然而,这很耗时,并且提取的高程只能精确到小数点后 3 位。

代码从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 和一般编码的新手,所以我正在努力学习。

【问题讨论】:

    标签: python urllib


    【解决方案1】:

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

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

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

    2. requests 中使用proxy 您可以使用来自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)
    

    【讨论】:

    • 这是个好建议。生病阅读如何对请求和代理进行分组,我会告诉你我的进展情况!
    • 成功了,谢谢。从其他用户看来,API 服务器几乎被请求淹没,这解释了为什么我经常返回 5xx 错误。
    • 我很高兴听到它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    • 2018-12-21
    • 2018-01-31
    相关资源
    最近更新 更多