Фильтрация записи по стороннему API отдыха - PullRequest
0 голосов
/ 20 января 2019

Я должен выполнить поиск по миллионам записей. Для этого у меня есть спокойный сервис (сторонний API), который выдает 25 записей за каждый отдельный вызов. В каждом ответе я получаю массив из 25 записей, номер страницы и общее количество страниц, т. Е. Если я задаю pagenumber = 2, то будут приходить следующие 25 записей. номер, сделайте вызов для каждого pageNumber и добавьте запись в каждом вызове в предыдущей коллекции. Ограничение - после 100 вызовов / минута сервер (третье лицо) начинает отклонять вызовы. И поэтому я никогда не получаю полные данные и в конечном итоге не выполняю требуемый поиск.

Я попытался перебрать все страницы. Я попробовал свои силы в упругом поиске, но, думаю, у меня не хватило понимания для его реализации.

public class EmpResponse
{
 public int Pages;
 public int PageNumber;
 public List<Employee> TotalRecords; 

    public Employee GetAllEmployees(string empId= "", string EmpName = "", string Manager = "")
    {
        string url = "thirdPartyurl?PageNumber=";
        string baseUrl = "thirdPartyurl?PageNumber=1";
        EmpResponse baseRes = JsonConvert.DeserializeObject<EmpResponse>(DataHelpers.GetDataFromUrl(baseUrl));
        for (int i = 2; i <= baseRes.Pages; i++)
        {
            EmpResponse currentRes = JsonConvert.DeserializeObject<EmpResponse>(DataHelpers.GetDataFromUrl(url + i));
            if (currentRes != null)
                foreach (var item in currentRes.TotalRecords)
                {
                    baseRes.TotalRecords.Add(item);
                }
        }
        return baseRes;
    }

}

DataHelpers.GetDataFromUrl используется для вызова URL-адреса и для получения ответа, отдельного для этого URL-адреса.

теперь baseRes.Pages получается равным 100000 (т.е. baseRes.Pages = 100000), что означает 100000 страниц, что означает 100000 вызовов. Это занимает очень много времени, и если количество вызовов превышает 100 в минуту, сторонний API начинает отклонять вызов. Так как получить все данные с этим ограничением и быстро.

1 Ответ

0 голосов
/ 21 января 2019

Если попытаться решить вашу проблему с помощью техники массовой загрузки.Вот что я сделал :) Интересная часть - это часть Python, потому что веб-сервер golang - это только ограниченный сервис третьих сторон:)

Наш HTTP-сервер, который обрабатывает все запросы ...

main.go

package main

import (
    "fmt"
    "io"
    "math/rand"
    "net/http"
    "time"
)

const (
    letterBytes   = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    letterIdxBits = 6                    // 6 bits to represent a letter index
    letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
    letterIdxMax  = 63 / letterIdxBits   // # of letter indices fitting in 63 bits
)

var (
    src = rand.NewSource(time.Now().UnixNano())
)

func generateData() string {
    b := make([]byte, 64)
    for i, cache, remain := 63, src.Int63(), letterIdxMax; i >= 0; {
        if remain == 0 {
            cache, remain = src.Int63(), letterIdxMax
        }
        if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
            b[i] = letterBytes[idx]
            i--
        }
        cache >>= letterIdxBits
        remain--
    }

    return string(b)
}

func main() {
    apiKeys := make(map[string]int)

    apiKeys["abc"] = 0

    // run api clear
    ticker := time.NewTicker(5 * time.Second)
    quit := make(chan struct{})
    go func() {
        for {
            select {
            case <-ticker.C:
                apiKeys["abc"] = 0
            case <-quit:
                ticker.Stop()
                return
            }
        }
    }()

    fmt.Printf("Loading basic http server\r\n")
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Printf("Got request: %s\r\n", r.URL.Query())

        // check api key
        if _, ok := apiKeys[r.URL.Query().Get("api")]; !ok {
            w.WriteHeader(http.StatusBadRequest)
            return
        }

        // check limitation
        if apiKeys[r.URL.Query().Get("api")] >= 100 {
            w.WriteHeader(http.StatusForbidden)
            return
        }

        // get page number & generate data...
        data := generateData()

        io.WriteString(w, data)

        // save request
        apiKeys[r.URL.Query().Get("api")] = apiKeys[r.URL.Query().Get("api")] + 1

        w.WriteHeader(http.StatusOK)
        return
    })

    http.ListenAndServe(":1337", nil)
}

Наш запросчик main.py

import requests
import time
"""
load data
"""

thirdPartyUrl = "http://localhost:1337/?api=abc"

def main():
    print("Loading program...")
    allPages = 100000
    currentPage = 0
    alreadyVisited = 0
    r = requests.session()
    res = r.get("{0}&PageNumber={1}".format(thirdPartyUrl, currentPage))

    if res.status_code == 200:
        print("Everything fine! Go and get other content...")
        while alreadyVisited <= allPages:
            if currentPage >= 99:
                time.sleep(6)
                currentPage = 0

            currentPage = currentPage + 1
            alreadyVisited = alreadyVisited + 1
            print("CurrentPage: {0} | Already visited: {1}".format(currentPage, alreadyVisited))

            data = r.get("{0}&PageNumber={1}".format(thirdPartyUrl, currentPage))
            print("Data: {0}".format(data.content))


main()

Это всего лишь прототип:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...