Как оптимизировать вызовы API для большого набора данных, используя Python? - PullRequest
2 голосов
/ 14 февраля 2020

Цель : отправить список адресов в API и извлечь определенную информацию (например, флаг, который указывает, находится ли адрес в зоне затопления или нет).

Solution : рабочий скрипт Python для небольших данных.

Проблема : я хочу оптимизировать свое текущее решение для больших входных данных. Как улучшить производительность вызовов API. Если у меня будет 100 000 адресов, мое текущее решение потерпит неудачу? Это замедлит HTTP-вызовы? Получу ли я время запроса? Выдерживает ли API количество вызовов API?

  • Ввод: список адресов

Пример ввода

777 Brockton Avenue, Abington MA 2351

30 Memorial Drive, Avon MA 2322

Мое текущее решение хорошо работает для небольшого набора данных.

# Creating a function to get lat & long of the existing adress and then detecting the zone in fema
def zonedetect(addrs):
    global geolocate
    geocode_result = geocode(address=addrs, as_featureset=True)
    latitude = geocode_result.features[0].geometry.x
    longitude = geocode_result.features[0].geometry.y
    url = "https://hazards.fema.gov/gis/nfhl/rest/services/public/NFHL/MapServer/28/query?where=1%3D1&text=&objectIds=&time=&geometry="+str(latitude)+"%2C"+str(longitude)+"&geometryType=esriGeometryPoint&inSR=4326&spatialRel=esriSpatialRelIntersects&relationParam=&outFields=*&returnGeometry=true&returnTrueCurves=false&maxAllowableOffset=&geometryPrecision=&outSR=&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&returnDistinctValues=false&resultOffset=&resultRecordCount=&queryByDistance=&returnExtentsOnly=false&datumTransformation=&parameterValues=&rangeValues=&f=json"
    response = req.get(url)
    parsed_data = json.loads(response.text)
    formatted_data = json_normalize(parsed_data["features"])
    formatted_data["Address_1"] = addrs

    #Exception handling
    if response.status_code == 200:
        geolocate = geolocate.append(formatted_data, ignore_index = True)
    else: 
        print("Request to {} failed".format(postcode))

# Reading every adress from existing dataframe
for i in range(len(df.index)):
    zonedetect(df["Address"][i])

Вместо использования для l oop выше есть альтернатива. Могу ли я обработать этот лог c в пакете?

1 Ответ

1 голос
/ 14 февраля 2020

Отправка 100 000 запросов на сервер hazards.fema.gov определенно вызовет некоторые замедления на их сервере, но это в основном повлияет на ваш сценарий, так как вам нужно будет ждать, пока каждый отдельный запрос HTTP будет поставлен в очередь и получит ответ, что может занять очень много времени. долго обрабатывать.

Что было бы лучше, это отправить один запрос REST для всего, что вам нужно, а затем обработать лог c. Глядя на REST API, вы обнаружите, что параметр URL geometry может принимать geometryMultiPoint из документов . Вот пример мультипункта:

{
  "points" : [[-97.06138,32.837],[-97.06133,32.836],[-97.06124,32.834],[-97.06127,32.832]],
  "spatialReference" : {"wkid" : 4326}
}

Итак, вы можете создать объект для хранения всех точек, которые вы хотите запросить:

multipoint = { points: [], spatialReference: { wkid: 4326}

И когда вы oop, добавьте точку широты / долготы в список многоточечности:

for i in range(len(df.index)):
    address = df["Address"][i]
    geocode_result = geocode(address=addrs, as_featureset=True)
    latitude = geocode_result.features[0].geometry.x
    longitude = geocode_result.features[0].geometry.y
    multiPoint.points.append([latitude, longitude])

Затем вы можете установить многоточечность как geometry в вашем запросе, что приведет к одному запросу API вместо одного для каждой точки. .

...