Python - pomoc - znajdowanie najmłodszych rekordów

0

Cześć, bardzo proszę o pomoc.

To wypluwa mój kod:
screenshot-20200922180508.png

Do jednego rekordu wypluwa mi kilka adresów url, a ja chciałbym tylko ten, który jest najmłodszy według aktulnosc lub aktualnosc rok.

Jakiś pomysl? Bede bardzo wdzięczny

1

Żadnego tekstu nie wkleja się jako zdjęcia/screenshota na forum!
bo:

  1. nikt nie będzie przepisywał kodu (albo robić OCR), żeby ci pomóc
  2. nie ma jak poprawić kodu
  3. nie da się wyszukiwać
  4. Niektórzy siedzą za firewall-em i mogą nie widzieć obrazków (szczególnie jeśli są na dziwnym serwerze)
  5. nie można sprawdzić, czy używasz jakiś dziwnych znaków
0

Jest jakiś regexp tylko nie wiadomo, co tam się właściwie maczuje.

8

title

1

Przepraszam bardzo za kłopot, już się poprawiam, przepraszam z całego serca.

Co chciałbym osiągnąć:

  1. Chciałbym aby pętla, która znajduję się na końcu dodawała wybrane matche do listy new_text. Niestety dodaje tylko tylko pierwszy, jestem pewny, że po prostu powinno to znajdować się w innym miejscu, bo z każdym requestem tworzy się nowa lista, a ja nie potrafię tego miejsca zlokalizować.
  2. Wybrane tzn, najmłodszy. Dla każdego rekordu, w tym przypadku dla 5, zwraca kilka adresów url, a ja chciałym tylko ten najmłodszy według 'aktualnosc' lub 'aktualnoscRok'.
  3. ' if row_num >5 : break # for testing, get first n rows' Ostatecznie będę to usuwał i kod będzie przechodził przez 101 tyś rekordów, chciałbym jakaś prostą logikę, która w momencie odmowy dostępu napiszę błąd i poczeka 10 sekund.

Bardzo proszę o pomoc i pozdrawiam!

# libraries
import re
import requests
import shapefile
import pandas as pd

#shapefile
shapefile_path = 'C:/Users/ja/PYTHON SPYDER/Python praca/shapefiles/PL1992_5000_025'

# wms
wms_request_base_url = 'https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMS/SkorowidzeWgAktualnosci'
wms_request_parameters = {
    'SERVICE': 'WMS',
    'request': 'GetFeatureInfo',
    'version': '1.3.0',
    'layers': 'SkorowidzeOrtofotomapyStarsze,SkorowidzeOrtofotomapy2018,SkorowidzeOrtofotomapy2019,SkorowidzeOrtofotomapy2020',
    'styles': '',
    'crs': 'EPSG:2180',
    'width': 1000,
    'height': 1000,
    'format': 'image/png',
    'transparent': 'true',
    'query_layers': 'SkorowidzeOrtofotomapyStarsze,SkorowidzeOrtofotomapy2018,SkorowidzeOrtofotomapy2019,SkorowidzeOrtofotomapy2020',
    'i': 1,
    'j': 1,
    'INFO_FORMAT': 'text/html'
}
regexp = '{url:"(.+)",godlo:"(.+)", aktualnosc:"(.+)", wielkoscPiksela:"(.+)", ukladWspolrzednych:"(.+)", calyArkuszWyeplnionyTrescia:"(.+)", modulArchiwizacji:"(.+)", zrodloDanych:"(.+)", kolor:"(.+)", numerZgloszeniaPracy:"(.+)", aktualnoscRok:"(.+)"}'
compiled_regexp = re.compile(regexp, re.IGNORECASE)
attribute_names = [
    'url',
    'godlo',
    'aktualnosc',
    'wielkoscPiksela',
    'ukladWspolrzednych',
    'calyArkuszWyeplnionyTrescia',
    'modulArchiwizacji',
    'zrodloDanych',
    'kolor',
    'numerZgloszeniaPracy',
    'aktualnoscRok'
]

if __name__ == '__main__':

    # open shape file
    with shapefile.Reader(shapefile_path) as shp:
        total_rows = shp.numRecords

        # for each record in the shapefile (we are ignoring geometry here)
        for row_num, row in enumerate(shp.iterRecords()):
            # -----------------------------------------------------
            # remove before production use:
            if row_num >5 : break  # for testing, get first n rows
            # -----------------------------------------------------

            # get row as dict so we have attribute names
            r = row.as_dict()

            # create bounding box
            minx = min(r['x1'], r['x2'], r['x3'], r['x4'])
            miny = min(r['y1'], r['y2'], r['y3'], r['y4'])
            maxx = max(r['x1'], r['x2'], r['x3'], r['x4'])
            maxy = max(r['y1'], r['y2'], r['y3'], r['y4'])
            bbox = [minx, miny, maxx, maxy]
            # create comma separated string representation of bbox that we will use for the HTTP request to WMS service
            bbox_str = ','.join([str(el) for el in bbox])
            wms_request_parameters['bbox'] = bbox_str

            print(f'{str(row_num+1).zfill(6)}/{total_rows}', '- godło:', r['godlo'], '- bbox:', bbox)

            # make the HTTP request
            new_text = [] 
            response = requests.get(wms_request_base_url, params=wms_request_parameters)      
            if response.ok:
                # construct dictionary with data parsed from http response using regular expressions
                for matches in compiled_regexp.findall(response.text):
                    record = {name: value for name, value in zip(attribute_names, matches)}
                    new_text.append(record)
             
                    
print(new_text)
# table = pd.DataFrame(text)
# table.to_excel(r'C:/Users/ja/linki.xlsx', index = True)
                        
                        



    
        
                    
           
                    
                    
                    
                    
                    
                    
                    
                    
                    

1

Człowieku, dostajesz w odpowiedzi JSona, więc ten regexp jest zagrożeniem dla zdrowia psychicznego.

            response = requests.get(wms_request_base_url, params=wms_request_parameters)      
            if response.ok:
                json = response.json()
                new_text = new_text + json

Dobra rada naucz się dzielić kod na funkcje, będzie większa szansa zrozumienia co twój kod robi/ma robić. Nie masz ani jednej!

0

^ nie używaj regexa do parsowania jsona. Jeżeli dostajesz xml to tym bardziej, sparsuj xml istniejącymi bibliotekami.

Co do pytań:

  1. Inicjalizujesz new_text w 73 linijce więc przy każdej iteracji inicjalizujesz na nowo. Jak chcesz zachować wyniki to wyniesć inicjalizację przed for loopem.
  2. Jak wygląda pełna odpowiedź? Wklej jsona/xml. Ale powinno to być proste jeżeli sparsujesz do struktur - wybrać po prostu strukturę wedle założonego parametru.
  3. Jak w poście @MarekR22 , jeżeli nie masz response.ok to dodaj logikę jaką chcesz (jak sleep). Jeżeli API, z którego korzystasz ma ograniczenia np. ilość requestów na godzinę dobrze byłoby uwzględnić to w kodzie. Są do tego gotowe biblioteki jak ratelimit .

Edit bo spojrzałem na screen w pierwszym poście, i widzę że w odpowiedzi dostajesz listę dictów z urlami. Rozszerzając 2. odpowiedź na przykładzie:

resp = [{'url': '1', 'aktualnosc': '2019/08/31'}, {'url': '2', 'aktualnosc': '2019/10/2'}, {'url': '3', 'aktualnosc': '2020/01/14'}]
recent = max(resp, key=lambda x: x['aktualnosc'])

Datę powinno raczej się parsować do obiektu datetime i na tej podstawie porównywać ale dzięki formatowi rok/miesiąc/dzień porównanie stringa powinno też zadziałać. Przy wielu rekordach i różnych operacjach pomocna może też być biblioteka pandas.

1 użytkowników online, w tym zalogowanych: 0, gości: 1